开发回放系统 市场模拟(第 14 部分):模拟器的诞生(IV)·综合运用
(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 序列是否触碰高低点。
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 仿真本身高风险,该写法仅用于回测数据构造,实盘直接套用可能扭曲成交假设。
}
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 里加载看重放表现;外汇和贵金属模拟虽无真金白银风险,但策略逻辑错配照样亏,练手前先确认自己改了哪些参数。 下一阶段就是把随机游走的尾巴收掉,同时把订单接进模拟器,这一步才是能拿来练交易反应的关键。