我对MT4的策略测试器真是又爱又恨。这玩意儿回测起来确实给力,但一旦你碰上“历史数据不可用”这个报错,或者在实盘里被“交易上下文繁忙”卡住的时候,那份爱意瞬间就烟消云散了。
这两个错误出现的频率其实不低,但你真去搜解决方案的时候,会发现网上有价值的资料少得可怜。大部分论坛的回复就两招:“重启MT4”或者“重装”。这跟告诉你“车胎爆了就去买辆新车”一样,虽然能解决,但成本太高,而且你永远搞不清楚真正的原因。我们今天就把这个问题拆透了。
问题一:神出鬼没的“历史数据不可用”报错
正打算跑回测,EA加载好了,品种也选对了,一点“开始”,结果弹出个“历史数据不可用于[品种名]”。遇到这种情况,正常人第一反应都是觉得经纪商的数据服务器宕机了,或者MT4安装文件坏了。有时候确实是这样,但更多时候,是一个很容易被忽略的文件夹权限问题。
几个月前我测试一个新头皮策略的时候就撞上了这堵墙。我那台主力机上回测跑得顺顺当当,换到VPS上就死活报“历史数据不可用”。排查了半天,差点没把键盘砸了,最后才发现问题出在VPS那套更严的文件夹权限设置上。
下面这个检查方法,能解决90%这类问题:
MQL4 > Tester。打开之后会看到按品种命名的文件夹。如果你要测试的那个品种对应的文件夹是空的,或者压根没有,那基本就破案了——测试器需要往这里面写入缓存文件,写不进去自然就给你报“历史不可用”。Tester文件夹的“保护”似乎格外上心,尤其是当你把MT4装在Program Files目录下的时候。平台想往里写数据,系统给拦了,但反馈给MT4的却是个模棱两可的“历史不可用”,压根不提权限的事。我当时的一个临时诊断操作是:手动把MT4根目录下history文件夹里的历史数据文件,复制到MQL4/Tester里对应的品种文件夹下。结果你猜怎么着?回测一下子就跑起来了。这个操作不是正规解决方案,但它是个极好的诊断手段——如果这招管用,那罪魁祸首100%就是写入权限;如果还不行,那问题大概率出在经纪商的数据源本身。MQL4文件夹,选“属性”,进“安全”选项卡,确保你的用户账户有“完全控制”权限。点应用,关掉MT4再重开,问题解决。MetaQuotes官方文档里只说了测试器会从经纪商服务器获取历史数据,但压根没提本地缓存和权限这茬。这就是那种你不踩坑就永远学不到的实战经验。
问题二:令人抓狂的“交易上下文繁忙”报错
这玩意是EA开发者的噩梦。你写了一个逻辑完美的机器人,开平仓都正常,突然某一天,它不动了。每次试图下单都给你弹个“交易上下文繁忙”,或者“市场已关闭”(但明明开着盘)。
网上搜出来的结果基本都指向一个原因:你的EA代码里没有做错误处理。这个说法没错,但还有一层更深、更冷门的原因,几乎没人提——EA试图执行交易操作的速度,超过了服务器返回确认的速度。
之前帮一个客户修一个网格EA,我花了一整天时间追这个问题。代码写得挺工整,该做的错误处理也都做了,但一到波动剧烈的新闻时段就直接卡死。最后解决的办法不只是加一句
Sleep(100);那么简单:OrderSend()或OrderModify()之前,必须先调RefreshRates()来刷新内部的市场数据(比如Ask和Bid)。这个操作听起来基础,但我见过太多EA只在OrderSend()里写了这句,OrderModify()和OrderClose()里完全不管。这个小小的不匹配,足以把交易上下文锁死——因为EA拿着过时的价格去下单,服务器一拒绝,上下文就卡在那儿不转了。ERR_TRADE_CONTEXT_BUSY这个错误码做处理。最近一次救急的时候,我用了下面这段代码:``
mq4
int retry = 0;
while(retry < 5)
{
RefreshRates();
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Comment", 0, 0, Green);
if(ticket > 0) break;
if(GetLastError() == ERR_TRADE_CONTEXT_BUSY)
{
Sleep(1000);
retry++;
}
else
{
// 处理其他类型的报错
break;
}
}
``参考来源:MQL4官方文档 – OrderSend和RefreshRates(docs.mql4.com),MetaQuotes帮助中心 – 策略测试器(help.metaquotes.net)。
本文首发于FXEAR.com,原创内容,未经授权禁止转载。