回测基本一致
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
"""tester.ini generator (doc 07 §2b).
|
||||
|
||||
A small INI tells the tester *what* to run: expert, symbol, period, tick
|
||||
model, date range, deposit, leverage, report name, and ``ShutdownTerminal=1``
|
||||
so the terminal closes itself when done (the bridge then knows it's finished).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import configparser
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
DEFAULT_MT5_INSTALL = r"C:\Program Files\MetaTrader 5 IC Markets Global"
|
||||
|
||||
# Tick models (doc 07 §2b):
|
||||
# 0 = Every tick based on real ticks (highest accuracy, slowest)
|
||||
# 1 = Every tick (generated from M1)
|
||||
# 2 = 1-minute OHLC (good for non-tick-sensitive, fast) — routine verification
|
||||
# 4 = Open prices only (rough, fastest)
|
||||
MODEL_OHLC = 2
|
||||
MODEL_EVERY_TICK = 1
|
||||
MODEL_REAL_TICKS = 0
|
||||
MODEL_OPEN_PRICES = 4
|
||||
|
||||
|
||||
@dataclass
|
||||
class TesterConfig:
|
||||
"""Inputs for one tester run (doc 07 §2b).
|
||||
|
||||
``FromDate`` / ``ToDate`` are formatted ``YYYY.MM.DD`` for MT5. The login
|
||||
section lives separately (kept out of code via the env file, doc 07 §5).
|
||||
"""
|
||||
|
||||
expert: str # e.g. "Experts\\MyEA.ex5"
|
||||
symbol: str
|
||||
period: str = "H1" # chart timeframe (≤ the EA's signal timeframe)
|
||||
model: int = MODEL_OHLC # tick model
|
||||
from_date: str = "2024.01.01" # YYYY.MM.DD
|
||||
to_date: str = "2026.01.01"
|
||||
deposit: float = 10000.0
|
||||
leverage: int = 100
|
||||
report: str = "report_myrun" # output HTML name (no extension)
|
||||
shutdown_terminal: bool = True
|
||||
set_file: Optional[str] = None # path to the .set, or None to inline
|
||||
login: Optional[int] = None # from env, never hard-coded
|
||||
password: Optional[str] = None # from env, never hard-coded
|
||||
server: Optional[str] = None # broker server
|
||||
|
||||
|
||||
def write_tester_ini(cfg: TesterConfig, path: str | Path) -> str:
|
||||
"""Write a ``tester.ini`` for ``terminal64.exe /config:`` and return its path."""
|
||||
p = Path(path)
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
cp = configparser.ConfigParser()
|
||||
cp.optionxform = str # preserve case (MT5 keys are case-sensitive)
|
||||
cp["Tester"] = {
|
||||
"Expert": cfg.expert,
|
||||
"Symbol": cfg.symbol,
|
||||
"Period": cfg.period,
|
||||
"Model": str(cfg.model),
|
||||
"FromDate": cfg.from_date,
|
||||
"ToDate": cfg.to_date,
|
||||
"Deposit": str(cfg.deposit),
|
||||
"Leverage": str(cfg.leverage),
|
||||
"Report": cfg.report,
|
||||
"ShutdownTerminal": "1" if cfg.shutdown_terminal else "0",
|
||||
}
|
||||
if cfg.set_file:
|
||||
cp["Tester"]["TestReplaceExpert"] = "0"
|
||||
common: dict[str, str] = {}
|
||||
if cfg.login is not None:
|
||||
common["Login"] = str(cfg.login)
|
||||
if cfg.password is not None:
|
||||
common["Password"] = cfg.password
|
||||
if cfg.server is not None:
|
||||
common["Server"] = cfg.server
|
||||
if common:
|
||||
cp["Common"] = common
|
||||
with p.open("w", encoding="utf-8") as f:
|
||||
cp.write(f)
|
||||
return str(p)
|
||||
Reference in New Issue
Block a user