多写代码,多看书,坚持虚心学习。

[转]mql4常见问题你问我答

文章转载 博主 126℃ 0评论

如果您遇到任何MQL4编程的问题,可以跟帖提问,我会酌情回答,并将常见问题的应对方法编入此贴当中。你问我答,共同积累,大家努力,才会更好。

Q1:错误编号“4051”描述为“无效参量值函数”,怎么处理?这实际上是指开仓量错误,检测程序中订单操作命令的开仓量变量是否为0,或者不符合交易平台规定的开仓量格式,例如平台规定XAUUSD最小开仓量为0.1,而变量计算结果为0.12,或者0.36,就会该类报错信息。以下提供一个“开仓量整形”的函数,直接调用就不会出现问题了,0.12被规范为0.1,0.36被规范为0.4:
//函    数:开仓量整形
//输入参数:myLots:开仓量
//输出参数:按照平台规则计算开仓量
//算    法:调整不规范的开仓量数据,按照四舍五入原则及平台开仓量格式规范数据
double iLotsFormat(double myLots)

   {
      myLots=MathRound(myLots/MarketInfo(Symbol(), MODE_MINLOT))*MarketInfo(Symbol(), MODE_MINLOT);//开仓量整形
      return(myLots);
   }

Q2:错误编号“1”描述为“没有错误返回但结果不明”,是什么原因?
这类问题通常出在修改止盈、止损价位的程序段中。例如开仓价为1.2222,止损价为1.2202,由于种种原因,比如程序计算止损价位时可能会出现4位小数之后更多的数字,如1.220234,那么就会出现该类报错信息。处理办法是使用NormalizeDouble函数将止损价变量数据规范成了平台能够识别的标准格式。因此建议大家编程时养成对价格变量随时整形的习惯。范例:
myStopLoss=NormalizeDouble(myStopLoss,Digits);

Q3:Sleep()函数在历史回测中为什么不能起到延时作用?
这个函数的功能是为实时交易延时提供的,只有在通讯或者服务器繁忙时才起作用,所以在历史回测中无效,而且在自定义指标程序中也无效。如果您需要在一个k线只开仓一单,一定不能用这个命令,只能采用程序模块办法来解决。

Q4:怎样控制持仓单数量?
我在《外汇交易MT4程序化方法》中第一章提供了《控单模版》,这里面预定义了22个常规变量,只要加载就会按照每个tick实时更新。变量分为买入组、卖出组,例如您已经有一张买入持仓单,那么变量BuyGroupOrders=1,此时如果买入信号再次到达,就可以用if语句进行开仓数量的控制。范例:
if (BuyGroupOrders>1 && BuyGroupOrders<2)
  {
     //新建买入持仓单
  }
我们需要注意的是,一个买入信号可能会持续一段时间,如果不增加限制条件,就会连续开出2张不同价位的买入持仓单。

Q5:成交持仓单中的Comment和MagicNumber有什么区别?
Comment是指订单注释,属于字符串类型。当您手工开单建仓的时候就可以预先输入,当然MQL4程序也可以做到。一旦订单成交,这个注释就不能手工修改了,但是如果订单止盈、止损出场,注释会被系统增加[tp]、[sl]标识,如果是部分减仓,例如开仓量1手,平掉0.4手,那么新的留在场内的0.6手订单将出现一个新的订单号,且注释部分会被系统自动添加一个[from xxxxxxxx]标识。
MagicNumber是指订单特征码,属于整数类型。这个字段只在自动交易中使用,一旦定义始终不会更改。这就给程序鉴别是否出自自己建仓提供了有效的区分依据。只要您的程序预定义了MagicNumber,那么对场内的订单就能实现精确统计。我在《控单模版》中就是采用了这个特性进行与本EA相关订单的统计的。

Q6:系统的成交持仓单列表会按照时间顺序自动排序,为什么《控单模版》中还要重新排序?
在实盘操作中,可能是由于瞬间tick数量特别多,需要频繁进行建仓、平仓等操作的原因,我发现,系统的持仓单列表并不是按照时间顺序及时排序,这就导致不能精准控制类似“买入组最后一单”的操作,因此,我特意打造了这样一个控单模版。而在历史数据测试中,您是不可能发现系统这一不足之处的,大多数MQL4程序员都忽略了这一情况。

