众所周知,MT4(MetaTrader 4)是外汇交易中最常用的交易软件。在MT4中我们不仅可以手动交易,还可以自己编程写成EA进行程序化交易。小编自己对MT4的EA编写也略知一二,今天在写一个多品种交易的EA中碰到了一些问题,仔细研究了一段时间才明白了其中的端倪,今天就把这个情况分享给大家,希望大家在自己写EA的时候可以避开这些“坑”。

         在MT4中,获取收盘价的函数是iClose(symbol, timeframe, shift)。这时如果我的EA是加载在XAUUSD的图表上的,这时使用iClose()函数来调取XAUUSD当前的收盘价,这时获取的价格肯定是正确的;但是如果使用iClose()函数来调取AUDUSD当前的收盘价,这时刚好我也没有打开AUDUSD的图表,那么EA获取的返回值很可能就是一个错误的数值。因为MT4为了不占用太多的硬盘空间,在储存收盘价的时候只会存当前图表已经打开了的品种的,如果没有打开某个品种的图表,MT4则不会储存这个品种的K线价格,如果在这个时候去用iCLose()调用AUDUSD的收盘价的话,MT4则会返回一个历史储存过的收盘价,而不是当前的收盘价。之后MT4发现用户在调用iClose()来获取收盘价之后,后台才会向服务器重新请求这些K线的数据,然后如果我们再次调用iClose(),其实就可以拿到正确的收盘价了。

         既然有MT4的这个内在机制,那么我们能不能在只打开一个图表的情况下,获取任意品种当前的收盘价呢?答案当然是可以的。MT4自带的另一个函数SymbolInfoDouble(symbol, prop_id)可以满足我们的要求,因为这个函数可以直接调用某个品种的Bid和Ask价格,而Bid和Ask价格就是左边市场报价里的价格,这些价格在MT4中是时时刻刻都在更新的,所以拿到的返回值一定就是最新的报价了。

         以下是我做测试的源代码:

int OnInit(){
    Print("AUDUSD close price is ", iClose("AUDUSD",0,0));
    Print("AUDUSD symbol bid is ", SymbolInfoDouble("AUDUSD", SYMBOL_BID));
    return INIT_SUCCEEDED;
}

         这个是MT4的打印结果,Ask和Bid就是当前正确的价格,Close是过去MT4储存的历史数据中最后一根K线的收盘价。

再次运行之后,AUDUSD的收盘价恢复到了正常水平。

         总结下来就是在MT4中如果开发多品种的EA或者指标,想要获取非当前图表的品种的价格时,尽量使用SymbolInfoDouble()函数,如果一定要用到iClose()函数的话,就提醒用户把其他需要的品种也打开一个图表在旁边,以免读取错误的数据导致EA误下单,引起不必要的损失。

本文作者:小土豆