Files
gavindiaz ed8e8afb44 Initial commit: MT5 EA 回测报告分析工具集
通用可复用的 MT5 回测分析工具,不针对任何具体 EA:

- mt5_report_parser.py: 解析 MT5 中文 xlsx 报告,重建逐笔交易
- run_analysis.py: 主分析器,IS/OSS 对比 + What-If + 蒙特卡洛 + 数据驱动建议
- walk_forward.py: Walk-Forward 滚动 IS→OOS 验证 (WFE/泛化相关性)
- param_scan.py: 参数敏感度扫描,高原检测 + 输出优化后 .set
- mae_mfe.py: MAE/MFE 分析 + TP/SL 扫描,附 MQL5 导出代码

所有输出为自包含 HTML (内联 SVG,无图片依赖)。
2026-06-28 02:31:54 +08:00

35 lines
16 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8">
<title>参数敏感度扫描 — PF</title>
<style>
body { font-family:-apple-system,"Microsoft YaHei",sans-serif; background:#f8fafc; color:#111827; margin:0; padding:20px;}
.wrap { max-width:1100px; margin:0 auto;}
h1,h2,h3 { color:#1e3a8a;} h1 { border-bottom:3px solid #1e3a8a; padding-bottom:8px;}
table.data { border-collapse:collapse; width:100%; background:#fff; margin:8px 0 16px; font-size:12px;}
table.data th, table.data td { border:1px solid #e2e8f0; padding:5px 7px; text-align:left;}
table.data th { background:#f1f5f9;}
.muted { color:#6b7280; font-size:12px;}
code { background:#f1f5f9; padding:1px 5px; border-radius:3px;}
.chart { width:100%; height:auto; background:#fff; border:1px solid #e2e8f0; border-radius:6px; margin:8px 0;}
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:12px;}
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:12px; margin:16px 0;}
.card { background:#fff; padding:14px; border-radius:8px; border:1px solid #e2e8f0;}
.card .k { color:#6b7280; font-size:12px;} .card .v { font-size:18px; font-weight:600; margin-top:4px;}
.note { background:#fef3c7; border-left:4px solid #f59e0b; padding:10px 14px; margin:12px 0; border-radius:4px;}
.warn { background:#fee2e2; border-left:4px solid #dc2626; padding:10px 14px; margin:12px 0; border-radius:4px;}
footer { color:#6b7280; font-size:11px; margin-top:32px; text-align:center;}
</style></head><body><div class="wrap">
<h1>参数敏感度扫描报告</h1>
<p class='muted'>指标: <code>PF</code> 参数轴: FastMA × SlowMA 样本数: 30</p>
<div class='cards'><div class='card'><div class='k'>全局峰值 PF</div><div class='v'>2.281</div></div><div class='card'><div class='k'>峰值邻域均值/峰值</div><div class='v'>0.47</div></div><div class='card'><div class='k'>高原覆盖率</div><div class='v'>17%</div></div><div class='card'><div class='k'>稳健性评分(0~1)</div><div class='v'>0.57</div></div></div>
<div class='note'>稳健性中等:有一定高原但峰值仍较突出,建议在高原内偏离峰值一点的位置选参以留安全边际。</div>
<div class='note'><b>推荐参数(最大高原中心)</b>FastMA = <code>10</code>SlowMA = <code>40</code>。该位置周围 5 个网格点 PF 均值 1.399,对参数扰动不敏感。</div>
<h2>1. 响应面热力图(找高原用)</h2>
<svg viewBox="0 0 560 420" class="chart"><text x="280" y="12" font-size="11" fill="#374151" text-anchor="middle">PF 响应面热力图(FastMA × SlowMA</text><rect x="70" y="18" width="30" height="10" fill="rgb(220,60,60)"/><text x="85" y="42" font-size="8" fill="#374151" text-anchor="middle">0.83</text><rect x="100" y="18" width="30" height="10" fill="rgb(196,123,76)"/><text x="115" y="42" font-size="8" fill="#374151" text-anchor="middle">1.12</text><rect x="130" y="18" width="30" height="10" fill="rgb(172,188,92)"/><text x="145" y="42" font-size="8" fill="#374151" text-anchor="middle">1.41</text><rect x="160" y="18" width="30" height="10" fill="rgb(140,212,92)"/><text x="175" y="42" font-size="8" fill="#374151" text-anchor="middle">1.70</text><rect x="190" y="18" width="30" height="10" fill="rgb(100,196,76)"/><text x="205" y="42" font-size="8" fill="#374151" text-anchor="middle">1.99</text><rect x="220" y="18" width="30" height="10" fill="rgb(60,180,60)"/><text x="235" y="42" font-size="8" fill="#374151" text-anchor="middle">2.28</text><rect x="70.0" y="306.0" width="79.0" height="64.0" fill="rgb(204,101,70)" stroke="#fff" stroke-width="0.5"><title>5, 20: 1.017</title></rect><text x="109.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">1.02</text><rect x="149.0" y="306.0" width="79.0" height="64.0" fill="rgb(191,135,78)" stroke="#fff" stroke-width="0.5"><title>10, 20: 1.169</title></rect><text x="188.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">1.17</text><rect x="228.0" y="306.0" width="79.0" height="64.0" fill="rgb(194,127,76)" stroke="#fff" stroke-width="0.5"><title>15, 20: 1.132</title></rect><text x="267.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">1.13</text><rect x="307.0" y="306.0" width="79.0" height="64.0" fill="rgb(192,133,78)" stroke="#fff" stroke-width="0.5"><title>20, 20: 1.163</title></rect><text x="346.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">1.16</text><rect x="386.0" y="306.0" width="79.0" height="64.0" fill="rgb(210,85,66)" stroke="#fff" stroke-width="0.5"><title>25, 20: 0.942</title></rect><text x="425.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">0.94</text><rect x="465.0" y="306.0" width="79.0" height="64.0" fill="rgb(220,60,60)" stroke="#fff" stroke-width="0.5"><title>30, 20: 0.827</title></rect><text x="504.5" y="341.0" font-size="9" fill="#111827" text-anchor="middle">0.83</text><rect x="70.0" y="242.0" width="79.0" height="64.0" fill="rgb(193,131,77)" stroke="#fff" stroke-width="0.5"><title>5, 30: 1.152</title></rect><text x="109.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.15</text><rect x="149.0" y="242.0" width="79.0" height="64.0" fill="rgb(193,130,77)" stroke="#fff" stroke-width="0.5"><title>10, 30: 1.148</title></rect><text x="188.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.15</text><rect x="228.0" y="242.0" width="79.0" height="64.0" fill="rgb(181,162,85)" stroke="#fff" stroke-width="0.5"><title>15, 30: 1.291</title></rect><text x="267.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.29</text><rect x="307.0" y="242.0" width="79.0" height="64.0" fill="rgb(185,150,82)" stroke="#fff" stroke-width="0.5"><title>20, 30: 1.240</title></rect><text x="346.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.24</text><rect x="386.0" y="242.0" width="79.0" height="64.0" fill="rgb(190,139,79)" stroke="#fff" stroke-width="0.5"><title>25, 30: 1.187</title></rect><text x="425.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.19</text><rect x="465.0" y="242.0" width="79.0" height="64.0" fill="rgb(191,134,78)" stroke="#fff" stroke-width="0.5"><title>30, 30: 1.167</title></rect><text x="504.5" y="277.0" font-size="9" fill="#111827" text-anchor="middle">1.17</text><rect x="70.0" y="178.0" width="79.0" height="64.0" fill="rgb(180,165,86)" stroke="#fff" stroke-width="0.5"><title>5, 40: 1.308</title></rect><text x="109.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.31</text><rect x="149.0" y="178.0" width="79.0" height="64.0" fill="rgb(170,192,93)" stroke="#fff" stroke-width="0.5"><title>10, 40: 1.431</title></rect><text x="188.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.43</text><rect x="228.0" y="178.0" width="79.0" height="64.0" fill="rgb(162,213,98)" stroke="#fff" stroke-width="0.5"><title>15, 40: 1.525</title></rect><text x="267.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.52</text><rect x="307.0" y="178.0" width="79.0" height="64.0" fill="rgb(176,176,89)" stroke="#fff" stroke-width="0.5"><title>20, 40: 1.355</title></rect><text x="346.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.35</text><rect x="386.0" y="178.0" width="79.0" height="64.0" fill="rgb(187,146,81)" stroke="#fff" stroke-width="0.5"><title>25, 40: 1.218</title></rect><text x="425.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.22</text><rect x="465.0" y="178.0" width="79.0" height="64.0" fill="rgb(185,151,82)" stroke="#fff" stroke-width="0.5"><title>30, 40: 1.244</title></rect><text x="504.5" y="213.0" font-size="9" fill="#111827" text-anchor="middle">1.24</text><rect x="70.0" y="114.0" width="79.0" height="64.0" fill="rgb(196,122,75)" stroke="#fff" stroke-width="0.5"><title>5, 50: 1.113</title></rect><text x="109.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.11</text><rect x="149.0" y="114.0" width="79.0" height="64.0" fill="rgb(174,180,90)" stroke="#fff" stroke-width="0.5"><title>10, 50: 1.374</title></rect><text x="188.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.37</text><rect x="228.0" y="114.0" width="79.0" height="64.0" fill="rgb(180,165,86)" stroke="#fff" stroke-width="0.5"><title>15, 50: 1.306</title></rect><text x="267.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.31</text><rect x="307.0" y="114.0" width="79.0" height="64.0" fill="rgb(194,127,76)" stroke="#fff" stroke-width="0.5"><title>20, 50: 1.133</title></rect><text x="346.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.13</text><rect x="386.0" y="114.0" width="79.0" height="64.0" fill="rgb(202,107,71)" stroke="#fff" stroke-width="0.5"><title>25, 50: 1.041</title></rect><text x="425.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.04</text><rect x="465.0" y="114.0" width="79.0" height="64.0" fill="rgb(197,120,75)" stroke="#fff" stroke-width="0.5"><title>30, 50: 1.100</title></rect><text x="504.5" y="149.0" font-size="9" fill="#111827" text-anchor="middle">1.10</text><rect x="70.0" y="50.0" width="79.0" height="64.0" fill="rgb(201,110,72)" stroke="#fff" stroke-width="0.5"><title>5, 60: 1.057</title></rect><text x="109.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">1.06</text><rect x="149.0" y="50.0" width="79.0" height="64.0" fill="rgb(192,133,78)" stroke="#fff" stroke-width="0.5"><title>10, 60: 1.159</title></rect><text x="188.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">1.16</text><rect x="228.0" y="50.0" width="79.0" height="64.0" fill="rgb(189,142,80)" stroke="#fff" stroke-width="0.5"><title>15, 60: 1.201</title></rect><text x="267.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">1.20</text><rect x="307.0" y="50.0" width="79.0" height="64.0" fill="rgb(189,141,80)" stroke="#fff" stroke-width="0.5"><title>20, 60: 1.199</title></rect><text x="346.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">1.20</text><rect x="386.0" y="50.0" width="79.0" height="64.0" fill="rgb(60,180,60)" stroke="#fff" stroke-width="0.5"><title>25, 60: 2.281</title></rect><text x="425.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">2.28</text><rect x="465.0" y="50.0" width="79.0" height="64.0" fill="rgb(210,85,66)" stroke="#fff" stroke-width="0.5"><title>30, 60: 0.942</title></rect><text x="504.5" y="85.0" font-size="9" fill="#111827" text-anchor="middle">0.94</text><rect x="70.0" y="114.0" width="316.0" height="128.0" fill="none" stroke="#1e3a8a" stroke-width="2.5" rx="2"/><text x="74.0" y="127.0" font-size="10" fill="#1e3a8a" font-weight="bold">P1</text><text x="109.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">5</text><text x="188.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">10</text><text x="267.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">15</text><text x="346.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">20</text><text x="425.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">25</text><text x="504.5" y="384.0" font-size="9" fill="#374151" text-anchor="middle">30</text><text x="64.0" y="341.0" font-size="9" fill="#374151" text-anchor="end">20</text><text x="64.0" y="277.0" font-size="9" fill="#374151" text-anchor="end">30</text><text x="64.0" y="213.0" font-size="9" fill="#374151" text-anchor="end">40</text><text x="64.0" y="149.0" font-size="9" fill="#374151" text-anchor="end">50</text><text x="64.0" y="85.0" font-size="9" fill="#374151" text-anchor="end">60</text><text x="280" y="416" font-size="10" fill="#374151" text-anchor="middle">FastMA →</text><text x="14" y="210" font-size="10" fill="#374151" text-anchor="middle" transform="rotate(-90 14 210)">SlowMA →</text></svg>
<p class='muted'>粗框 P1/P2/P3 = 检测到的高原(连通高分区域)。高原越宽 = 参数越稳健。</p>
<h2>2. 3D 等距投影曲面</h2>
<svg viewBox="0 0 560 420" class="chart"><text x="280" y="16" font-size="11" fill="#374151" text-anchor="middle">PF 3D 响应面(等距投影)</text><polygon points="312.4,371.2 344.8,383.3 312.4,423.7 280.0,229.8" fill="rgb(202,107,71)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="344.8,328.4 377.2,344.8 344.8,383.3 312.4,371.2" fill="rgb(187,146,81)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="280.0,339.4 312.4,371.2 280.0,229.8 247.6,350.6" fill="rgb(194,127,76)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="377.2,312.6 409.6,335.0 377.2,344.8 344.8,328.4" fill="rgb(190,139,79)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="312.4,290.8 344.8,328.4 312.4,371.2 280.0,339.4" fill="rgb(176,176,89)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="247.6,297.1 280.0,339.4 247.6,350.6 215.2,330.6" fill="rgb(180,165,86)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="409.6,324.7 442.0,359.4 409.6,335.0 377.2,312.6" fill="rgb(210,85,66)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="344.8,285.9 377.2,312.6 344.8,328.4 312.4,290.8" fill="rgb(185,150,82)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="280.0,248.9 312.4,290.8 280.0,339.4 247.6,297.1" fill="rgb(162,213,98)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="215.2,268.5 247.6,297.1 215.2,330.6 182.8,316.2" fill="rgb(174,180,90)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="377.2,276.1 409.6,324.7 377.2,312.6 344.8,285.9" fill="rgb(192,133,78)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="312.4,259.5 344.8,285.9 312.4,290.8 280.0,248.9" fill="rgb(181,162,85)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="247.6,241.3 280.0,248.9 247.6,297.1 215.2,268.5" fill="rgb(170,192,93)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="182.8,282.6 215.2,268.5 182.8,316.2 150.4,309.7" fill="rgb(196,122,75)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="344.8,260.4 377.2,276.1 344.8,285.9 312.4,259.5" fill="rgb(194,127,76)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="280.0,258.3 312.4,259.5 280.0,248.9 247.6,241.3" fill="rgb(193,130,77)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="215.2,237.5 247.6,241.3 215.2,268.5 182.8,282.6" fill="rgb(180,165,86)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="312.4,235.7 344.8,260.4 312.4,259.5 280.0,258.3" fill="rgb(191,135,78)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="247.6,238.0 280.0,258.3 247.6,241.3 215.2,237.5" fill="rgb(193,131,77)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/><polygon points="280.0,235.7 312.4,235.7 280.0,258.3 247.6,238.0" fill="rgb(204,101,70)" stroke="#1f2937" stroke-width="0.3" opacity="0.92"/></svg>
<h2>3. 高原清单</h2>
<table class='data'><thead><tr><th>高原</th><th>面积(格数)</th><th>FastMA 范围</th><th>SlowMA 范围</th><th>PF 均值</th><th>PF 峰值</th></tr></thead><tbody><tr><td>P1</td><td>5</td><td>5~20</td><td>40~50</td><td>1.399</td><td>1.525</td></tr></tbody></table>
<h3>Top-10 单点峰值(对比用,单点 ≠ 稳健)</h3><table class='data'><thead><tr><th>FastMA</th><th>SlowMA</th><th>PF</th></tr></thead><tbody><tr><td>25.0</td><td>60.0</td><td>2.281</td></tr><tr><td>15.0</td><td>40.0</td><td>1.525</td></tr><tr><td>10.0</td><td>40.0</td><td>1.431</td></tr><tr><td>10.0</td><td>50.0</td><td>1.374</td></tr><tr><td>20.0</td><td>40.0</td><td>1.355</td></tr><tr><td>5.0</td><td>40.0</td><td>1.308</td></tr><tr><td>15.0</td><td>50.0</td><td>1.306</td></tr><tr><td>15.0</td><td>30.0</td><td>1.291</td></tr><tr><td>30.0</td><td>40.0</td><td>1.244</td></tr><tr><td>20.0</td><td>30.0</td><td>1.24</td></tr></tbody></table>
<footer>由 param_scan.py 生成 · 高原检测阈值=80分位 · 2026-06-28 02:22</footer>
</div></body></html>