mirror of
https://github.com/Ichinga-Samuel/aiomql.git
synced 2026-07-27 20:27:43 +00:00
add testdata class
This commit is contained in:
@@ -4,7 +4,7 @@ from .constants import BookType, TradeAction, OrderType, OrderTime, OrderFilling
|
||||
DealReason, SymbolChartMode, SymbolTradeMode, SymbolCalcMode, SymbolOptionMode, SymbolOrderGTCMode, \
|
||||
SymbolOptionRight, \
|
||||
SymbolTradeExecution, SymbolSwapMode, DayOfWeek, AccountTradeMode, AccountStopOutMode, AccountMarginMode, \
|
||||
OrderReason
|
||||
OrderReason, TickFlag
|
||||
|
||||
from .base import Base
|
||||
|
||||
@@ -334,9 +334,9 @@ class SymbolInfo(Base):
|
||||
path: str
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
if 'name' not in kwargs:
|
||||
if name := kwargs.pop('name', None):
|
||||
raise AttributeError('Symbol Object Must be initialized with a name')
|
||||
self.name = kwargs.pop('name')
|
||||
self.name = name
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
@@ -351,6 +351,28 @@ class SymbolInfo(Base):
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
class TickInfo(Base):
|
||||
"""Price Tick of a Financial Instrument.
|
||||
|
||||
Attributes:
|
||||
time (int): Time of the last prices update for the symbol
|
||||
bid (float): Current Bid price
|
||||
ask (float): Current Ask price
|
||||
last (float): Price of the last deal (Last)
|
||||
volume (float): Volume for the current Last price
|
||||
time_msc (int): Time of the last prices update for the symbol in milliseconds
|
||||
flags (TickFlag): Tick flags
|
||||
volume_real (float): Volume for the current Last price
|
||||
Index (int): Custom attribute representing the position of the tick in a sequence.
|
||||
"""
|
||||
time: float
|
||||
bid: float
|
||||
ask: float
|
||||
last: float
|
||||
volume: float
|
||||
time_msc: float
|
||||
flags: TickFlag
|
||||
volume_real: float
|
||||
|
||||
class BookInfo(Base):
|
||||
"""Book Information Class.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import TypeDict
|
||||
import pickle
|
||||
import random
|
||||
import lzma
|
||||
from datetime import datetime
|
||||
from logging import getLogger
|
||||
import asyncio
|
||||
@@ -7,21 +8,31 @@ import asyncio
|
||||
import pytz
|
||||
from MetaTrader5 import Tick, SymbolInfo
|
||||
import pandas as pd
|
||||
from pandas import DataFrame
|
||||
|
||||
from ...core.meta_trader import MetaTrader
|
||||
from ...core.config import Config
|
||||
from ...core.errors import Error
|
||||
from ...core.constants import TimeFrame, CopyTicks, OrderType
|
||||
from ...core.models import (AccountInfo, SymbolInfo, BookInfo, TradeOrder, OrderCheckResult, OrderSendResult,
|
||||
TradePosition, TradeDeal)
|
||||
TradePosition, TradeDeal, TickInfo)
|
||||
from ...utils import backoff_decorator
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
class Data(TypeDict):
|
||||
account: AccountInfo
|
||||
symbols: dict[str, SymbolInfo]
|
||||
prices: DataFrame
|
||||
ticks: DataFrame
|
||||
rates: DataFrame
|
||||
span: range
|
||||
|
||||
|
||||
class GetData(MetaTrader):
|
||||
config: Config = Config()
|
||||
|
||||
def __init__(self, start: datetime, end: datetime, timeframes: set[TimeFrame], symbols: set[str],
|
||||
def __init__(self, *, start: datetime, end: datetime, timeframes: set[TimeFrame], symbols: set[str],
|
||||
interval: int = 60, name: str = '', tz: str = 'Etc/UTC'):
|
||||
""""""
|
||||
super().__init__()
|
||||
@@ -37,7 +48,7 @@ class GetData(MetaTrader):
|
||||
self.span = range(start := int(self.start.timestamp()), diff + start)
|
||||
self.mt5 = MetaTrader()
|
||||
|
||||
async def get_test_data(self) -> dict:
|
||||
async def get_data(self) -> Data:
|
||||
""""""
|
||||
data = {}
|
||||
rates, ticks, prices = await asyncio.gather(self.get_symbols_rates(), self.get_symbols_ticks(),
|
||||
@@ -48,43 +59,55 @@ class GetData(MetaTrader):
|
||||
data['prices'] = prices
|
||||
data['symbols'] = await self.get_symbols_info()
|
||||
data['account'] = self.get_account_info()
|
||||
data['range'] = self.span
|
||||
|
||||
return data
|
||||
|
||||
async def get_and_save_data(self) -> None:
|
||||
async def pickle_data(self) -> None:
|
||||
""""""
|
||||
data = await self.get_test_data()
|
||||
data = await self.get_data()
|
||||
fh = open(f'{self.config.root}/data/{self.name}', 'wb')
|
||||
pickle.dump(data, fh)
|
||||
fh.close()
|
||||
|
||||
def load_data(self, name: str = '') -> dict:
|
||||
|
||||
async def compress_data(self):
|
||||
""""""
|
||||
name = name or self.name
|
||||
file = open(f'{self.config.root}/data/{name}', 'rb')
|
||||
data = pickle.load(file)
|
||||
file.close()
|
||||
data = await self.get_data()
|
||||
bdata = pickle.dumps(data)
|
||||
name = self.name + 'xz'
|
||||
with lzma.open(name, 'w') as fh:
|
||||
fh.write(bdata)
|
||||
|
||||
@classmethod
|
||||
def load_data(cls, name: str, compressed=False) -> dict:
|
||||
""""""
|
||||
fo = open(f'{cls.config.root}/data/{name}', 'rb')
|
||||
|
||||
if compressed:
|
||||
data = lzma.decompress(fo)
|
||||
data = pickle.load(data)
|
||||
fo.close()
|
||||
return data
|
||||
|
||||
async def get_symbols_info(self):
|
||||
async def get_symbols_info(self) -> dict[str, SymbolInfo]:
|
||||
""""""
|
||||
tasks = [self.get_symbol_info(symbol) for symbol in self.symbols]
|
||||
res = await asyncio.gather(*tasks)
|
||||
return {symbol: info for symbol, info in res}
|
||||
return {symbol: SymbolInfo(**info) for symbol, info in res}
|
||||
|
||||
async def get_symbols_ticks(self):
|
||||
async def get_symbols_ticks(self) -> dict[str, DataFrame]:
|
||||
""""""
|
||||
tasks = [self.get_symbol_ticks(symbol) for symbol in self.symbols]
|
||||
res = await asyncio.gather(*tasks)
|
||||
return {symbol: ticks for symbol, ticks in res}
|
||||
return {symbol: tick for symbol, tick in res}
|
||||
|
||||
async def get_symbols_prices(self):
|
||||
async def get_symbols_prices(self) -> dict[str, DataFrame]:
|
||||
""""""
|
||||
tasks = [self.get_symbol_prices(symbol) for symbol in self.symbols]
|
||||
res = await asyncio.gather(*tasks)
|
||||
return {symbol: prices for symbol, prices in res}
|
||||
|
||||
async def get_symbols_rates(self):
|
||||
async def get_symbols_rates(self) -> dict[str: dict[TimeFrame: DataFrame]]:
|
||||
""""""
|
||||
tasks = [self.get_symbol_rates(symbol, timeframe) for symbol in self.symbols for timeframe in self.timeframes]
|
||||
res = await asyncio.gather(*tasks)
|
||||
@@ -94,19 +117,19 @@ class GetData(MetaTrader):
|
||||
return data
|
||||
|
||||
@backoff_decorator(max_retries=5)
|
||||
async def get_account_info(self) -> AccountInfo | None:
|
||||
async def get_account_info(self) -> dict:
|
||||
""""""
|
||||
res = await self.mt5.account_info()
|
||||
return res._asdict()
|
||||
|
||||
@backoff_decorator(max_retries=5)
|
||||
async def get_symbol_info(self, symbol: str):
|
||||
async def get_symbol_info(self, symbol: str) -> tuple[str, dict]:
|
||||
""""""
|
||||
res = await self.mt5.symbol_info(symbol)
|
||||
return symbol, res._asdict()
|
||||
|
||||
@backoff_decorator(max_retries=5)
|
||||
async def get_symbol_ticks(self, symbol: str):
|
||||
async def get_symbol_ticks(self, symbol: str) -> tuple[str, DataFrame]:
|
||||
""""""
|
||||
res = await self.mt5.copy_ticks_range(symbol, self.start, self.end, CopyTicks.ALL)
|
||||
res = pd.DataFrame(res)
|
||||
@@ -115,7 +138,7 @@ class GetData(MetaTrader):
|
||||
return symbol, res
|
||||
|
||||
@backoff_decorator(max_retries=5)
|
||||
async def get_symbol_prices(self, symbol: str):
|
||||
async def get_symbol_prices(self, symbol: str) -> tuple[str, DataFrame]:
|
||||
""""""
|
||||
res = await self.mt5.copy_ticks_range(symbol, self.start, self.end, CopyTicks.ALL)
|
||||
res = pd.DataFrame(res)
|
||||
@@ -125,7 +148,7 @@ class GetData(MetaTrader):
|
||||
return symbol, res
|
||||
|
||||
@backoff_decorator(max_retries=5)
|
||||
async def get_symbol_rates(self, symbol: str, timeframe: TimeFrame):
|
||||
async def get_symbol_rates(self, symbol: str, timeframe: TimeFrame) -> tuple[str, TimeFrame, DataFrame]:
|
||||
""""""
|
||||
res = await self.mt5.copy_rates_range(symbol, timeframe, self.start, self.end)
|
||||
res = pd.DataFrame(res)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
from typing import Literal
|
||||
from ...core.models import AccountInfo, SymbolInfo
|
||||
from typing import Literal, TypedDict
|
||||
from ...core.models import AccountInfo, SymbolInfo, Tick
|
||||
from ...core.constants import TimeFrame
|
||||
from ...core.meta_trader import MetaTrader
|
||||
# from ...account import Account
|
||||
from .get_data import Data, GetData
|
||||
|
||||
|
||||
class TestData:
|
||||
|
||||
def __init__(self, data):
|
||||
self._data = data
|
||||
def __init__(self, data: Data):
|
||||
self.data = data
|
||||
self.cursor = 0
|
||||
|
||||
def __getitem__(self, item: tuple[Literal['ticks', 'rates'], SymbolInfo, TimeFrame]):
|
||||
type_, symbol, time_frame = item
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Tick:
|
||||
last: float
|
||||
volume: float
|
||||
time_msc: float
|
||||
flags: float
|
||||
flags: TickFlag
|
||||
volume_real: float
|
||||
Index: int
|
||||
|
||||
|
||||
@@ -60,4 +60,5 @@ def backoff_decorator(func=None, *, max_retries: int = 3, retries: int = 0, dela
|
||||
delay += 1
|
||||
retries += 1
|
||||
return await wrapper(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
Reference in New Issue
Block a user