mirror of
https://github.com/Ichinga-Samuel/aiomql.git
synced 2026-08-09 02:07:47 +00:00
testdata
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{"a": 5}{"af": 5}
|
||||
@@ -18,4 +18,4 @@ from .terminal import Terminal
|
||||
from .sessions import Session, Sessions
|
||||
from .utils import dict_to_string, round_off, backoff_decorator, error_handler, error_handler_sync, round_up, round_down
|
||||
from .lib import *
|
||||
from .contrib import *
|
||||
# from .contrib import *
|
||||
|
||||
@@ -1 +1 @@
|
||||
from .backtester import *
|
||||
# from .backtester import *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from .meta_tester import MetaTester
|
||||
from .test_data import TestData
|
||||
from .backtest_engine import BackTestEngine
|
||||
from .get_data import GetData
|
||||
from .test_strategy import TestStrategy
|
||||
from .event_manager import EventManager
|
||||
|
||||
+19
-23
@@ -1,16 +1,14 @@
|
||||
import asyncio
|
||||
from collections import namedtuple
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
from itertools import zip_longest
|
||||
import random
|
||||
import json
|
||||
from functools import cached_property
|
||||
from logging import getLogger
|
||||
|
||||
import pandas as pd
|
||||
import pytz
|
||||
import numpy as np
|
||||
from debugpy.common.timestamp import current
|
||||
from pandas import DataFrame
|
||||
from MetaTrader5 import (Tick, SymbolInfo, AccountInfo, TradeOrder, TradePosition, TradeDeal,
|
||||
TradeRequest, OrderCheckResult, OrderSendResult, TerminalInfo)
|
||||
@@ -18,18 +16,18 @@ from MetaTrader5 import (Tick, SymbolInfo, AccountInfo, TradeOrder, TradePositio
|
||||
from ...core.meta_trader import MetaTrader
|
||||
from ...core.constants import TimeFrame, CopyTicks, OrderType, TradeAction, AccountStopOutMode, PositionReason
|
||||
from ...core.config import Config
|
||||
from ...lib.strategies.finger_trap import logger
|
||||
from ...utils import round_down, round_up, error_handler, error_handler_sync, async_cache
|
||||
|
||||
from .get_data import Data, GetData
|
||||
from .get_data import Data, GetData, Cursor
|
||||
from .test_account import TestAccount
|
||||
from .types import PositionsManager, OrdersManager, DealsManager
|
||||
|
||||
tz = pytz.timezone('Etc/UTC')
|
||||
Cursor = namedtuple('Cursor', ['index', 'time'])
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class TestData:
|
||||
class BackTestEngine:
|
||||
mt5: MetaTrader = MetaTrader()
|
||||
span: range
|
||||
range: range
|
||||
@@ -45,8 +43,8 @@ class TestData:
|
||||
self.margins: dict[int, float] = {}
|
||||
self.config = Config(test_data=self)
|
||||
self.set_up(start=start, end=end, speed=speed)
|
||||
self.cursor: Cursor = self._data.cursor or Cursor(index=self.range.start, time=self.span.start)
|
||||
self._data.name = self._data.name or f"{datetime.fromtimestamp(self.span[0]):%d-%m-%y}_{datetime.fromtimestamp(self.span[-1]):%d-%m-%y}"
|
||||
self.fh = open(f'{self.config.test_data_dir}/data.json', 'a')
|
||||
|
||||
def set_up(self, start: float | datetime = 0, end: float | datetime = 0, speed: int = 1):
|
||||
span_start = (int(start.timestamp()) if isinstance(start, datetime) else int(start)) or self._data.span.start
|
||||
@@ -54,12 +52,14 @@ class TestData:
|
||||
self.span = range(span_start, span_end, speed)
|
||||
self.range = range(0, span_end - span_start, speed)
|
||||
self.iter = zip_longest(self.range, self.span)
|
||||
self.cursor: Cursor = Cursor(index=self.range.start, time=self.span.start)
|
||||
|
||||
def __next__(self) -> Cursor:
|
||||
index, time = next(self.iter)
|
||||
self.cursor = Cursor(index=index, time=time)
|
||||
return self.cursor
|
||||
try:
|
||||
index, time = next(self.iter)
|
||||
self.cursor = Cursor(index=index, time=time)
|
||||
return self.cursor
|
||||
except StopIteration:
|
||||
logger.warning('End of time')
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}()"
|
||||
@@ -70,15 +70,12 @@ class TestData:
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
def to_json(self, data):
|
||||
json.dump(data, self.fh)
|
||||
|
||||
def reset(self):
|
||||
self.iter = zip_longest(self.range, self.span)
|
||||
self.cursor = Cursor(index=self.range.start, time=self.span.start)
|
||||
|
||||
def go_to(self, time: datetime | int):
|
||||
def go_to(self, *, time: datetime | int):
|
||||
time = int(time.timestamp()) if isinstance(time, datetime) else int(time)
|
||||
steps = time - self.cursor.time
|
||||
|
||||
@@ -92,7 +89,7 @@ class TestData:
|
||||
self.iter = zip_longest(range_, span)
|
||||
self.cursor = Cursor(index=range_.start, time=span.start)
|
||||
|
||||
def fast_forward(self, steps: int):
|
||||
def fast_forward(self, *, steps: int):
|
||||
for _ in range(steps):
|
||||
self.next()
|
||||
|
||||
@@ -108,7 +105,6 @@ class TestData:
|
||||
self.update_account(profit=profit)
|
||||
|
||||
def save(self):
|
||||
self.fh.close()
|
||||
try:
|
||||
if len(self.orders) or len(self.deals):
|
||||
for symbol in self.orders:
|
||||
@@ -243,7 +239,7 @@ class TestData:
|
||||
osr = {'retcode': 10013, 'comment': 'Invalid request',
|
||||
'request': TradeRequest(request.get(k, (0 if k != 'comment' else '')) for k in
|
||||
TradeRequest.__match_args__)}
|
||||
trade_order = {'ticket': order_ticket, **{k: v for k, v in request.items() if k in TradeOrder.__match_args__}}
|
||||
trade_order = {k: v for k, v in request.items() if k in TradeOrder.__match_args__}
|
||||
current_tick = await self.get_price_tick(request.get('symbol'), self.cursor.time)
|
||||
if current_tick is None:
|
||||
osr['comment'] = 'Market is closed'
|
||||
@@ -297,7 +293,7 @@ class TestData:
|
||||
return OrderSendResult((osr.get(k, 0) for k in OrderSendResult.__match_args__))
|
||||
# self.to_json(osr) # ToDo: remove later
|
||||
# return OrderSendResult(osr)
|
||||
price = current_tick.ask if order_type == OrderType.BUY else current.tick.bid
|
||||
price = current_tick.ask if order_type == OrderType.BUY else current_tick.bid
|
||||
# ToDo: Cross check this values with actual values.
|
||||
position = {'comment': 'Position Opened', 'ticket': order_ticket, 'symbol': symbol, 'volume': volume,
|
||||
'price_open': price, 'price_current': price, 'type': order_type, 'profit': 0, 'reason': PositionReason.EXPERT,
|
||||
@@ -315,9 +311,9 @@ class TestData:
|
||||
|
||||
self.positions[order.ticket] = pos
|
||||
self.orders[order.ticket] = order
|
||||
osr.update({'order': order_ticket, 'price': price, 'volume': volume, 'bid': tick.bid,
|
||||
'ask': tick.ask, 'deal': deal_ticket})
|
||||
margin = await self.order_calc_margin(action, symbol, volume, price, use_)
|
||||
osr.update({'order': order_ticket, 'price': price, 'volume': volume, 'bid': current_tick.bid,
|
||||
'ask': current_tick.ask, 'deal': deal_ticket})
|
||||
margin = await self.order_calc_margin(action, symbol, volume, price)
|
||||
self.margins[order_ticket] = margin
|
||||
self.update_account(margin=margin)
|
||||
self.to_json(osr) # ToDo: remove later
|
||||
@@ -1,42 +1,21 @@
|
||||
from functools import cached_property
|
||||
class Data:
|
||||
from turtledemo.penrose import start
|
||||
|
||||
|
||||
class Tre:
|
||||
def __init__(self):
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
self.start = 0
|
||||
self.end = 3
|
||||
self.span = iter(range(self.start, self.end))
|
||||
|
||||
class TData:
|
||||
_a: int
|
||||
_b: int
|
||||
_dat: dict
|
||||
|
||||
def __init__(self):
|
||||
self._data = Data()
|
||||
|
||||
def __getattr__(self, item):
|
||||
if val := self.__annotations__.get(item):
|
||||
return getattr(self._data, item, val())
|
||||
|
||||
@property
|
||||
def a(self):
|
||||
return self._a
|
||||
|
||||
@a.setter
|
||||
def a(self, val):
|
||||
self._a = val
|
||||
|
||||
@property
|
||||
def dat(self):
|
||||
return self._dat
|
||||
|
||||
@dat.setter
|
||||
def dat(self, key, val):
|
||||
self._dat |= val
|
||||
|
||||
@dat.deleter
|
||||
def dat(self):
|
||||
self._dat = {}
|
||||
def __next__(self):
|
||||
try:
|
||||
next(self.span)
|
||||
except StopIteration:
|
||||
print('End of range')
|
||||
|
||||
|
||||
f = TData()
|
||||
# f.data = {'a': 1}
|
||||
print(f.a)
|
||||
r = Tre()
|
||||
next(r)
|
||||
next(r)
|
||||
next(r)
|
||||
next(r)
|
||||
|
||||
@@ -5,6 +5,7 @@ import lzma
|
||||
from datetime import datetime
|
||||
from logging import getLogger
|
||||
from typing import Sequence, ClassVar
|
||||
from collections import namedtuple
|
||||
|
||||
import pytz
|
||||
import pandas as pd
|
||||
@@ -21,11 +22,10 @@ logger = getLogger(__name__)
|
||||
from MetaTrader5 import TradePosition, TradeOrder, TradeDeal
|
||||
|
||||
tof = list(TradeOrder.__match_args__)
|
||||
tof.append('symbol')
|
||||
tpf = list(TradePosition.__match_args__)
|
||||
tpf.append('symbol')
|
||||
tdf = list(TradeDeal.__match_args__)
|
||||
tdf.append('symbol')
|
||||
|
||||
Cursor = namedtuple('Cursor', ['index', 'time'])
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -40,12 +40,12 @@ class Data:
|
||||
rates: dict[str, dict[str, DataFrame]] = field(default_factory=dict)
|
||||
span: range = range(0)
|
||||
range: range = range(0)
|
||||
history_orders: DataFrame = field(default_factory=lambda: DataFrame([], columns=tof))
|
||||
history_deals: DataFrame = field(default_factory=lambda: DataFrame([], columns=tdf))
|
||||
positions: dict[str, DataFrame] = field(default_factory=dict)
|
||||
orders: dict[str, DataFrame] = field(default_factory=dict)
|
||||
|
||||
_fields: list[ClassVar[str]] = field(default_factory=list)
|
||||
orders: dict[int, dict] = field(default_factory=lambda: {})
|
||||
deals: dict[int, dict] = field(default_factory=lambda: {})
|
||||
positions: dict[int, dict] = field(default_factory=lambda: {})
|
||||
active_orders: tuple[int, ...] = field(default_factory=lambda: ())
|
||||
open_positions: tuple[int, ...] = field(default_factory=lambda: ())
|
||||
cursor: Cursor = None
|
||||
|
||||
def __str__(self):
|
||||
return f"""
|
||||
@@ -68,7 +68,7 @@ class Data:
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
return self._fields or [name for f in fields(self) if (name := f.name) != '_fields']
|
||||
return [f.name for f in fields(self)]
|
||||
|
||||
|
||||
class GetData:
|
||||
|
||||
@@ -5,7 +5,7 @@ from numpy import ndarray
|
||||
from MetaTrader5 import (Tick, SymbolInfo, AccountInfo, TerminalInfo, TradeOrder, TradePosition, TradeDeal,
|
||||
OrderCheckResult, OrderSendResult)
|
||||
|
||||
from .test_data import TestData
|
||||
from .backtest_engine import BackTestEngine
|
||||
from .get_data import GetData
|
||||
|
||||
from ...core.meta_trader import MetaTrader
|
||||
@@ -18,17 +18,17 @@ logger = getLogger(__name__)
|
||||
class MetaTester(MetaTrader):
|
||||
"""A class for testing trading strategies in the MetaTrader 5 terminal. A subclass of MetaTrader."""
|
||||
|
||||
def __init__(self, test_data: TestData = None):
|
||||
def __init__(self, test_data: BackTestEngine = None):
|
||||
super().__init__()
|
||||
if test_data is not None:
|
||||
self.config.test_data = test_data
|
||||
|
||||
@property
|
||||
def test_data(self) -> TestData | None:
|
||||
def test_data(self) -> BackTestEngine | None:
|
||||
return self.config.test_data
|
||||
|
||||
@test_data.setter
|
||||
def test_data(self, value: TestData):
|
||||
def test_data(self, value: BackTestEngine):
|
||||
self.config.test_data = value
|
||||
|
||||
async def last_error(self) -> tuple[int, str]:
|
||||
@@ -47,7 +47,7 @@ class MetaTester(MetaTrader):
|
||||
name = f"{self.config.test_data_dir_name}/{test_data_file}"
|
||||
data = GetData.load_data(name=name, compressed=self.config.compress_test_data)
|
||||
if data is not None:
|
||||
self.test_data = TestData(data)
|
||||
self.test_data = BackTestEngine(data)
|
||||
success = True
|
||||
|
||||
except Exception as err:
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
from typing import Generic
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
from MetaTrader5 import TradePosition, TradeOrder, TradeDeal
|
||||
|
||||
from aiomql.utils import logger
|
||||
|
||||
TradeData = TypeVar('TradeData', bound=TradePosition | TradeOrder | TradeDeal)
|
||||
|
||||
class TradingData[Generic]:
|
||||
_data: dict[int, TradePosition | TradeOrder | TradeDeal]
|
||||
|
||||
class TradingData(Generic[TradeData]):
|
||||
_data: dict[int, TradeData]
|
||||
_open_items: set[int]
|
||||
|
||||
def __init__(self, open_items: set[int] = None, data: dict = None):
|
||||
self._data = data or {}
|
||||
self._open_items = open_items or {trade.ticket for trade in self._data.values()}
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self._data[item]
|
||||
|
||||
def __setitem__(self, key, value: TradePosition | TradeOrder | TradeDeal):
|
||||
def __setitem__(self, key, value: TradeData):
|
||||
self._open_items.add(value.ticket)
|
||||
self._data[key] = value
|
||||
|
||||
@@ -23,7 +29,7 @@ class TradingData[Generic]:
|
||||
except KeyError:
|
||||
logger.warning(f'{key} not found')
|
||||
|
||||
def __contains__(self, item):
|
||||
def __contains__(self, item: int):
|
||||
return item in self._open_items
|
||||
|
||||
def __iter__(self):
|
||||
@@ -32,10 +38,10 @@ class TradingData[Generic]:
|
||||
def __len__(self):
|
||||
return len(self._data)
|
||||
|
||||
def get(self, key, default=None):
|
||||
def get(self, key, default=None) -> TradeData | None:
|
||||
return self._data.get(key, default) if key in self._open_items else default
|
||||
|
||||
def pop(self, key, default=None):
|
||||
def pop(self, key, default=None) -> TradeData | None:
|
||||
self._open_items.discard(key)
|
||||
return self._data.get(key, default)
|
||||
|
||||
@@ -59,10 +65,6 @@ class TradingData[Generic]:
|
||||
class PositionsManager(TradingData):
|
||||
_data: dict[int, TradePosition]
|
||||
|
||||
def __init__(self, open_items: set[int] = None, data: dict = None):
|
||||
self._open_items = open_items or set()
|
||||
self._data = data or {}
|
||||
|
||||
@property
|
||||
def open_positions(self) -> tuple[TradePosition, ...]:
|
||||
return tuple(position for position in self._data.values() if position.ticket in self.open_items)
|
||||
@@ -71,16 +73,10 @@ class PositionsManager(TradingData):
|
||||
class OrdersManager(TradingData):
|
||||
_data = dict[int, TradeOrder]
|
||||
|
||||
def __init__(self, open_items: set[int] = None, data: dict = None):
|
||||
self._open_items = open_items or set()
|
||||
self._data = data or {}
|
||||
|
||||
@property
|
||||
def active_orders(self) -> tuple[TradeOrder, ...]:
|
||||
return tuple(order for order in self._data.values() if order.ticket in self.open_items)
|
||||
|
||||
|
||||
class DealsManager(TradingData):
|
||||
def __init__(self, open_items: set[int] = None, data: dict = None):
|
||||
self._open_items = open_items or set()
|
||||
self._data = data or {}
|
||||
...
|
||||
|
||||
@@ -4,7 +4,7 @@ from logging import getLogger
|
||||
|
||||
from .config import Config
|
||||
from .meta_trader import MetaTrader
|
||||
from ..contrib.backtester import MetaTester
|
||||
# from ..contrib.backtester import MetaTester
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class Base:
|
||||
**kwargs: Set instance attributes with keyword arguments. Only if they are annotated on the class body.
|
||||
"""
|
||||
self.config = Config()
|
||||
self.mt5 = MetaTrader() if self.config.mode == 'live' else MetaTester()
|
||||
self.mt5 = MetaTrader() #if self.config.mode == 'live' else MetaTester()
|
||||
self.exclude = {'mt5', "config", 'exclude', 'include', 'annotations', 'class_vars', 'dict'}
|
||||
self.include = set()
|
||||
self.set_attributes(**kwargs)
|
||||
|
||||
@@ -91,8 +91,8 @@ class MetaTrader(metaclass=BaseMeta):
|
||||
self.error = Error(*err)
|
||||
|
||||
if self.error.is_connection_error():
|
||||
await self.initialize(**self.config.account_info(), path=self.config.path)
|
||||
await self.login(**self.config.account_info())
|
||||
await self.initialize(path=self.config.path)
|
||||
await self.login()
|
||||
res = await asyncio.to_thread(func, *args, **kwargs)
|
||||
|
||||
if res is None:
|
||||
@@ -103,7 +103,7 @@ class MetaTrader(metaclass=BaseMeta):
|
||||
logger.warning(f'{error_msg}:{self.error.description}')
|
||||
return res
|
||||
|
||||
async def login(self, login: int, password: str, server: str, timeout: int = 60000) -> bool:
|
||||
async def login(self, *, login: int = 0, password: str = '', server: str = '', timeout: int = 60000) -> bool:
|
||||
"""
|
||||
Connects to the MetaTrader terminal using the specified login, password and server.
|
||||
|
||||
@@ -116,6 +116,10 @@ class MetaTrader(metaclass=BaseMeta):
|
||||
Returns:
|
||||
bool: True if successful, False otherwise.
|
||||
"""
|
||||
acc_details = self.config.account_info()
|
||||
login = login or acc_details.get('login', 0)
|
||||
password = password or acc_details.get('password', '')
|
||||
server = server or acc_details.get('server', '')
|
||||
return await asyncio.to_thread(self._login, login, password=password, server=server, timeout=timeout)
|
||||
|
||||
async def initialize(self, path: str = "", login: int = 0, password: str = "", server: str = "",
|
||||
@@ -128,15 +132,20 @@ class MetaTrader(metaclass=BaseMeta):
|
||||
login (int): The trading account number.
|
||||
password (str): The trading account password.
|
||||
server (str): The trading server name.
|
||||
timeout (int): The timeout for the connection in seconds.
|
||||
timeout (int): The timeout for the connection in milliseconds.
|
||||
portable (bool): If True, the terminal will be launched in portable mode.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise.
|
||||
"""
|
||||
path = path or self.config.path
|
||||
args = (str(path),) if path else ()
|
||||
kwargs = {key: value for key, value in (('login', login), ('password', password), ('server', server),
|
||||
('timeout', timeout), ('portable', portable)) if value}
|
||||
acc = self.config.account_info()
|
||||
kwargs = {key: value for key, value in (('login', login or acc.get('login')),
|
||||
('password', password or acc.get('password')),
|
||||
('server', server or acc.get('server')),
|
||||
('timeout', timeout or 60000),
|
||||
('portable', portable)) if key is not None}
|
||||
res = await asyncio.to_thread(self._initialize, *args, **kwargs)
|
||||
return res
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from .finger_trap import FingerTrap
|
||||
from .tracker import Tracker
|
||||
from .finger_trap_back_test import FingerTrapTest, FingerTrapSingleTest
|
||||
# from .finger_trap_back_test import FingerTrapTest, FingerTrapSingleTest
|
||||
|
||||
@@ -7,7 +7,7 @@ from .core.models import TradePosition, TradeAction
|
||||
from .core.constants import OrderType
|
||||
from .core.config import Config
|
||||
|
||||
from .contrib.backtester.meta_tester import MetaTester
|
||||
# from .contrib.backtester.meta_tester import MetaTester
|
||||
|
||||
from .order import Order
|
||||
from .utils import backoff_decorator
|
||||
@@ -25,7 +25,7 @@ class Positions:
|
||||
ticket (int): Position ticket.
|
||||
mt5 (MetaTrader): MetaTrader instance.
|
||||
"""
|
||||
mt5: MetaTrader | MetaTester
|
||||
mt5: MetaTrader #| MetaTester
|
||||
|
||||
def __init__(self, *, symbol: str = "", group: str = "", ticket: int = 0):
|
||||
"""Get Open Positions.
|
||||
@@ -38,7 +38,7 @@ class Positions:
|
||||
|
||||
"""
|
||||
self.config = Config()
|
||||
self.mt5 = MetaTrader() if self.config.mode == 'live' else MetaTester()
|
||||
self.mt5 = MetaTrader() # if self.config.mode == 'live' else MetaTester()
|
||||
self.symbol = symbol
|
||||
self.group = group
|
||||
self.ticket = ticket
|
||||
|
||||
@@ -6,7 +6,7 @@ from logging import getLogger
|
||||
|
||||
from .positions import Positions
|
||||
from .core.config import Config
|
||||
from.contrib.backtester.event_manager import EventManager
|
||||
# from.contrib.backtester.event_manager import EventManager
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
@@ -20,13 +20,13 @@ def delta(obj: time) -> timedelta:
|
||||
return timedelta(hours=obj.hour, minutes=obj.minute, seconds=obj.second, microseconds=obj.microsecond)
|
||||
|
||||
|
||||
async def backtest_sleep(secs):
|
||||
"""A custom function to call when the session starts."""
|
||||
em = EventManager()
|
||||
|
||||
async with em.condition:
|
||||
while em.config.test_data.cursor.time < (em.config.test_data.cursor.time + secs):
|
||||
await em.condition.wait()
|
||||
# async def backtest_sleep(secs):
|
||||
# """A custom function to call when the session starts."""
|
||||
# # em = EventManager()
|
||||
#
|
||||
# async with em.condition:
|
||||
# while em.config.test_data.cursor.time < (em.config.test_data.cursor.time + secs):
|
||||
# await em.condition.wait()
|
||||
|
||||
|
||||
class Session:
|
||||
@@ -213,7 +213,7 @@ class Sessions:
|
||||
current_session = self.find_next(now)
|
||||
secs = current_session.until() + 10
|
||||
logger.info(f'sleeping for {secs} seconds until next {current_session} session')
|
||||
sleep_func = sleep if Config().mode == 'live' else backtest_sleep
|
||||
sleep_func = sleep # if Config().mode == 'live' else backtest_sleep
|
||||
await sleep_func(secs)
|
||||
self.current_session = current_session
|
||||
await self.current_session.begin()
|
||||
|
||||
@@ -8,7 +8,7 @@ from datetime import time as dtime
|
||||
from .core.meta_trader import MetaTrader
|
||||
from .symbol import Symbol as _Symbol
|
||||
from .core import Config
|
||||
from .contrib.backtester.meta_tester import MetaTester
|
||||
# from .contrib.backtester.meta_tester import MetaTester
|
||||
from .sessions import Sessions, Session
|
||||
|
||||
Symbol = TypeVar("Symbol", bound=_Symbol)
|
||||
@@ -48,7 +48,7 @@ class Strategy(ABC):
|
||||
self.parameters["name"] = self.name
|
||||
self.sessions = sessions or Sessions(Session(start=0, end=dtime(hour=23, minute=59, second=59)))
|
||||
self.config = Config()
|
||||
self.mt5 = MetaTrader() if self.config.mode == 'live' else MetaTester()
|
||||
self.mt5 = MetaTrader() #if self.config.mode == 'live' else MetaTester()
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.name}({self.symbol!r})"
|
||||
|
||||
Reference in New Issue
Block a user