feat: 24/7 synthetic rollover calibration, stop-limit orders, MT5 wave model, and open prices mode fixes

This commit is contained in:
Ethansi2947E
2026-10-28 01:55:56 +01:00
parent 08f72b67ac
commit f3ba591aa9
8 changed files with 269 additions and 21 deletions
+7 -1
View File
@@ -7,7 +7,7 @@ General-Purpose MetaTrader 5 Strategy Tester Replica (Python Interface).
from __future__ import annotations
import edge_tester as tester_api
from .symbol_spec import make_symbol_spec
from .symbol_spec import make_symbol_spec, create_symbol_spec
from .optimizer import StrategyOptimizer
# Expose core tester classes directly at edge_engine top level
@@ -22,6 +22,9 @@ LatencyMode = tester_api.LatencyMode
OptimizationCriterion = tester_api.OptimizationCriterion
OptimizationAlgorithm = tester_api.OptimizationAlgorithm
INIT_SUCCEEDED = tester_api.INIT_SUCCEEDED
INIT_FAILED = tester_api.INIT_FAILED
__version__ = "2.0.0"
__all__ = [
"Strategy",
@@ -36,5 +39,8 @@ __all__ = [
"OptimizationAlgorithm",
"StrategyOptimizer",
"make_symbol_spec",
"create_symbol_spec",
"INIT_SUCCEEDED",
"INIT_FAILED",
"tester_api",
]
+13 -1
View File
@@ -39,6 +39,16 @@ def _eval_pass(
if hasattr(spec, k):
setattr(spec, k, v)
# Optional preparation hook for strategies that precalculate buffers
if hasattr(strat, "prepare"):
strat.prepare(
bars_dict["open"],
bars_dict["high"],
bars_dict["low"],
bars_dict["close"],
spec
)
# Build config
cfg = et.TesterConfig()
for k, v in cfg_dict.items():
@@ -129,7 +139,9 @@ class StrategyOptimizer:
"high": df["high"].to_numpy(np.float64),
"low": df["low"].to_numpy(np.float64),
"close": df["close"].to_numpy(np.float64),
"time": df["time"].to_numpy(np.int64) if "time" in df.columns else np.zeros(n, np.int64),
"time": (df["time"].astype("int64") // 10**9).to_numpy(np.int64)
if pd.api.types.is_datetime64_any_dtype(df["time"])
else df["time"].to_numpy(np.int64) if "time" in df.columns else np.zeros(n, np.int64),
"volume": df["tick_volume"].to_numpy(np.int64) if "tick_volume" in df.columns else np.zeros(n, np.int64),
"spread": df["spread"].to_numpy(np.int32) if "spread" in df.columns else np.zeros(n, np.int32),
}
+23
View File
@@ -70,3 +70,26 @@ def make_symbol_spec(name: str, try_mt5: bool = False) -> Dict[str, Any]:
except Exception:
pass
return spec
def create_symbol_spec(name: str, try_mt5: bool = False):
"""Instantiate and populate a C++ SymbolSpec object for the given instrument."""
import edge_tester as et
d = make_symbol_spec(name, try_mt5=try_mt5)
sym = et.SymbolSpec()
sym.name = name
sym.point = float(d.get("point", 0.01))
sym.digits = int(d.get("digits", 2))
sym.spread_val = float(d.get("spread_val", 0.0))
sym.trade_tick_size = float(d.get("trade_tick_size", 0.01))
sym.trade_tick_value = float(d.get("trade_tick_value", 0.01))
sym.volume_min = float(d.get("volume_min", 0.01))
sym.volume_max = float(d.get("volume_max", 100.0))
sym.volume_step = float(d.get("volume_step", 0.01))
sym.commission_per_lot = float(d.get("commission_per_lot", 0.0))
sym.trade_stops_level = float(d.get("trade_stops_level", 0.0))
sym.trade_freeze_level = float(d.get("trade_freeze_level", 0.0))
sym.swap_long = float(d.get("swap_long", 0.0))
sym.swap_short = float(d.get("swap_short", 0.0))
return sym