# MT5 EA 批量回测系统 基于 MetaTrader 5 的自动化批量回测工具,支持多EA、多交易品种、多时间周期的组合测试。 ## 项目结构 ``` mt5_backtest/ ├── gui.py # 图形界面(统一入口,所有回测操作都在这里) ├── scripts/ │ ├── ini_generator.py # 生成MT5配置文件 │ ├── mt5_auto_runner.py # 自动运行回测 │ ├── batch_executor.py # 批量执行器 │ ├── result_parser.py # 解析HTM/XML报告 │ ├── report_generator.py # 生成汇总报告 │ ├── symbol_resolver.py # 根品种别名解析(XAUUSD→XAUUSDc) │ └── optimizer/ # EA参数优化系统 ├── config/ # 配置文件目录 ├── reports/ # 回测报告输出目录 ├── tests/ # 自检脚本(test_*.py / smoke_*.py) ├── logs/ # 日志目录 └── README.md # 本文档 ``` ## 核心原理 ### 1. 配置生成阶段 (ini_generator.py) - 读取配置文件 `config/ea_configs.yaml` - 扫描 MT5 的 `MQL5/Experts` 目录获取 EA 列表 - 根据配置的 EA品种、时间周期、参数组合生成 INI 配置文件 - 每个 INI 文件对应一次回测任务 - 写入 INI 的 `Symbol=` 行通过 `scripts/symbol_resolver.py` 查表替换(见下文"根品种别名映射") ### 2. 自动执行阶段 (mt5_auto_runner.py) - 通过命令行调用 MT5 终端: `terminal64.exe /config:xxx.ini` - 监控回测进度,等待报告文件生成 - 自动终止并重启 MT5 进程(可选) - 复制生成的 HTM 报告到项目目录 ### 3. 结果解析阶段 (result_parser.py) - 读取 `reports/` 目录下的 HTM 报告文件 - 自动检测文件编码(UTF-16-LE with BOM) - 使用正则表达式提取关键指标 - 支持中英文标签匹配 ### 4. 报告生成阶段 (report_generator.py) - 将解析结果导出为 Excel、CSV、HTML、Markdown 格式 - 支持按盈利因子、胜率等指标排序 ## 使用方式 ### 方式一:图形界面(推荐) ```bash python gui.py ``` 界面包含三个标签页: - **回测配置**:选择 EA、交易品种、时间周期、回测日期等 - **执行选项**:设置超时、跳过已完成的测试等 - **报告查看**:查看已解析的回测结果,支持排序和导出CSV ### 方式二:GUI(推荐,唯一入口) ```bash python gui.py ``` > 整个回测流程(生成 INI → 运行 → 解析 → 汇总)都在 GUI 后台线程完成, > 进度实时显示在 "参数优化" 标签页的日志框。 > YAML 仅作为可读的配置导出/快照(GUI "保存配置" 按钮),不参与运行时通信。 ## 配置文件格式 配置文件 `config/ea_configs.yaml` 示例: ```yaml eas: - name: GMarket filename: GMarket.ex5 set_file: GMarket_default.set # 可选,使用SET文件 backtest_settings: symbols: ["EURUSD", "GBPUSD", "XAUUSD", "USDJPY"] timeframes: ["M1", "M5", "M15", "H1"] # 可选:根品种别名映射(见下文"根品种别名映射") # symbol_aliases: # XAUUSD: XAUUSDc # 逻辑 XAUUSD -> 实际 XAUUSDc # XAGUSD: XAGUSDm # 逻辑 XAGUSD -> 实际 XAGUSDm date_range: from: "2026.01.01" to: "2026.01.04" model: 0 # 0=Every Tick, 1=OHLC, 4=Real Tick execution_delay: 0 # 延迟设置 deposit: 10000 # 初始保证金 leverage: "1:100" # 杠杆 replace_report: true # 覆盖已有报告 shutdown_terminal: true mt5_settings: terminal_path: "C:\\Program Files\\MetaTrader 5 IC Markets Global\\terminal64.exe" data_dir: "C:\\Users\\Administrator\\AppData\\Roaming\\MetaQuotes\\Terminal\\..." reports_dir: "reports" ini_dir: "config/generated" execution: timeout_per_test: 30 # 分钟 skip_existing: true kill_between: true # 测试间关闭MT5 ``` ## 关键指标说明 | 指标 | 说明 | 评判标准 | |------|------|----------| | **profit_factor** | 盈利因子 = 毛利/毛损 | >1.5 优秀, >1.0 微利, <1.0 亏损 | | **net_profit** | 总净盈利 | 越高越好 | | **gross_profit** | 毛利(所有盈利交易总和) | 越高越好 | | **gross_loss** | 毛损(所有亏损交易总和) | 越低越好 | | **win_rate** | 胜率(盈利交易占比) | >60% 较好 | | **total_trades** | 总交易次数 | 样本量参考 | | **max_drawdown** | 最大回撤金额 | 越低越稳定 | | **sharpe_ratio** | 夏普比率(风险收益比) | >1.0 较好, >2.0 优秀 | | **recovery_factor** | 采收率 | >1.5 较好 | ## 如何添加新的交易品种 ### 方法一:通过 GUI 界面 1. 打开 `python gui.py` 2. 切换到"回测配置"标签页 3. 在"交易品种"区域勾选需要的品种 4. 点击"保存配置" ### 方法二:直接编辑配置文件 编辑 `config/ea_configs.yaml`: ```yaml backtest_settings: symbols: - EURUSD - GBPUSD - XAUUSD # 添加新品种 - USDJPY - BTCUSD # 添加数字货币 ``` ### 支持的交易品种类型 | 类型 | 示例 | |------|------| | 主流货币对 | EURUSD, GBPUSD, USDJPY, USDCHF | | 商品货币 | AUDUSD, NZDUSD, USDCAD | | 交叉货币 | EURGBP, EURJPY, GBPJPY | | 贵金属 | XAUUSD, XAGUSD | | 原油 | XBRUSD, XTIUSD | | 数字货币 | BTCUSD, ETHUSD, LTCUSD | ## 根品种别名映射 (`symbol_aliases`) MT5 自带品种(如 `XAUUSD`)历史深度和精度有限;用户常在 MT5 里添加自定义品种 (如 `XAUUSDc` / `XAUUSDm`)作为更长时间范围或优化用途的"替身"。本系统通过 `symbol_aliases` 让你在 yaml 里写一次逻辑品种名、由系统按表替换成实际 MT5 品种。 ### 写入 `config/ea_configs.yaml` ```yaml backtest_settings: symbols: [XAUUSD, XAGUSD, EURUSD] # 用户的"逻辑品种" symbol_aliases: XAUUSD: XAUUSDc # 逻辑 XAUUSD -> 实际 XAUUSDc XAGUSD: XAGUSDm # 逻辑 XAGUSD -> 实际 XAGUSDm # EURUSD 不列 -> 始终 EURUSD ``` ### 工作机制 1. `scripts/ini_generator.py` 和 `scripts/optimizer/ea_batch_optimizer.py` 在 写 INI 的 `Symbol=` 之前调用 `scripts/symbol_resolver.resolve_symbol()`。 2. 解析器是**纯查表**——没有任何"基于日期/优化/周期的智能判断"——写啥用啥: - 别名表里有这个逻辑品种 → 用别名替换 - 没有 → 原样写入 `Symbol=` 3. 两条调用路径共用同一份解析器(`scripts/symbol_resolver.py`),保证 GUI 回测页 和优化器生成的 INI 行为一致。 ### GUI 优化页 GUI 优化页下拉只显示**逻辑品种**(不再同时列出 XAUUSD / XAUUSDc)。旁边有一个 `→ XAUUSDc` 提示标签,**实时反映 yaml 里 `symbol_aliases` 当前配置下实际会用什么品种**。 改 yaml 后重启 GUI 即可看到提示变化,无需在 GUI 里反复切换。 ### 验证 无需 MT5 也能验: ```bash python tests/test_symbol_resolver.py # 9 条查表断言 python tests/test_ini_generator.py # 5 条端到端断言 ``` 需要 MT5 验证完整流水线: ```bash python tests/smoke_alias_backtest.py # 跑两次真实回测:一次无别名 (Symbol=XAUUSD),一次有别名 (Symbol=XAUUSDc) # 期望:C:\Users\Administrator\Desktop\mt5-backtest\reports 下生成两份 .htm 报告 # 报告"交易品种"字段分别是 XAUUSD 和 XAUUSDc ``` > 注:`smoke_alias_backtest.py` 顶部硬编码了 MT5 路径和 data dir hash,复制到其他电脑后 > 需要相应修改 `MT5_PATH` / `MT5_DATA_DIR` 常量。 ### 扩展点(ponytail) `scripts/symbol_resolver.py` 是共享函数入口,将来要把"配置源"切换成数据库或要做 MT5 `SymbolSelect` 校验,**只改这一个文件**即可,所有调用方(ini 生成器、批量优化器、 GUI 预览)同步生效。 ## 如何添加新的时间周期 编辑 `config/ea_configs.yaml`: ```yaml backtest_settings: timeframes: - M1 # 1分钟 - M5 # 5分钟 - M15 # 15分钟 - M30 # 30分钟 - H1 # 1小时 - H4 # 4小时 - D1 # 日线 - W1 # 周线 ``` ## 报告导出功能 ```bash # 导出排序后的CSV python scripts/result_parser.py --results-dir reports --csv reports/results.csv --sort profit_factor # 可用排序字段 # expert, symbol, period, net_profit, gross_profit, profit_factor # total_trades, win_rate, max_drawdown, sharpe_ratio ``` ## HTM 报告解析说明 MT5 生成的 HTM 报告采用特殊编码: - 编码格式:UTF-16-LE with BOM - 标签语言:中英混合 解析器会自动处理以下情况: 1. BOM 标记检测与跳过 2. 中文字段名匹配(如"盈利因子"、"夏普比率") 3. 特殊格式数据提取(如 "92.46 (8.61%)") ### 解析的完整字段列表 **测试信息 (test_info)**: - expert: EA名称 - symbol: 交易品种 - period: 时间周期 - company: 经纪商 - currency: 货币 - leverage: 杠杆 **性能指标 (metrics)**: - initial_deposit: 初始入金 - net_profit: 总净盈利 - gross_profit: 毛利 - gross_loss: 毛损 - profit_factor: 盈利因子 - expected_payoff: 预期收益 - recovery_factor: 采收率 - sharpe_ratio: 夏普比率 - ahpr/ghpr: 几何/算术平均收益率 - lr_correlation: LR相关性 - lr_standard_error: LR标准误差 - max_drawdown: 最大结余亏损 - max_equity_drawdown: 最大净值亏损 - absolute_drawdown: 绝对结余亏损 - margin_level: 预付款维持率 - total_trades: 交易总计 - total_deals: 总成交 - short_trades: 卖出交易 - long_trades: 买入交易 - winning_trades: 盈利交易 - losing_trades: 亏损交易 - win_rate: 胜率 - max_profit_trade: 最大获利交易 - max_loss_trade: 最大亏损交易 - avg_profit_trade: 平均获利交易 - avg_loss_trade: 平均亏损交易 - longest_win_streak: 最大连胜 - longest_lose_streak: 最大连败 - avg_win_streak: 平均连胜 - avg_lose_streak: 平均连败 - min_hold_time/max_hold_time/avg_hold_time: 持仓时间 - quality: 质量历史 - bars: 柱数 - quotes: 报价数 - score: 分值 - on_tester: OnTester结果 ## EA参数优化系统 ### 概述 EA参数优化系统用于自动寻找EA的最优参数组合,支持多种搜索策略。 ### 目录结构 ``` optimizer/ ├── configs/ # EA配置文件目录 │ ├── MA_Cross.json # 示例: MA交叉策略 (6参数, Grid搜索) │ └── Grid_Pro.json # 示例: 网格策略 (8参数, 遗传算法) ├── set_files/ # 生成的SET参数文件 │ └── {EA_NAME}/ │ └── params_00000001.set ~ params_NNNNNNNN.set ├── reports/ # MT5测试报告 ├── results/ # 分析结果 │ ├── {EA_NAME}_param_mapping.csv │ └── optimization_report.txt ├── scripts/ # PowerShell脚本 └── logs/ # 日志 ``` ### EA配置文件格式 ```json { "ea_name": "MA Cross Scalper", "ea_path": "Experts\\MA_Cross.ex5", "description": "双MA交叉策略", "search_strategy": "grid", "optimization_criterion": "profit_factor", "parameters": { "FastMA_Period": { "type": "int", "default": 14, "min": 5, "max": 30, "step": 1, "description": "快速MA周期" }, "SlowMA_Period": { "type": "int", "default": 50, "min": 20, "max": 100, "step": 5, "description": "慢速MA周期", "condition": ">FastMA_Period" } }, "test_config": { "symbol": "EURUSD", "period": "H1", "from_date": "2025.01.01", "to_date": "2025.12.31", "model": 1, "deposit": 10000, "leverage": "1:100" }, "walk_forward": { "enabled": false } } ``` ### 参数类型 | 类型 | 说明 | 示例 | |------|------|------| | int | 整数参数 | FastMA_Period: 5-30 | | double | 浮点参数 | RiskPercent: 0.5-3.0 | | bool | 布尔参数 | EnableMM: true/false | | enum | 枚举参数 | TradingMode: BUY/SELL/BOTH | ### 搜索策略选择 | 组合数 | 策略 | 说明 | |--------|------|------| | ≤10,000 | Grid Search | 暴力遍历,适合快速测试 | | 10,001-500,000 | Latin Hypercube | 均匀采样,效率高 | | >500,000 | Genetic Algorithm | 遗传算法,智能搜索 | ### 使用方式 #### 方式一:图形界面 ```bash python gui.py ``` 切换到"参数优化"标签页,可以: - 查看EA配置列表 - 生成SET文件 - 运行优化测试 - 分析优化结果 #### 方式二:命令行 ```bash # 列出所有EA配置 python optimizer_main.py list # 生成SET文件 python optimizer_main.py generate --ea "MA Cross Scalper" # 分析结果 python optimizer_main.py analyze --sort profit_factor ``` ### 参数约束 在EA配置中使用 `condition` 字段定义参数约束: ```json "SlowMA_Period": { "condition": ">FastMA_Period" } ``` 支持的运算符:`>`, `<`, `>=`, `<=`, `==`, `!=` ### GUI优化面板功能 1. **列出EA配置** - 显示所有配置的参数数量、组合数、预估时间 2. **生成SET文件** - 为每个参数组合创建.set文件 3. **运行优化** - 生成PowerShell脚本,用户可手动执行 4. **分析结果** - 解析报告,找出最优参数组合 ### 输出文件 - `{EA_NAME}_param_mapping.csv` - 参数ID映射表 - `optimization_report.txt` - 优化分析报告 - `best_params.json` - 最优参数JSON ## AI辅助参数优化工具 ### 概述 `scan_set_prompt.py` 是一个命令行工具,用于扫描 MT5 的 SET 参数文件,生成带完整提示词的文本文件,方便发给 AI 讨论参数优化方案。 ### 工作流程 ``` SET文件 → scan_set_prompt.py → AI提示词txt → AI生成优化JSON → 保存到optimizer/configs/ ``` ### 使用方式 ```bash # 交互式选择模式 python scripts/scan_set_prompt.py --interactive # 扫描单个SET文件 python scripts/scan_set_prompt.py --file "C:\path\to\EA.set" # 扫描文件夹下所有SET文件 python scripts/scan_set_prompt.py --folder "C:\path\to\Profiles\Tester" # 批量扫描多个SET文件 python scripts/scan_set_prompt.py --batch a.set b.set c.set # 指定输出目录 python scripts/scan_set_prompt.py --file "C:\path\to\EA.set" --output "C:\path\to\output" ``` ### 交互式模式选项 ``` 1. 扫描单个 SET 文件 2. 扫描文件夹下所有 SET 文件 3. 批量扫描多个 SET 文件 4. 从剪贴板读取 SET 内容 0. 退出 ``` ### 生成的文件内容 生成的 `_optimization_prompt.txt` 包含: 1. **基本信息** - EA名称、参数总数 2. **参数详情表** - 所有参数的当前值、范围、步进 3. **参数分析任务** - 引导 AI 分析哪些参数该优化、范围建议 4. **完整JSON模板** - 符合 `optimizer/configs/*.json` 格式,包含: - `ea_path` 自动做 ASCII 安全处理(支持中文名 EA) - `parameters` 部分带优化建议注释 - `test_config` 和 `walk_forward` 配置 ### 输出示例 ```json { "ea_name": "GoldSniper_Pro_v2", "ea_path": "MY-EA\\GoldSniper_Pro_v2.ex5", "description": "Edited via GUI", "search_strategy": "auto", "parameters": { "LotSize": { "type": "double", "default": 0.01, "min": 0.01, "max": 0.1, "step": 0.001, "optimize": true // AI根据策略分析填写 } }, "test_config": {...}, "walk_forward": {...} } ``` ### 注意事项 - SET 文件支持多种格式:我们的 `=val||min||step||max||Y` 格式、MT5 原生 ` ` 格式、布尔 `true/false` 格式 - 自动检测文件编码(UTF-8、UTF-16-LE/BE) - `ea_path` 使用双反斜杠 `\\`,中文 EA 名自动转换为 ASCII(如 `(EA)GoldSniper` → `EA_GoldSniper`) - AI 生成的 JSON 可直接保存到 `optimizer/configs/` 目录使用 ## 批量提取文件名工具 ### 概述 `extract_filenames.py` 用于批量提取某个文件夹下所有文件名,支持子文件夹递归检索。 ### 使用方式 ```bash python extract_filenames.py ``` 交互式操作: 1. 输入要扫描的文件夹路径 2. 选择是否包含子文件夹(默认包含) 3. 输入输出文件名(直接回车使用自动命名) ### 输出文件命名规则 - 自动命名格式:`{源文件夹名}_filenames_{日期时间}.txt` - 例如:`mt5_backtest_filenames_20260531_195723.txt` - 文件保存在被扫描文件夹的**父目录** ### 示例 ``` 请输入文件夹路径: C:\Projects\MyEA 是否包含子文件夹? (y/n, 默认y): 输出文件名 (直接回车使用自动命名): 正在扫描文件夹: C:\Projects\MyEA 模式: 包含子文件夹 (递归) 请稍候... 完成! 共找到 128 个文件 结果已保存到: C:\Projects\MyEA_filenames_20260531_195723.txt ``` ## 未来可扩展方向 ### 1. 自动化参数优化 - 集成 OptParams 参数优化功能 - 支持遗传算法、枚举等优化方法 - 自动寻找最优参数组合 ### 2. 多经纪商支持 - 支持不同经纪商的配置切换 - 账户资金和杠杆差异化设置 ### 3. 实时监控面板 - Web 界面实时显示回测进度 - 推送通知(邮件/微信)回测完成提醒 ### 4. 机器学习辅助 - 使用历史数据训练预测模型 - 辅助参数选择和优化方向建议 ### 5. 云端分布式回测 - 支持多台机器并行回测 - 任务队列和负载均衡 ### 6. 更丰富的报告分析 - 资金曲线图表 - 交易分布热力图 - 月度/年化收益统计 ### 7. 数据库存储 - SQLite/PostgreSQL 存储历史回测结果 - 支持历史对比和趋势分析 ## 依赖环境 - Python 3.8+ - MetaTrader 5 Terminal - 依赖库: tkinter (GUI), yaml, openpyxl, beautifulsoup4, lxml ## 项目结构 ``` mt5_backtest/ ├── gui.py # 图形界面(回测 + 优化,唯一入口) ├── scripts/ │ ├── ini_generator.py # 生成MT5配置文件 │ ├── mt5_auto_runner.py # 自动运行回测 │ ├── batch_executor.py # 批量执行器 │ ├── result_parser.py # 解析HTM/XML报告 │ ├── report_generator.py # 生成汇总报告 │ ├── symbol_resolver.py # 根品种别名解析(symbol_aliases 查表) │ └── optimizer/ # EA优化系统 │ ├── ea_config_parser.py # EA配置解析 │ ├── smart_search.py # 搜索策略 │ ├── parameter_constraint.py # 参数约束 │ ├── analyze_results.py # 结果分析 │ └── ea_batch_optimizer.py # 批量优化器 ├── config/ # 配置文件 ├── reports/ # 回测报告目录 ├── tests/ # 自检脚本(test_symbol_resolver / test_ini_generator / smoke_alias_backtest) ├── optimizer/ # 优化系统目录 │ ├── configs/ # EA配置 │ ├── set_files/ # SET文件 │ ├── reports/ # 优化报告 │ └── results/ # 分析结果 └── logs/ # 日志目录 ``` ## 常见问题 ### Q: MT5 终端路径不正确 修改 `config/ea_configs.yaml` 中的 `terminal_path` 为实际路径 ### Q: 报告文件未生成 1. 检查 MT5 是否正常启动 2. 查看 `logs/batch_executor.log` 日志 3. 确认 `data_dir` 配置正确 ### Q: 中文显示乱码 HTM 报告采用 UTF-16-LE 编码,result_parser.py 会自动处理,无需手动转换 ### Q: 想用 MT5 自定义品种(如 XAUUSDc)跑同一 EA 在 `config/ea_configs.yaml` 的 `backtest_settings` 下加: ```yaml symbol_aliases: XAUUSD: XAUUSDc ``` yaml 符号表里仍写 `XAUUSD`,系统会自动把 INI 的 `Symbol=` 替换为 `XAUUSDc`。 详见上文"根品种别名映射"一节。 ### Q: 改了 `symbol_aliases` 后 GUI 提示没变 GUI 启动时读取一次 `config/ea_configs.yaml`,改完后重启 GUI 即可看到 `→ XAUUSDc` 提示标签更新。无需重新生成报告历史。 ## 许可证 MIT License