This commit is contained in:
Ichinga Samuel
2024-08-27 05:57:07 +01:00
parent 3b62e145a7
commit a972a06da8
11 changed files with 249 additions and 58 deletions
+155 -9
View File
@@ -2,20 +2,166 @@
"cells": [
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"id": "f4500c8d-0e58-4d3f-8dd3-06a4896f397f",
"metadata": {},
"outputs": [],
"source": [
"import shelve\n",
"import pickle\n",
"import zlib\n",
"import lzma\n",
"import pytz\n",
"# import shelve\n",
"# import pickle\n",
"# import zlib\n",
"# import lzma\n",
"# import pytz\n",
"from datetime import datetime, timedelta\n",
"from aiomql import MetaTrader, MetaTester, TimeFrame, TestData, AccountInfo, TimeFrame, CopyTicks, Account, GetData\n",
"# from MetaTrader5 import SymbolInfo\n",
"import pandas as pd"
"from aiomql import MetaTrader, TimeFrame, AccountInfo, TimeFrame, CopyTicks, Account, Symbol\n",
"from MetaTrader5 import SymbolInfo\n",
"import pandas as pd\n",
"from pandas import DataFrame\n",
"import pytz"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f2ef126c-6edc-4651-8a81-06bb97eed6f9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"source": [
"res = await Account().sign_in()\n",
"print(res)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "2c598a85-1e90-49b0-abf1-87329597feae",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tz = pytz.timezone('Etc/UTC')\n",
"sym = Symbol(name='EURUSD')\n",
"start = datetime(day=22, month=8, year=2024, tzinfo=tz)\n",
"end = datetime(day=26, month=8, year=2024, hour=12, tzinfo=tz)\n",
"# rates = await sym.mt5.copy_rates_from(symbol='EURUSD', date_from=end, count=5, timeframe=TimeFrame.H12)\n",
"rates = await sym.mt5.copy_rates_from_pos(symbol='EURUSD', start_pos=0, count=5, timeframe=TimeFrame.H12)\n",
"df = DataFrame(rates)\n",
"df['time'] = pd.to_datetime(df['time'], unit='s')\n",
"df.index[-1]"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "0a7d319c-5760-4058-994f-27e8d10df108",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>time</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>tick_volume</th>\n",
" <th>spread</th>\n",
" <th>real_volume</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2024-08-25 12:00:00</td>\n",
" <td>1.11869</td>\n",
" <td>1.11947</td>\n",
" <td>1.11849</td>\n",
" <td>1.11894</td>\n",
" <td>4570</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2024-08-26 00:00:00</td>\n",
" <td>1.11894</td>\n",
" <td>1.12016</td>\n",
" <td>1.11628</td>\n",
" <td>1.11652</td>\n",
" <td>43583</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2024-08-26 12:00:00</td>\n",
" <td>1.11652</td>\n",
" <td>1.11790</td>\n",
" <td>1.11501</td>\n",
" <td>1.11618</td>\n",
" <td>45034</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" time open high low close tick_volume \\\n",
"2 2024-08-25 12:00:00 1.11869 1.11947 1.11849 1.11894 4570 \n",
"3 2024-08-26 00:00:00 1.11894 1.12016 1.11628 1.11652 43583 \n",
"4 2024-08-26 12:00:00 1.11652 1.11790 1.11501 1.11618 45034 \n",
"\n",
" spread real_volume \n",
"2 1 0 \n",
"3 0 0 \n",
"4 0 0 "
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc[2:6]"
]
},
{
@@ -20,12 +20,13 @@ from ...utils import backoff_decorator
logger = getLogger(__name__)
class Data(TypedDict):
account: AccountInfo
symbols: dict[str, SymbolInfo]
prices: DataFrame
ticks: DataFrame
rates: DataFrame
prices: dict[str, DataFrame]
ticks: dict[str, DataFrame]
rates: dict[str, dict[str, DataFrame]]
interval: range
+82
View File
@@ -0,0 +1,82 @@
from datetime import datetime, tzinfo
import pytz
import numpy as np
import pandas as pd
from pandas import DataFrame
from MetaTrader5 import Tick, SymbolInfo, AccountInfo
from ..constants import TimeFrame, CopyTicks
from .get_data import Data, GetData
from ...utils import round_down, round_up
tz = pytz.timezone('Etc/UTC')
class TestData:
def __init__(self, data: Data):
self._data = data
self.account = data['account']
self.symbols = data['symbols']
self.prices = data['prices']
self.ticks = data['ticks']
self.rates = data['rates']
self.interval = data['interval']
self.cursor = 0
self.iter = iter(self.interval)
def __next__(self):
self.cursor = next(self.iter)
return self.cursor
def reset(self):
self.iter = iter(self.interval)
return self.iter
def get_symbols_total(self) -> int:
return len(self.symbols)
def get_symbols(self) -> list:
return list(self.symbols.keys())
def get_account_info(self) -> AccountInfo:
return AccountInfo(**self.account.dict)
def get_symbol_info_tick(self, symbol: str) -> Tick:
tick = self.prices[symbol].iloc[self.cursor]
return Tick(**tick)
def get_symbol_info(self, symbol: str) -> SymbolInfo:
info = self.symbols[symbol]
tick = self.get_symbol_info_tick(symbol)
info = info.dict
info |= {'bid': tick.bid, 'bidhigh': tick.bid, 'bidlow': tick.bid, 'ask': tick.ask,
'askhigh': tick.ask, 'asklow': tick.bid, 'last': tick.last, 'volume_real': tick.volume_real}
return SymbolInfo(**info)
def get_rates_from(self, symbol: str, timeframe: TimeFrame, date_from: datetime | float, count: int) -> np.ndarray:
rates = self.rates[symbol][timeframe.name]
start = int(datetime.timestamp(date_from)) if isinstance(date_from, datetime) else int(date_from)
start = round_down(start, timeframe.time)
start = rates.index.get_loc(start)
end = start + count
return rates.iloc[start:end].to_numpy()
def get_rates_from_pos(self, symbol: str, timeframe: TimeFrame, start_pos: int, count: int) -> np.ndarray:
rates = self.rates[symbol][timeframe.name]
end = -start_pos + count
return rates.iloc[-start_pos:end].to_numpy()
def get_rates_range(self, symbol: str, timeframe: TimeFrame, date_from: datetime, date_to: datetime) -> np.ndarray:
rates = self.rates[symbol][timeframe.name]
start = int(datetime.timestamp(date_from))
start = round_down(start, timeframe.time)
end = round_up(int(datetime.timestamp(date_to)), timeframe.time)
return rates.loc[start:end].to_numpy()
def get_ticks_from(self, symbol: str, date_from: datetime | float, count: int, flags: CopyTicks) -> DataFrame:
ticks = self.ticks[symbol]
start = int(datetime.timestamp(date_from)) if isinstance(date_from, datetime) else int(date_from)
start = round_down(start, 1)
end = start + count
return ticks.loc[start:end]
+1 -1
View File
@@ -334,7 +334,7 @@ class SymbolInfo(Base):
path: str
def __init__(self, **kwargs):
if name := kwargs.pop('name', None):
if name := kwargs.pop('name', None) is None:
raise AttributeError('Symbol Object Must be initialized with a name')
self.name = name
super().__init__(**kwargs)
-1
View File
@@ -1,4 +1,3 @@
from .strategies import *
from .traders import *
from .symbols import *
from .backtester import *
-44
View File
@@ -1,44 +0,0 @@
from ...core.models import AccountInfo, SymbolInfo, TickInfo
from .get_data import Data, GetData
from MetaTrader5 import Tick, SymbolInfo
class TestData:
def __init__(self, data: Data):
self._data = data
self.account = data['account']
self.symbols = data['symbols']
self.prices = data['prices']
self.ticks = data['ticks']
self.rates = data['rates']
self.interval = data['interval']
self.cursor = 0
self.iter = iter(self.interval)
def __next__(self):
self.cursor = next(self.iter)
return self.cursor
def reset(self):
self.iter = iter(self.interval)
return self.iter
def get_symbol_info_tick(self, symbol: str) -> Tick:
tick = self.prices[symbol].iloc[self.cursor]
return Tick(**tick)
def get_symbol_info(self, symbol: str) -> SymbolInfo:
symbol = self.symbols[symbol]
symbol |= {'bid': tick.bid, 'bidhigh': tick.bid, 'bidlow': tick.bid, 'bid': tick.bid, 'bidhigh': tick.bid, 'bidlow': tick.bid}
symbol = SymbolInfo(**symbol)
tick = self.get_symbol_info_tick(symbol)
symbol.bid = tick.bid
symbol.bidhigh = 120.506
symbol.bidlow = tick.
ask=120.041
askhigh=120.526
asklow=118.828
symbol.update()
+7
View File
@@ -62,3 +62,10 @@ def backoff_decorator(func=None, *, max_retries: int = 3, retries: int = 0, dela
return await wrapper(*args, **kwargs)
return wrapper
def round_down(value: int, base: int) -> int:
return value if value % base == 0 else value - (value % base)
def round_up(value: int, base: int) -> int:
return value if value % base == 0 else value + base - (value % base)