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

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

(3/3)·从自由随机游走到约束化生成,收尾模拟器诞生的最后一块拼图

实战向进阶 第 3/3 篇
很多人拿到模拟器生成的数据却不会分析,导致后续扩展无从下手。其实只要理清随机游走的约束逻辑,复杂行情合成就有了根基。本文顺着前两篇的铺垫,把模拟器收尾成型。

◍ 用随机游走把K线拆成逐笔成交

想把 MT5 的整根 K 线还原成近似真实的逐笔 tick,常见做法是按 real_volume 与 tick_volume 的差值补量,再在 high/low 区间内做随机步进。下面这段逻辑就是典型实现:先给首 tick 挂上 K 线开盘时间,尾 tick 绑定收盘价,中间缺失的成交量随机摊到已有 tick 上。 步进核心在 for 循环里:每个 tick 价格 = 上一 tick 加减一个最小跳点 m_PointsPerTick,方向由 rand() 奇偶决定。若算出的 v0 超过本根 high,就强制向下调一个跳点;低于 low 则向上调,保证模拟轨迹不破区间。 bLowOk / bHighOk 两个布尔在循环里持续刷新,只要某次 v0 精确等于 rate.low 或 rate.high 就置真。实盘外汇与贵金属波动极快、跳空频繁,这种合成 tick 仅用于回测环境验证策略,真实风险远高于模拟。 直接把代码贴进 EA 的 tick 构造函数,把 m_PointsPerTick 设成你品种的标准点值(比如 XAUUSD 常取 0.01),跑一根 M1 看合成的 tick 序列是否触碰高低点。

MQL5 / C++
tick[c0].time = rate.time + (class="type">class="kw">datetime) (il0 / class="num">1000);
tick[c0].time_msc = il0 % class="num">1000;
tick[c0].volume_real = class="num">1.0;
}
tick[class="num">0].last = rate.open;
tick[max].last = rate.close;
for (class="type">int c0 = (class="type">int)(rate.real_volume - rate.tick_volume); c0 > class="num">0; c0--)
   tick[macroRandomLimits(class="num">0, max)].volume_real += class="num">1.0;
bLowOk = bHighOk = class="kw">false;
for (class="type">int c0 = class="num">1; c0 < max; c0++)
{
   v0 = tick[c0 - class="num">1].last + (m_PointsPerTick * ((rand() & class="num">1) == class="num">1 ? class="num">1 : -class="num">1));
   if (v0 <= rate.high)
      v0 = tick[c0].last = (v0 >= rate.low ? v0 : tick[c0 - class="num">1].last + m_PointsPerTick);
   else
      v0 = tick[c0].last = tick[c0 - class="num">1].last - m_PointsPerTick;
   bLowOk = (v0 == rate.low ? true : bLowOk);
   bHighOk = (v0 == rate.high ? true : bHighOk);

用随机槽位回填缺失极值

这段逻辑处理的是 tick 序列里高低点缺失的修补:先按总样本数 max 的 0.3 倍算出偏移量 il0,即 il0 = (long)(max * 0.3),把前 30% 区间留给低价回填、后段留给高价回填。 若 bLowOk 为假,就在 macroRandomLimits(il0, il0*2) 决定的随机下标处把 rate.low 写进 tick[].last;高价同理落在 max-il0 到 max 之间。这样造出的序列在统计上高低点分布不会死板集中在两端。 随后用 for 循环把 tick[0..max] 逐个通过 ArrayResize 追加进 m_Ticks.Info,nTicks 同步自增;循环结束 #undef 掉 macroRandomLimits 宏。外汇与贵金属 tick 仿真本身高风险,该写法仅用于回测数据构造,实盘直接套用可能扭曲成交假设。

MQL5 / C++
      }
      il0 = (class="type">long)(max * (class="num">0.3));
      if (!bLowOk) tick[macroRandomLimits(il0, il0 * class="num">2)].last = rate.low;
      if (!bHighOk) tick[macroRandomLimits(max - il0, max)].last = rate.high;
      for (class="type">int c0 = class="num">0; c0 <= max; c0++)
      {
         ArrayResize(m_Ticks.Info, (m_Ticks.nTicks + class="num">1), def_MaxSizeArray);
         m_Ticks.Info[m_Ticks.nTicks++] = tick[c0];
      }
class="macro">#undef macroRandomLimits
      }

「回放服务收尾前还差一口气」

随机游走这套逻辑已经讲完,但配套的回放/模拟服务还没真正交付。当前附带的 Market_Replay_nvc_14_.zip 约 10.3 MB,里面是开发中途状态的系统,能跑通基础行情重放,却还没有订单模块。 作者留的话很直白:订单系统要等回放服务彻底成型再动,因为那时才能像真实市场一样挂单成交。现在服务只差少量细节,补完就能进订单开发。 想提前摸手的,直接下 ZIP 在 MT5 里加载看重放表现;外汇和贵金属模拟虽无真金白银风险,但策略逻辑错配照样亏,练手前先确认自己改了哪些参数。 下一阶段就是把随机游走的尾巴收掉,同时把订单接进模拟器,这一步才是能拿来练交易反应的关键。

把重复劳动交给小布
这些诊断与回放生成流程里耗时的数据导出和格式校验,小布盯盘的 AIGC 已内置,打开对应品种页即可看到,你只需专注策略逻辑本身。

常见问题

宏通过位运算与归一化把随机值钳制在指定区间,避免额外分支判断,让基础函数保持简洁,也方便后续复杂函数复用同一思路。
目前小布盯盘内置的是行情诊断与 AIGC 摘要,回放文件需先按知识库格式导出,后续版本可能开放自定义回放通道,外汇贵金属波动高风险,请先小额验证。
自由版图形杂乱无规律,仅用于理解最底层机制;约束版加入范围与偏移控制,更接近真实报价分布,是模拟器落地的前提。
会有断层,建议回看《开发回放系统 市场模拟·基础篇》与《开发回放系统 市场模拟·实战篇》再接着读,否则宏背后的设计动机可能不好消化。