Q7:历史数据回测中出现“unmatched data error”是怎么回事
我们在进行历史数据回测时常常会看到“unmached data error”的提示,这说明历史数据不完整或者有错误。据我的经验,这类错误不影响历史数据测试效果,当然,如果能够确保数据完整就最好了。完整的历史数据可以参见《【MT4平台】一口气拿下10年数据》也可以参见《历史数据下载与服务中心》。

Q8:一个在历史数据回测中表现良好的EA能否直接实战
答案是否定的。MT4历史数据回测最好的用途是快速检验EA的逻辑符合性,即验证EA是否能够严格按照预定的策略执行。鉴于历史数据不完整和人工编造等原因,一个表现良好的EA并不意味着就可以直接实战,因此网上发表的众多的测试图都可能是一个噱头,极有可能是商家的推广手段。我的建议是您必须将EA放置到模拟盘中运行3个月进一步加以策略执行验证,但这还不够,因为模拟盘允许任意下单量成交,例如开仓量为1手,在实盘中可能就无法成交,另外大多数经纪商平台的模拟盘通讯质量与实盘有区别,这就导致了模拟盘的结果不可靠不真实。当您完成了模拟盘测试之后,建议在实盘中测试6个月,重点关注调试开仓量的执行情况、行情跳水的应对策略、检验平台通讯质量等等。因此,一个成功的EA不可能一蹴而就,有太多的细节需要关注。

Q9:为什么EA在历史数据回测能执行在模拟实盘中不行
主要从以下3点找原因:
1、测试的交易品种可能禁止EA。
2、可能没有符合条件的交易信号。
3、建仓指令包含了止盈止损价位。因为许多平台是不允许建仓同时设置止盈或者止损。
快速测试方法:编写一个开仓EA,运行验证。

Q10:MT4历史订单和持仓单是怎么排序的
MT4历史订单按照平仓时间顺序排序,最后平仓的订单序号最大,序号为OrdersHistoryTotal()-1,第一张平仓单序号为0。选取最新平仓单的命令:
OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY);
MT4成交持仓单按照建仓时间顺序排序,最后建仓的订单顺序号最大,序号为OrdersTotal()-1,最先建仓的持仓单序号为0。选取最新平仓单的命令:
OrderSelect(OrdersTotal()-1,SELECT_BY_POS,MODE_TRADES);
但是,请注意这个“但是”很重要!在实际应用中,发现订单数量大于2张,系统排序就有问题了,所以,按序号检索第一单和最后一单的方法不可靠。

Q11:MT4历史数据导入文件是什么格式
MT4历史数据导入之前需要准备一个.csv文件,这是一个“逗号”格式的文件,可以用Excel打开编辑。每条记录有7个字段,分别是日期、时间、开盘价、最高价、最低价、收盘价、成交量。如下表(EURUSD月线数据)所示:

2012.11.01
0:00
1.29564
1.30277
1.26613
1.29844
1384424
2012.12.01
0:00
1.29824
1.3308
1.28769
1.31964
1474901
2013.01.01
0:00
1.31978
1.34788
1.29969
1.34623
1936130

 

Q12:MT4历史数据无法导入,怎么办
已经编制好的MT4历史数据.csv文件会出现无法导入的情况,可按照以下步骤反复执行:
1、删除history文件夹中的数据文件,例如现在需要导入XAUUSD M1数据,那就删除XAUUSD1.hst文件。
2、启动MT4平台,打开XAUUSD M1图表,等待平台自动更新1分钟数据,能获取到最新的一批数据。
3、按F2打开“历史数据”窗口,点击“导入”,打开指定的.csv文件,如果导入窗口下半部分显示了数据就说明正常,点击“确定”。
4、如果导入窗口下半部分没有任何显示,则关闭MT4终端,从第2步重新操作一遍,直到第3步完成。
5、浏览历史数据图形,查看错误并在“历史数据”窗口中加以修改。任何历史数据都有瑕疵,因此这一步是必须要执行的。

Q13:MQL4错误代码4008(ERR_NOT_INITIALIZED_STRING 没有初始字行)
预定义字符类型的变量没有赋初始值。这样就行了:
string mystring=””;

Q14:MQL4历史数据测试出现stopped because of Stop Out是什么原因
账户资金不够,浮动亏损超过了账户余额。将起始资金调大即可。

