开发回放系统  市场模拟(第 04 部分):调整设置(II)·综合运用
📘

开发回放系统 市场模拟(第 04 部分):调整设置(II)·综合运用

第 3/3 篇

「用历史tick文件驱动MT5回放」

想在不接真实行情的情况下复盘某段行情,可以借助 Market Replay 类把历史 tick 文件注入到 MT5 的图表里。下面这段脚本以 WINZ21_202110220900_202110221759 这一小时级别的 tick 文件为例,在 OnStart 里直接拉起回放窗口。 回放不是一启动就自己跑,脚本先等全局变量 def_GlobalVariableReplay 出现(每 750 毫秒轮询一次),拿到权限后才打印「Replay system started」。这一步卡住很正常,没开回放控制面板就会一直 Sleep。 核心推进逻辑在 while 循环:未播放时调 Event_OnTime 探一下有没有待处理事件;播放中则按 delay 节拍走,delay 默认 3 毫秒,若 AdjustPositionReplay 返回 0 就复位成 3,否则沿用返回值。外汇与贵金属回测属高风险,历史tick重播结果只代表该样本表现,换时段可能完全走样。 让小布替你跑这套 把 user01 改成你自己的 tick 文件名(格式 YYYYMMDDHHMM_YYYYMMDDHHMM),编译前确认 Include 路径下有 Market Replay\C_Replay.mqh,否则 CreateSymbolReplay 直接返回失败。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Market Replay\C_Replay.mqh>
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">input class="type">class="kw">string     user01 = "WINZ21_202110220900_202110221759"; class=class="str">"cmt">//File with ticks
class=class="str">"cmt">//+------------------------------------------------------------------+
C_Replay         Replay;
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
{
      class="type">class="kw">ulong t1;
      class="type">int delay = class="num">3;
      class="type">long id;
      u_Interprocess Info;
      class="type">bool bTest = class="kw">false;
      
      if (!Replay.CreateSymbolReplay(user01)) class="kw">return;
      id = Replay.ViewReplay();
      Print("Wait for permission to start replay ...");
      class="kw">while (!GlobalVariableCheck(def_GlobalVariableReplay)) Sleep(class="num">750);
      Print("Replay system started ...");
      t1 = GetTickCount64();
      class="kw">while ((ChartSymbol(id) != "") && (GlobalVariableGet(def_GlobalVariableReplay, Info.Value)))
      {
            if (!Info.s_Infos.isPlay)
            {
                  if (!bTest) bTest = (Replay.Event_OnTime() > class="num">0);
            }else
            {
                  if (bTest)
                  {
                        delay = ((delay = Replay.AdjustPositionReplay()) == class="num">0 ? class="num">3 : delay);
                        bTest = class="kw">false;
                        t1 = GetTickCount64();
                  }else if ((GetTickCount64() - t1) >= (class="type">uint)(delay))
                  {
                        if ((delay = Replay.Event_OnTime()) < class="num">0) class="kw">break;
                        t1 = GetTickCount64();
                  }
            }
      }
}

回放系统的停止与收尾

在 MQL5 回放逻辑里,停止动作往往藏在某个条件分支的末尾,而不是单独写个 Stop 函数。上面这段截断的代码显示,当外层判断不成立时,先闭合内层花括号,再闭合外层花括号,随后调用 Replay.CloseReplay() 释放回放资源,并打印 "Replay system stopped ..." 作为终止信号。 这种写法意味着回放句柄在退出前必须显式关闭,否则 MT5 策略测试器里的可视化回放可能占用内存句柄不释放,再次启动同符号回放时概率出现「旧帧残留」。 复制这段代码到你的 EA 收尾段,把 Print 内容改成带时间戳的自定义串,跑一次 EURUSD 的 M1 回放就能验证关闭是否干净。外汇与贵金属回放涉及杠杆品种,历史重演不代表未来,实盘前务必用小资金验证。

MQL5 / C++
}
}
Replay.CloseReplay();
Print("Replay system stopped ...");
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 回放系统落地前的最后提醒

附件里的 Market_Replay.zip 约 10.8 MB,内附两份真实市场跳价文件,可在不同跳价密度的交易日里试跑移动与定位。当前版本在把光标拖到目标价位点时,移动执行偶有卡顿,作者确认后续会修,但眼下不影响你熟悉整套回放逻辑。 用这套回放真正能练的是市场分析本身,而不是找某个绝对入场点——你看到的走势可能实际发生在几根柱线之后,外汇与贵金属市场高杠杆、跳价稀疏时段尤甚,误把回放里的‘清晰信号’当实盘依据概率上会吃亏。 有读者在评论里问过:EA 能否接管回放服务、停掉图表绘刻?作者回说只需在 EA 里加一行代码即可,但前提是把这行代码在 MT5 里的机制先弄懂,相关文章还没发。想验证的人,现在就能做的动作是:下载 ZIP,用经纪商 tick 数据替换附件样本,跑一遍看百分比推进是否符合你的预期。

常见问题

把整理好的历史tick文件放到对应品种的数据目录,通过回放脚本加载并指定时间范围,即可逐tick重演行情做手动或EA验证。
先暂停回放脚本再关闭图表,导出成交与日志文件;别直接强退终端,否则可能丢最后几秒tick和未写盘的记录。
小布可接管tick回放加载与参数切换,你只需选品种和时段,它能把重复劳动替你做了,你专注看价格行为。
多是tick重建算法或点差模型不一致导致;落地前用同一段行情对比回放与实盘成交滑点,偏差大就调设置。
贵金属跳空和流动性断层频繁,回放可能平滑了缺口;结论仅作概率参考,实盘前务必用模拟盘过一遍。