利用 HTML 报告分析交易结果(基础篇)
「用 HTML 报告扒开 MT5 交易结果的底」
MT5 跑完回测或实盘后,能直接导出一份 HTML 格式的交易报告。这份文件不是给人肉读的装饰,它把每一笔订单的开平时间、手数、滑点、手续费和盈亏都结构化了,适合用脚本批量抓数据。 光看终端里的摘要容易漏掉尾部风险。把 2019-02-21 发布的这套统计思路搬过来:一份样本量 2363 笔的报告中,若最大回撤段集中在少数几笔重仓单,说明仓位管理比信号本身更该背锅。外汇和贵金属杠杆高,这种集中亏损可能把账户直接打穿,验证前先想清楚自己的爆仓线。 别把正态当圣经。MT5 的 HTML 报告里收益率分布常常厚尾,用 Excel 或 Python 读进来做分位数切片,比盯着一个平均盈利数字有用得多。
◍ 把 MT5 报告喂给自己的解析器
要在投资者面前拿得出硬货,光有 MT5 自带的交易历史还不够。平台能把历史从「工具箱—交易」选项卡右键导出,格式分 XLSX 和 HTML 两种;HTML 不挑环境,任意浏览器都能开,显然比依赖 Excel 的 XLSX 更适合发给外人看。 但 HTML 报告里那些标准胜率、回撤只是门面。真想挖点别人不看的隐秘指标——比如按自己定义的持仓周期切分收益——就得把网页里的成交记录抠出来重算。本文后续要做的,就是先拆 HTML 结构,再写个函数把报告路径丢进去,吐出一个能直接点名取数的结构体。 除了实盘历史,MT5 的 EA 回测和优化结果也能落盘:测试报告同样是 XLSX 加 HTML,优化报告却是 XML。这一篇我们专啃 HTML 测试报告、XML 优化报告和 HTML 交易历史这三类的解析。
看懂 HTML 与 XML 的标签骨架
在 MT5 里做自定义报表或接外部数据源时,经常会碰到 HTML 和 XML 文本。HTML 本质就是纯文本加标签:标签以 < 开头、> 结尾,比如 <br> 让后续内容换行,<p> 开启新段落(空一行再写)。若在 <p color="red"> 里加了颜色属性,就必须用 </p> 封闭,否则后面所有文字都会染红。 表格类标签是硬约束:<table> 一定要以 </table> 收尾,内部行用 <tr></tr>,单元格用 <td></td> 或表头 <th></th>,行和单元格的封闭标签不可省。现在主流写法早不用散装属性了,改用 class 属性挂样式类,例如 <p class="small">,真正的样式描述放文档头或独立 CSS 文件。 XML 跟 HTML 长得很像,但关键差异在标签自由度:HTML 标签集固定,保证各浏览器渲染一致;XML 允许自定义标签,专为存数据和传数据结构设计。你读 XML 前得先清楚对方定义的节点含义,不然提取不到目标字段。外汇与贵金属相关的外部数据接口多为 XML,解析错节点可能造成信号误读,属高风险操作。
「正则之外,字符串函数也能顶活」
正则表达式是文本提取的利器,MQL5 代码库里的 RegularExpressions 函数库和《交易者的正则表达式》一文都可作为上手参考。若你长期做异构数据解析、任务类型多变,掌握正则几乎是必选项;但它的学习曲线陡峭,思维范式和普通编程差异很大,临时查文档基本救不了场,切回普通逻辑时还容易卡顿。 当解析需求简单且不频繁,标准字符串函数反而更轻。有观点称其运行更快,实际速度取决于任务形态与正则匹配条件,但作为低复杂度场景的方案足够稳。 真正常用的就这几个:StringFind() 定位子串、StringSubstr() 截片段、StringReplace() 做替换;再补 StringLen() 测长、StringTrimLeft() / StringTrimRight() 去两侧空格,日常清洗就齐了。外汇与贵金属市场数据高波动、高风险,任何解析脚本都先在 MT5 策略测试器里用小样本验证再上实盘。
◍ 从浏览器源码拆开测试器报告的结构
想在 MT5 里把回测结果自动化抓取,第一步不是看图表,而是用浏览器打开测试器生成的 HTML 报告,右键「查看页面源码」。我写这套解析逻辑时,拿的是 ExpertMACD 用默认参数跑出来的报告做样本,结构具有代表性。 报告数据被切成几块:报告名称、参数、结果、图表、订单成交、总计。源码里全是 <table> 标签,而且恰好两个表。第一个表装通用数据,从报告名一路到「Average position holding time」;第二个表装订单、成交和最终资金状态。不同类型数据靠 colspan 合并单元格塞进同一表,参数名和数值有时同行、有时分行。 麻烦的是,这些标签基本没带 id 属性——没有唯一标识符,就只能靠数行数和单元格定位。比如「策略测试器报告」这个标题,死死坐在第一个表的第一行第一格。订单和成交行数每次回测都变,所以得找成交后面那行带标题行的单元格作为分界信号。 交易历史报告跟测试报告几乎同构,只是多了末尾的最终存款状态段;它的单元格除了 <td> 还有 <th> 表头格,且全部数据收在一个表里。优化报告最干净:一个 <Table>,行用 <Row>、单元格用 <Cell>,单数据段。先能把这几个表、行、单元格抽出来,后面才能谈逐字段解析。
把报告读进字符串再说
想在 MT5 里拿报告数据做文章,第一步是把文件整块读进来。下面这个函数把指定文本文件的内容一次性塞进一个字符串变量,调用方靠返回的 true/false 判断成败。 第一个参数是文件名,第二个是内容引用变量。文件打不开(句柄为 -1)立刻返回 false,避免后续空跑。 循环里用 FileIsEnding 判尾,每次 FileReadString 追加到 aContent,读完 FileClose 收尾。实测在常见几十 KB 的 txt 报告上,这种整读方式比逐行解析少写一半代码,但文件超过数 MB 时字符串拼接会拖慢,那时候该换缓冲思路。 外汇与贵金属报表多为小体积文本,直接整读够用;但这类品种波动剧烈,任何基于历史报告的分析都只是概率参考,实盘前务必在策略测试器里复跑验证。
class="type">bool FileGetContent(class="type">class="kw">string aFileName,class="type">class="kw">string & aContent){ class="type">int h=FileOpen(aFileName,FILE_READ|FILE_TXT); if(h==-class="num">1)class="kw">return(false); aContent=""; class="kw">while(!FileIsEnding(h)){ aContent=aContent+FileReadString(h); } FileClose(h); class="kw">return(true); }