如何基于HTML和CSV报表可视化多币种交易历史·综合运用
📘

如何基于HTML和CSV报表可视化多币种交易历史·综合运用

第 3/3 篇

「清理残留的副图指标」

在 MT5 脚本里批量移除旧版副图指标,最直接的方式是遍历图表上的指标槽位,用前缀做匹配。下面这段代码针对名称为 "SubChartReporter" 开头的指标执行删除,避免手动一个个右击移除的低效操作。 [CODE] string name = ChartIndicatorName(0, i, 0); if(StringFind(name, "SubChartReporter") == 0) { Print("Deleting ", name); result &= ChartIndicatorDelete(0, i, name); } } return result; } [/CODE] 逐行拆解:第 1 行用 ChartIndicatorName 取当前图表(0 号)、第 i 个窗口、第 0 子项的指标名;第 2 行 StringFind 返回 0 表示名字以 "SubChartReporter" 起头;第 4 行 Print 仅打印日志便于排查;第 5 行 ChartIndicatorDelete 执行删除,并用 &= 累积成功标记;末尾 return 把整体结果交回调用方。 实盘前先在 EURUSD 的 M1 上挂两个同名测试指标跑一遍,确认无残留再用于正式模板。外汇与贵金属杠杆高,误删正在计算的信号指标可能让策略短暂失聪,操作前建议先存模板。

MQL5 / C++
class="type">class="kw">string name = ChartIndicatorName(class="num">0, i, class="num">0);
if(StringFind(name, "SubChartReporter") == class="num">0)
{
Print("Deleting ", name);
result &= ChartIndicatorDelete(class="num">0, i, name);
}
}
class="kw">return result;
}

◍ 主图指标怎么甩掉缓冲区

MainChartReporter 直接画在主图窗口,不需要任何指标缓冲区,也不画趋势以外的对象。它会在 apply 里把当前图表切到真实分析品种,并留一行 Comment 显示标题,逻辑上就是 SubChartReporter 的精简版。 三个核心类 Processor、ReportProcessor、HistoryProcessor 被挪进共用头文件,靠 CHART_REPORTER_MAIN 与 CHART_REPORTER_SUB 两个宏做条件编译区分。主图版只加两行切换品种和注释,子图版才保留按 _Symbol 重绘的兼容代码。 原缓冲相关声明全部删掉:indicator_buffers 设 0、indicator_plots 设 0,子窗口参数组一并移除。OnCalculate 留空函数壳,数据拉取完全交给 OnInit 里启动的定时器。 代码里有一段 ChartNavigate 试图滚到首笔交易位置,作者实测从未生效——图表不会被移动。更稳的思路是用 CHART_CURRENT_POS 基于当前位置相对导航,但样本里没采用。外汇与贵金属品种切换涉及实时报价,实操请先在模拟盘验证高风险。

MQL5 / C++
class="macro">#ifdef CHART_REPORTER_MAIN
      ChartSetSymbolPeriod(class="num">0, real, _Period);
class="macro">#endif
class="macro">#ifdef CHART_REPORTER_MAIN
      Comment(title);
class="macro">#endif
class="macro">#ifdef CHART_REPORTER_SUB
            ChartSetSymbolPeriod(class="num">0, _Symbol, _Period);
class="macro">#endif
class="macro">#class="kw">property indicator_chart_window
class="macro">#class="kw">property indicator_buffers class="num">0
class="macro">#class="kw">property indicator_plots   class="num">0
class="kw">input GroupSettings Chart_Settings; class=class="str">"cmt">// 子图表设置
class="kw">input class="type">class="kw">string SubSymbol = ""; class=class="str">"cmt">// · 交易品种
class="kw">input class="type">bool Exact = true; class=class="str">"cmt">// · Exact
class="type">void OnTimer()
{
  EventKillTimer();
  
  if(processor.isEmpty()) class=class="str">"cmt">// 只载入一次文件
  {
    if(processor.attach(ReportFile))
    {
      processor.apply();
      class="type">class="kw">datetime start = processor.getStart();
      if(start != class="num">0)
      {
        ChartSetInteger(ChartID(), CHART_AUTOSCROLL, class="kw">false);
        class=class="str">"cmt">// FIXME: 这里没有正确工作
        ChartNavigate(ChartID(), CHART_END, -class="num">1 * (iBarShift(_Symbol, _Period, start)));
      }
    }
  }
}

别急着下结论

把多品种报价和成交记录画到一张图上看,核心输入不一定是 MT5 自带报表。用通用解析器吃 HTML,再补一层 CSV 支持,就能把信号历史也拉进来——俄文原版工程里那套 report2chart 就是这么干的,ZIP 包 34.55 KB,开源可改。 MQL 环境有个坑:编译器不保证向后兼容,老头文件在新版 MT5 可能直接编不过。上面讨论区里有人 2020 年 1 月换掉两个头文件才跑通,说明你下载源码后第一件事不是拖进图表,而是核对构建版本。 下面这三行是原文里顺手给出的水平线画法,能在图表上标出当前收盘价参考线,自己开 MT5 新建脚本粘进去就能验证: ObjectCreate 建一条名为 Close 的水平线,绑定到子窗口 1;ObjectSetInteger 把颜色设成浅石板灰;ObjectMove 按 close[0] 重定位。外汇和贵金属波动大,这类参考线只是视觉辅助,不代表方向判断。

MQL5 / C++
 ObjectCreate(NULL,"Close",OBJ_HLINE,class="num">1,class="num">1,close[class="num">0]);
 ObjectSetInteger(class="num">0,"Close",OBJPROP_COLOR,clrLightSlateGray);
 ObjectMove(class="num">1,"Close",class="num">1,class="num">1,close[class="num">0]);

常见问题

先停掉报表刷新,手动移除副图对象再重载 CSV,避免旧缓冲区继续渲染干扰看图。
在生成可视化前重置指标数组长度并只写入有效数据,导出时剔除空值列即可。
可以,小布能读取你的 CSV 并自动识别副图残留,一键生成干净的主图可视化供你核对。
多是时区或平仓计算字段解析错位,检查报表导出格式并统一时间戳后再渲染。
别急着下结论,单币种短期回撤可能只是样本少,拉长时间和总样本再看胜率更稳。