量化交易软件:交易机器人在市场发布前必须经过的检验

怎样快速捕捉和修复交易机器人中的错误
平台中集成的策略测试器不仅允许回测交易系统,而且可以用于发现交易机器人开发过程中的逻辑和算法错误,在测试中,所有有关交易操作的消息以及发现的错误都输出在测试器的日志(Journal)中。使用特别的记录阅读器就可以很方便地分析这些消息, 它可以使用上下文菜单的命令调用出来。
编辑搜图
在EA交易的测试之后,打开阅读器并启用"只显示错误(Error only)"模式,如上图所示。如果您的交易机器人包含错误,您就能立即看到它们。如果第一次没有侦测到错误,可以在不同的交易品种/时段/输入参数以及不同数量的初始存款情况下进行一系列的测试。使用这些简单的技巧可以发现 99% 的错误,并且赫兹量化会在本文中讨论它们。
赫兹量化可以使用在 MetaEditor 中的在历史数据上做调试的功能来仔细研究发现的错误,通过这个方法,赫兹量化可以使用可视化测试模式,不仅监控价格图表和使用的指标,也能跟踪程序在每个时刻的变量数值。这样,您就能够调试您的交易策略了,而不必在实时模式下花费很长时间。
资金不足以进行交易操作
在发送每个交易订单之前,需要检查账户是否有足够的资金,缺乏资金以进行未来的建仓或者订单会被认为是疏忽大意的。
请一定要记住就算设置一个挂单也可能会要求担保 — 保证金。
编辑搜图
赫兹量化推荐特意使用很小的初始存款来测试交易机器人,例如,1美元或者1欧元。
如果检查显示,资金不足以进行交易操作,就有必要在记录中输出一个错误消息而不是调用 OrderSend() 函数。检验实例:
MQL5
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
{//--- 取得建仓价格 MqlTick mqltick;
SymbolInfoTick(symb,mqltick);
double price=mqltick.ask;
if(type==ORDER_TYPE_SELL)
price=mqltick.bid;//--- 所需以及可用保证金的数值 double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- 调用检验函数 if(!OrderCalcMargin(type,symb,lots,price,margin))
{
//--- 出错了,发送报告并返回 false Print("有错误出现在 ",__FUNCTION__," 编号=",GetLastError());
return(false);
}
//--- 如果资金不够进行操作 if(margin>free_margin)
{
//--- 报告错误并返回 false Print("资金不足以进行 ",EnumToString(type)," ",lots," ",symb," 错误编号=",GetLastError());
return(false);
}//--- 检验成功 return(true);
}
MQL4
bool CheckMoneyForTrade(string symb, double lots,int type)
{
double free_margin=AccountFreeMarginCheck(symb,type, lots);
//-- 如果资金不够 if(free_margin<0)
{
string oper=(type==OP_BUY)?"买入":"卖出";
Print("资金不足以进行", oper," ",lots, " ", symb, " 错误编号",GetLastError());
return(false);
}
//--- 检验成功 return(true);
}
交易操作中的无效交易量
在发送交易订单之前,也有必要检查在订单中指定的交易量的正确性,EA交易中订单设置的手数必须在调用 OrderSend() 函数之前进行检查,交易品种所允许的最小和最大交易量,以及交易量之间的步长是在规格说明中指定的。在 MQL5 中, 这些数值可以通过ENUM_SYMBOL_INFO_DOUBLE 枚举,在SymbolInfoDouble()函数的帮助下获得。
SYMBOL_VOLUME_MIN
交易的最小交易量
SYMBOL_VOLUME_MAX
交易的最大交易量
SYMBOL_VOLUME_STEP
执行交易时最小的交易量变化步长
检查交易量正确性函数的实例
//+------------------------------------------------------------------+//| 检查订单交易量的正确性 |//+------------------------------------------------------------------+bool CheckVolumeValue(double volume,string &description)
{//--- 交易操作允许的最小交易量 double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
if(volume<min_volume)
{
description=StringFormat("交易量小于允许的最小交易量,SYMBOL_VOLUME_MIN=%.2f",min_volume);
return(false);
}//--- 交易操作允许的最大交易量 double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
if(volume>max_volume)
{
description=StringFormat("交易量大于允许的最大交易量,SYMBOL_VOLUME_MAX=%.2f",max_volume);
return(false);
}//--- 取得交易量变化的最小步长 double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
int ratio=(int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step-volume)>0.0000001)
{
description=StringFormat("交易量不是最小交易步长的整数倍,SYMBOL_VOLUME_STEP=%.2f, 最接近的正确交易量是 %.2f",
volume_step,ratio*volume_step);
return(false);
}
description="正确的交易量数值";
return(true);
}
挂单的限制数量
账户中允许同时设置的活动挂单的数量可能也会有所限制。IsNewOrderAllowed() 函数的实例, 它用来检查是否还允许继续设置挂单。
//+------------------------------------------------------------------+//| 检查是否还允许设置订单 |//+------------------------------------------------------------------+bool IsNewOrderAllowed()
{//--- 取得账户中允许设置的挂单数量 int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);//--- 如果没有限制,返回 true; 您可以发送一个订单 if(max_allowed_orders==0) return(true);//--- 如果我们达到这一行,说明有限制; 找出已经设置了多少挂单 int orders=OrdersTotal();//--- 返回比较结果 return(orders<max_allowed_orders);
}
这个函数很简单: 取得允许的最大订单数并赋予max_allowed_orders变量; 如果它不等于0,把它与当前订单数量做比较。但是,这个函数没有考虑到另外的可能的限制 - 对某一特定交易品种开启仓位总交易量的限制和挂单数量的限制。
某特定交易品种的手数限制
为了取得某一特定交易品种的开启仓位的总交易量,首先您需要使用PositionSelect()函数来选择一个仓位,之后您就可以使用PositionGetDouble()来得到已建仓位的交易量, 它可以返回双精度类型的所选仓位的各种属性。让我们写一个 PostionVolume() 函数来取得所需交易品种的仓位交易量。
//+------------------------------------------------------------------+//| 返回指定交易品种的仓位大小 |//+------------------------------------------------------------------+double PositionVolume(string symbol)
{//--- 尝试根据交易品种选择仓位 bool selected=PositionSelect(symbol);//--- 有仓位 if(selected)
//--- 返回仓位交易量 return(PositionGetDouble(POSITION_VOLUME));
else {
//--- 选择仓位出错报告 Print(__FUNCTION__," 执行 PositionSelect() 失败,交易品种为 ",
symbol," 错误编号 ",GetLastError());
return(-1);
}
}
对于支持对冲的账户,还需要迭代当前交易品种所有的仓位。
在根据交易品种生成交易请求以设置挂单之前, 您应该检查在一个交易品种上的已开启仓位和挂单总交易量的限制 - SYMBOL_VOLUME_LIMIT,如果没有限制,那么挂单的总交易量不能超过使用SymbolInfoDouble()得到的最大交易量。