feat: 24/7 synthetic rollover calibration, stop-limit orders, MT5 wave model, and open prices mode fixes
This commit is contained in:
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user