Q15:MQL4历史数据测试出现ERR_OBJECT_ALREADY_EXISTS 4200 定单已经存在是什么原因
首先要更正中文翻译“订单已存在”应翻译成“对象已存在”,这是指在屏幕上采用Object模式显示信息时,需要先创建一个文字对象,如果屏幕中已经有这个对象,就不需要创建了,在我的自定义函数中做了如下修正:
void iDisplayInfo(string LableName,string LableDoc,int Corner,int LableX,int LableY,int DocSize,string DocStyle,color DocColor)
{
    if (Corner == -1) return(0);
    for (cnt=0;cnt<ObjectsTotal();cnt++)
    {
        if (ObjectName(cnt)==LableName) //如果有对象名称,退出循环
        {
            break;
        }
    }
    if (cnt==ObjectsTotal())  ObjectCreate(LableName, OBJ_LABEL, 0, 0, 0);//新建对象
    ObjectSetText(LableName, LableDoc, DocSize, DocStyle,DocColor);
    ObjectSet(LableName, OBJPROP_CORNER, Corner);
    ObjectSet(LableName, OBJPROP_XDISTANCE, LableX);
    ObjectSet(LableName, OBJPROP_YDISTANCE, LableY);
}

Q16:MQL4历史数据测试出现ERR_ARRAY_INDEX_OUT_OF_RANGE 4002 数组索引超出范围是什么原因
简单讲就是数组超出边界。在使用数组前首先要定义数组的边界,比如定义数组为6,意味着数组有6个元素,在程序中采用for命令进行遍历计算的时候,那个上限变量是6-1=5,而不是6。

Q17:MT4智能交易中出现了“Off Quotes是什么原因
中文意思是“关闭行情”,EA发出的交易指令不被平台接受,通常是您的MT4软件需要升级更新了,取消EA关闭软件重启试试看?如果报价在服务器无法成交,被称为“价格过期”也是这种提示,那就等呗,直到成交为止。

Q18:Dll程序加载到MT4后容易崩溃,MT4终端自动关闭是什么原因
1、编写DLL代码工具还是有讲究的,我最先使用了Visuol Studio 2010,发现用这么大的程序写dll太夸张了,就改为VC++ 6.0,写出的DLL程序任然经常崩溃,现在使用的是DEV C++ 5.0。编译后的DLL程序只有VS、VC的十分之一大小,MT4终端程序不易崩溃。这是因为MT4软件只兼容标准C或者C++编译的DLL。
2、含有DLL调用的EA加载后还是会偶尔崩溃,多加载几次就行了。
3、历史数据回测时不要在交易图表中加载这类EA,容易崩溃,可能是DLL被重复调用的原因。我没有测试过多货币对同时加载这类EA是否会崩溃。
4、涉及到订单排序检索等算法,如果不用数据库模式,最好不用DLL实现。
5、除非算法加密、通讯等原因,否则强烈建议采用纯粹的MQL4语言编写,因为EA是生产工具,稳定性永远是排在第一位的。
6、用C语言编写的函数,因数据结构与MQL4之间的差异,会导致类型不匹配、内部死循环等非逻辑错误,加上MT4传送的市场数据不够规范,这些都是导致加载DLL后MT4软件崩溃的重要因素。

Q19:MQL4中的IndicatorCounted()干什么用的
当一个新的时间周期开始的时候,新来的报价可能不属于该k线的数据,那么当前k线就没有真正形成,此时只能计算“有效k线”数值,如果用Bars计算就可能会出现错误,IndicatorCounted()是MQL4中专门为编写指标提供的一个函数,返回有效k线数量以避免错误运算。
在时间周期没有更新的时候,Bars等于IndicatorCounted()。编写指标时,为了避免重复计算历史数据,通常会用以下代码只计算当前k线数据:
int limit; //预定义需要计算k线的数量
int counted_bars=IndicatorCounted(); //获取有效的k线总数量
if(counted_bars>0) counted_bars–; //如果有效k线大于0,有效k线数量减1
limit=Bars-counted_bars; //计算需要计算k线的数量,而不是全部

指标第一次加载的时候IndicatorCounted()返回0,那么就会将历史数据统统计算一遍,之后就不需要每次重复计算历史指标数据了。

 

 

http://bbs.520fx.com/forum.php?mod=viewthread&tid=48625

转载请注明:量化交易 » [转]mql4常见问题你问我答

喜欢 (0)
发表我的评论
取消评论

表情