盈利的回测与实盘灾难之间的差异,往往归结为一个问题:未来函数泄漏。MT4的策略测试器无法检测你的EA在决策时使用了当时不可用的价格数据这一逻辑错误。
K线偏移规则
最常见的未来函数是在K线收盘前访问
Close[0]或High[0]。在实盘交易中,Close[0]不断变化。在"每笔报价"模式的回测中,Close[0]在K线开盘时等于Open[0],但在K线收盘时等于Close[0]——这就产生了前视偏差。安全实现:偏移1使用
``
cpp
// MQL4 - 仅使用已收盘K线数据的安全入场条件
input double LotSize = 0.1;
input int FastMA = 5;
input int SlowMA = 20;
bool ShouldBuy() {
// 使用索引1和2 - 决策绝不使用0
double FastMA_prev = iMA(NULL, 0, FastMA, 0, MODE_SMA, PRICE_CLOSE, 1);
double FastMA_current = iMA(NULL, 0, FastMA, 0, MODE_SMA, PRICE_CLOSE, 2);
double SlowMA_prev = iMA(NULL, 0, SlowMA, 0, MODE_SMA, PRICE_CLOSE, 1);
// 使用完全收盘的K线检测金叉
if(FastMA_prev > SlowMA_prev && FastMA_current <= SlowMA_current) {
return true;
}
return false;
}
// 带错误处理的安全开仓代码
int OpenBuyOrder() {
if(!ShouldBuy()) return -1;
double sl = Bid - 50 Point;
double tp = Bid + 100 Point;
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "EA Entry", 0, 0, Green);
if(ticket < 0) {
Print("OrderSend失败: ", GetLastError());
return -1;
}
return ticket;
}
``数据挖掘偏差公式
通过随机因素找到至少一个盈利策略的概率随测试次数增加而上升:
\[
P(\text{至少一个假阳性}) = 1 - (1 - \alpha)^n
\]
其中 \( \alpha \) 为显著性水平(通常取0.05),\( n \) 为测试的策略/参数数量。测试100次时,假阳性的概率达到99.4%。
最小样本外K线数量要求
为实现统计有效的回测结果,所需的最小交易次数 \( N \):
\[
N = \left( \frac{Z_{\alpha/2} \cdot \sigma}{\delta} \right)^2
\]
其中 \( \sigma \) 为收益标准差,\( \delta \) 为预期回撤容忍度,\( Z_{\alpha/2} = 1.96 \)(对应95%置信度)。对于日线策略,这通常需要3-5年的数据。
每次回测后的三个验证步骤
Tick模拟的局限性
MT4的"控制点"和"仅开盘价"模式不足以验证止损和移动止损。当测试带有挂单、止损或止盈的策略时,始终使用"每笔报价"模式。不同Tick模式之间的最大不利偏移(MAE)差异可超过30%。
参考来源:MQL4社区 - 回测最佳实践(https://www.mql5.com/en/articles/1519),《基于证据的技术分析》David Aronson 著,2006年。