开发回放系统  市场模拟(第 13 部分):模拟器的诞生(III)·综合运用
📘

开发回放系统 市场模拟(第 13 部分):模拟器的诞生(III)·综合运用

第 3/3 篇

把1分钟柱线拆成跳价看随机游走

做市场重放最绕的一步,是在1分钟柱线里模拟所有可能的跳价轨迹。这里要造的不是纯随机噪声,而是带数学约束的随机游走:起点和终点已知,中间过程塞进随机性,短期走势仍不可预测。 新手常以为调个随机数生成器、再把数值夹在某个区间就够用了。实际画出来是一团乱麻——下图就是这种跳点连成的走势,乍看根本不像随机游走,但本质就是时间点之间硬跳的结果。每行数据对应一根1分钟柱,附件里能拿到原始序列自己验证。 为了在MT5里抓出模拟器怎么填跳价,我们在服务文件先开两个定义做旁路检查,再把数据写进CSV用Excel画图。MT5自身也能画,但信息量一大就糊成一团,Excel更直白。注意服务会报一条错,只要确认def_TEST_SIMULATION已定义直接忽略即可。 别把正态当圣经 单纯把模拟计算写复杂,并不保证走出真随机游走。每根柱线都该是独一份的轨迹;想让柱间走势雷同,就在调用前写死一个起始值。下面这段代码就是旁路记录跳价数组用的骨架,复制去建个Info.csv就能看到自己的游走图形。

MQL5 / C++
class="macro">#define def_TEST_SIMULATION
class="macro">#ifdef def_TEST_SIMULATION
	class="macro">#define def_FILE_OUT_SIMULATION "Info.csv"
class="macro">#endif
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property service
class="macro">#class="kw">property icon "\Images\Market Replay\Icon.ico"
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property version   "class="num">1.13"
class=class="str">"cmt">// ... The rest of the code...
					class="type">bool LoadBarsToTicksReplay(const class="type">class="kw">string szFileNameCSV)
							{
								class="type">int file;
								class="type">MqlRates rate[class="num">1];
								class="type">MqlTick tick[];
								
								if (OpenFileBars(file, szFileNameCSV))
								{
											Print("Converting bars to ticks. Please wait...");
											ArrayResize(m_Ticks.Info, def_MaxSizeArray, def_MaxSizeArray);
											ArrayResize(tick, def_MaxSizeArray);
											while ((!FileIsEnding(file)) && (!_StopFlag))

◍ 把 CSV 棒线重采样成逐笔 tick 的落地代码

这段逻辑干的事很直接:从 CSV 读入 OHLC 棒线,在调试宏 def_TEST_SIMULATION 开启时,把模拟出的逐笔 last 价写回另一个 ANSI 文本,方便拿去和真实 tick 比对。外汇与贵金属价差跳变频繁,这种重采样仅用于回测假设,实盘滑点可能让结论偏移。 核心循环里 FileReadBars 把棒线塞进 rate 数组,Simulation(rate[0], tick) 以首棒为起点生成 tick 流;m_Ticks.nTicks 记录总数,循环上限就是它。若定义了 def_TEST_SIMULATION,会先关旧文件、开 def_FILE_OUT_SIMULATION 写盘,逐行落 %0.f 格式的 last 值,再释放 tick 数组并返回 false 阻断后续实跑。 正常分支下,OpenFileBars 成功就打印等待提示,把 m_Ticks.Info 和 tick 都预扩到 def_MaxSizeArray;while 里用 FileIsEnding(file) 且非 _StopFlag 作为继续条件,保证用户点停止后能干净退出。复制时留意 def_MaxSizeArray 若设太小,大周期 CSV 会触发多次 ArrayResize,拖慢转换。

MQL5 / C++
{
   FileReadBars(file, rate);
   Simulation(rate[class="num">0], tick);
class="macro">#ifdef def_TEST_SIMULATION
   FileClose(file);
   file = FileOpen(def_FILE_OUT_SIMULATION, FILE_ANSI | FILE_WRITE);
   for (class="type">long c0 = class="num">0; c0 < m_Ticks.nTicks; c0++)
      FileWriteString(file, StringFormat("%class="num">0.f\n", m_Ticks.Info[c0].last));
   FileClose(file);
   ArrayFree(tick);
   class="kw">return class="kw">false;
class="macro">#endif
}
   FileClose(file);
   ArrayFree(tick);
   class="kw">return (!_StopFlag);

   class="kw">return class="kw">false;
}
class=class="str">"cmt">// ... Code ...
   if (OpenFileBars(file, szFileNameCSV))
   {
      Print("Converting bars to ticks. Please wait...");
      ArrayResize(m_Ticks.Info, def_MaxSizeArray, def_MaxSizeArray);
      ArrayResize(tick, def_MaxSizeArray);
      while ((!FileIsEnding(file)) && (!_StopFlag))

「用固定种子跑蒙特卡洛模拟」

把历史 tick 读进内存后,别急着让随机函数自由发挥。先调用 srand(5) 把伪随机序列锁死,这样每次重跑 Simulation 得到的路径分布都可复现,方便你对比参数微调前后的差异。 下面这段就是核心入口:先用 FileReadBars 把汇率数据灌进 rate 数组,再以 rate[0] 和 tick 为初值交给 Simulation。种子写死成 5 不是玄学,只是给你一个稳定的对照基线;换成别的整数也行,但同一次回测里不能变。 外汇与贵金属杠杆高、滑点随机,模拟结果只代表某种概率倾向,实盘可能明显偏离。开 MT5 把这段嵌进 EA,改 srand 里的数字,看方差曲线怎么挪。

MQL5 / C++
{
   FileReadBars(file, rate);
   srand(class="num">5);
   Simulation(rate[class="num">0], tick);
class=class="str">"cmt">// ... The rest of the code...
}

把这条线请下神坛

随机游走模型只是市场微观结构的一种近似投影,别把它当成价格必然遵循的真理。前面几节搭好的回放与模拟框架,核心价值在于让你用可控数据观察走势生成逻辑,而不是预测下一根 K 线。 服务文件里那段条件编译开关直接决定回放系统会不会因为写盘而崩。把 #define def_TEST_SIMULATION 保持注释状态,服务就不会往 Info.csv 输出图形分析数据,否则你每加一组图表数据它就报错。 外汇和贵金属杠杆高、随机性被放大,用这类模拟验证想法可以,但真金白银下单前先想清楚:模型跑通不等于实盘能活。先把今天的服务配置和代码逻辑在 MT5 里跑一遍,比急着追下一篇更重要。

MQL5 / C++
class=class="str">"cmt">//class="macro">#define def_TEST_SIMULATION // <<-- Leave this line as it is to be able to use the replay/simulation service....
class="macro">#ifdef def_TEST_SIMULATION
                class="macro">#define def_FILE_OUT_SIMULATION "Info.csv"
class="macro">#endif 
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property service
class="macro">#class="kw">property icon "\Images\Market Replay\Icon.ico"
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property version   "class="num">1.13"

常见问题

用CSV读入棒线后,按固定种子在高低区间内均匀撒点生成tick序列,再写回文件即可落地重采样。
给MathSrand传一个固定整型常量即可,每次跑模拟前重置种子,蒙特卡洛结果就能稳定复现。
可以,小布盯盘的AIGC已内置重采样与固定种子蒙特卡洛模块,打开对应品种页即可一键跑,不用自己写代码。
固定种子只保证随机过程可复现,市场有跳空与流动性断层,模拟倾向低估极端滑点,仅作概率参考。
不能当圣经,外汇贵金属高风险,模拟线只暴露可能区间,实盘仍需结合当下盘口与风控参数。