master
- mtlib: PnL/仓位统一走 报价货币->账户货币 折算率 (tick_value 语义), USDJPY 已用 demo 实盘+导出记录逐分验证关闭 (偏差 <0.01 USD) - run_backtest/position_sizing 由注册商品自动推导折算率 (USD 报价对子恒 1.0) - 新增 eurusd_scalp 策略 (M1 均值回归, MAGIC=2026091501) + 50k 数据 - 协议入口 AGENTS.md / CLAUDE.md / .mcp.json; 策略登记 MAGIC/DATA_FILE - 验证记录 ReportHistory-52845377.html (12 笔 deal 交叉核对, smoke 47 PASS) Co-Authored-By: Claude Code <noreply@anthropic.com>
MT5 多策略量化工作区
MetaTrader 5 策略的回测 / 样本外验证 / 参数优化 / 实盘一体化工作区。 结构目标: 多策略 × 多商品, 回测与实盘信号同源, 杜绝逻辑漂移。
AI 代理入口协议: 任何 AI 改本仓库前先读
AGENTS.md(铁律/命名/魔术号, 由python -m mtlib smoke机器把关)。
前置依赖: 本项目根植于 mtdata MCP
整个工作区的数据、行情、分析与实盘交易全部建立在 mtdata 之上, 没有它什么都跑不了:
┌───────────────┐ mcp__mtdata__* 工具 ┌──────────────────┐ mtdata-cli(子进程) ┌───────────────┐
│ Claude Code │ ───────────────────────▶ │ mtdata 服务 │ ───────────────────▶ │ MetaTrader 5 │
│ (交互分析 + 本项目代码) │ ◀─────────────────────── │ (MCP Server / CLI) │ ◀─────────────────── │ (终端运行中) │
└───────────────┘ 行情/指标/分析/交易 └──────────────────┘ JSON 回传 └───────────────┘
- 两条通道, 同一个后端: 交互分析时 Claude 直接调
mcp__mtdata__*MCP 工具; 策略代码一律经mtlib/cli.py调mtdata-cli子进程(唯一出口, 见该文件头注释)。 - 前置条件:
- MetaTrader 5 终端运行中且已登录;
mtdata-cli/mtdata-stdio已安装并在 PATH;- Claude Code 已注册 mtdata MCP(本项目已配好):
- 用户级(所有项目可用):
claude mcp add -s user --transport stdio mtdata -- mtdata-stdio - 项目级(双保险): 仓库根
.mcp.json(同定义); 修改后重启 Claude Code 生效。
- 用户级(所有项目可用):
- 参考文档(随仓库提供):
mtdata MCP 详细说明书.md(全部工具契约与坑) /指标列表.md(193 个可内嵌指标)。 - 版本注意: 用户级 MCP 配置存在
~/.claude.json, 不是~/.claude/mcp.json(后者当前版本不读取)。
目录结构
mtlib/ # 公共核心库 (与具体策略无关)
data.py # 数据加载 (唯一入口)
instruments.py # 商品事实注册表 (点差/合约/时段, 实测后填写)
cli.py # mtdata-cli 封装 (参数契约/去重/下单/平仓)
backtest.py # 回测引擎 (唯一)
metrics.py # 绩效指标 (唯一)
plot.py / walkforward.py / console.py / __main__.py
strategies/<name>/ # 一个策略一个目录
strategy.py # 唯一信号源: generate_signals + generate_signal_at 共用 _check
params.py # 策略参数 (dataclass)
backtest.py / walkforward.py / optimize.py / session_analysis.py / live.py
data/ # K线 JSON
tools/ # 数据拉取 / 点差实测 (规划中)
常用命令 (仓库根目录, 一律 python -m)
| 命令 | 作用 |
|---|---|
python -m mtlib smoke |
冒烟测试: 一致性把关 (~30s, 改动前必跑) |
python -m strategies.xauusd_scalp.backtest |
回测 |
python -m strategies.xauusd_scalp.walkforward |
样本外验证 (前后两半) |
python -m strategies.xauusd_scalp.walkforward + XAUUSD_SPREAD=0.22 |
点差压力测试 |
python -m strategies.xauusd_scalp.optimize |
参数网格优化 |
python -m strategies.xauusd_scalp.session_analysis |
时段/星期/方向分析 |
python -m strategies.xauusd_scalp.live |
实盘/模拟盘 (默认 dry-run 预览) |
旧文件名 (python xauusd_scalp_backtest.py 等) 保留为薄壳, 转调新命令。
实盘安全开关
- 默认预览模式, 绝不发单:
XAUUSD_DRY_RUN未设置或非0 - 真实下单:
XAUUSD_DRY_RUN=0 python -m strategies.xauusd_scalp.live - 点差覆盖(压力测试):
XAUUSD_SPREAD=0.22 ...
开始一个新策略 (5 步)
- 注册商品: 在
mtlib/instruments.py添加一个Instrument(必须填实测点差与交易时段; 禁止拍脑袋)。 - 复制目录:
strategies/<name>/复制xauusd_scalp/。 - 写信号: 在
strategy.py只改_check(或重写信号逻辑), 同时保留generate_signals+generate_signal_at双入口。 - 改参数: 编辑
params.py的StrategyParams。 - 验证: 跑
python -m mtlib smoke(信号双入口一致断言会自动覆盖新策略)。
铁律: 信号逻辑只写一份。任何"实盘另写一份信号"的冲动都是 bug。 回测假设(成交价/点差/滑点)口径见
mtlib/backtest.py头注释。
2026-09 重构记录 (三个显式行为修正)
重构时统一了三处旧脚本间的漂移, 数字与旧版不同是预期的:
| 项目 | 旧值 | 新值(统一) | 影响 |
|---|---|---|---|
| 时段过滤 | 回测/实盘用离散 {7,8,9,10,16,17,18,20}; optimize/session_analysis 用区间 (7-16)∪(12-21) |
全部离散集合 (来自 instruments) | optimize/session_analysis 信号集合变化 |
| 点差 | backtest/walkforward/optimize=0.16, session_analysis=0.06 | 全部 0.16 (商品实测) | session_analysis 结果变化 |
| 回测签名默认值 | tp=2.0/sl=1.0/step=0.5 (从未实际使用) | tp=1.2/sl=0.6/start=1.0/step=0.2 | 无 (main 早已传 1.2/0.6/0.2) |
另修复 walkforward 判定: 旧逻辑"测试半 PF>1 即判泛化"会漏过训练半亏损的过拟合; 新逻辑要求两半都 PF>=1 且收益>0。
验证哲学
- 回测只是筛选器, 不是结论。样本量 50 笔/段远远不够。
- 判读顺序: 样本外两半都正 → 点差压力测试 → demo 真实成交 2~4 周对照实际滑点/点差。
- 任何改动前跑
python -m mtlib smoke。
Languages
Python
100%