首页学院交易策略EA智能交易文章详细

MT4编程之MACD EA详解

外汇网2021-06-17 09:39:44 90
汇外网 - 全球专业的黄金外汇门户导航行情资讯网站

在MT4安装后,默认会给用户供应几个例子程序,这些程序对于新学习EA开发过程中有很大的帮助,下面我们就来对MACD Sample这个例子EA来做个注解,来说看别人是如何开发一个EA的。

首先是注释,在MQL语言中所有//的这一行就是注释行,系统自身不会去实施它,它导致用来解释目前代码的含义的,我们在代码中加入这些注释为了是让我们能够清楚的阅读代码的含义,在程序中加入详细的注释是一个很好的编程习惯,我们激励大家多加入注释。很多人认为注释这东西由于没用在写代码中认为很麻烦而忽视它,但是即便是自己编撰的程序假使不加注释过几天就会忘记意思,还要再一行一行地看这些代码,所以注释是非常重要的。

下面这些就是定义变量,我们发现前面加之了extern核心字,假使在定义变量的前面有这个词表明这个变量将令被作为EA运行的参数,举个例子,比如我要编撰一个EA,在运用过程中我想更改它的止盈和止损值,假使我程序均为事先编好的止盈止损,那么以后要改动它务必要改代码,如此不仅麻烦也不灵活,假使我把这些信息作为EA运行参数,那么在EA运行中就可以随时调整它了。

extern double TakeProfit = 50;

extern double Lots = 0.1;

extern double TrailingStop = 30;

extern double MACDOpenLevel=3;

extern double MACDCloseLevel=2;

extern double MATrendPeriod=26;

上面定义了6个变量而且均为当作参数,这里设定变量名称的时机尽量运用用户可以理解的词汇,在EA的参数设置里这些变量名就是参数的名字。值得注意的是EA里变量名称是值得用中文的。

int start()

tart()函数是EA运行的核心,MQL语言规定了几个默认函数,其中EA首次运行时会调用init()函数,在这个函数里我们可以放入一部分需要初始化的信息,start()函数中放我们EA的核心代码,每次一个TICK(换句话说就是新报价)到达后,系统会自动调用start()函数。deinit()函数是当EA关闭的时机调用的,这里放一部分我们程序停止后需要“善后”的代码。start()函数是务必要有的,其它两个函数假使不需要可以不用写。

if(Bars<100)

{

Print("bars less than 100");

return(0);

}

上面代码的意思是假使目前图表中的k线少于100根将令在日志信息里输出提示信息而且终结start()函数的实施。return的意思是返回,假使在程序中分析出有错误,下面的代码无法继续实施了,我们调用return()函数让他退出start()函数的实施。

if(TakeProfit<10)

{

Print("TakeProfit less than 10");

return(0);

// check TakeProfit

}

上面的代码意思是假使参数里的TakeProfit变量差于10也提示一条信息并终结实施,TakeProfit从字面的意思中我们可以知道是止盈的意思,有些平台会制约下单时的止盈点数不得差于某个点,假使差于某值会在下单时报错,为了避免该种错误我们会制约参数中止盈的设定。

其实这里可以调用MarketInfo()函数得到我们目前平台中允许的止盈止损最小值进而依据平台的不同自动计算出最小的止盈点数,详细情形请参阅文档MarketInfo()函数的描述。

MacdCurrent=iMACD(NULL,0,12,26,9,PR洲际交易所_CLOSE,MODE_MAIN,0);

MacdPrevious=iMACD(NULL,0,12,26,9,PR洲际交易所_CLOSE,MODE_MAIN,1);

SignalCurrent=iMACD(NULL,0,12,26,9,PR洲际交易所_CLOSE,MODE_SIGNAL,0);

SignalPrevious=iMACD(NULL,0,12,26,9,PR洲际交易所_CLOSE,MODE_SIGNAL,1);

MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PR洲际交易所_CLOSE,0);

MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PR洲际交易所_CLOSE,1);

以上语句是调用了MQL的一部分内置指标函数,在MQL语言中,对于常用的指标如均线,MACD,KD等MQL已经供应给我们现成的函数,我们只要调用他即可得到指标的值(相见文档技术指标部分:http://docs.mql4.com/cn/indicators)。

就上面的代码,MacdCurrent的值是参数为12,26,9的MACD主线目前K线的值,MacdPrevious则是MacdCurrent前一根K线的值,SignalCurrent和SignalPrevious则是相同参数信号线的目前值和前一根值。

后两个是调用均线指标函数,这里的均线周期参数则是运用了EA的参数变量MATrendPeriod,如此写是个好习惯,把调用指标的参数放到EA参数里,如此可以随时在运行中调整这些参数方便我们更改策略。MaCurrent和MaPrevious是得到26均线的目前K线值和前一根的值。

total=OrdersTotal();

if(total<1)

上面的代码就是分析我们目前能否有单子在做,他调用了OrdersTotal()函数,它可以计算目前账户中一共还没有平仓的单子和挂单的个数,假使它差于1表明目前没有任何单子,该种分析方法导致一种简单的分析法,假使这个EA在运行过程中人为也去下单则EA永远不会下单了,假使要愈加精确的计算这个EA所下的单子数量仍需要利用其余方法,这些技巧我们会在以后的文章中介绍。

if(AccountFreeMargin()<(1000*Lots))

{

Print("We have no money. Free Margin = ", AccountFreeMargin());

return(0);

}

上面的代码是计算目前的余下保证金能否差于1000,假使太少钱会不够用,所以会输出下目前的保证金只剩多少并退出。

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious)

{

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);

if(ticket>0)

{

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());

}

else Print("Error opening BUY order : ",GetLastError());

return(0);

}

上面这段就是多单开仓部分了,条件是如此:假使目前MACD主线在0轴下方,MACD“金叉”,MACD的主线不在0轴附近(这块是EA的参数来指定0轴附近多少点)而且还要目前的均线是上升的。

这里最精彩的部分在于如何分析MACD“金叉”,如何分析MACD值不在0轴附近和均线当前是上升的依旧下滑的。

“金叉”的分析是EA里用的比较多的,这里我们用了分析大小的方法就能很容易的计算它,首先得到MACD两根线目前的值和上一根K线的MACD值,假使上一根K线的MACD主线大于信号线而且目前的MACD主线差于信号线那就相当于这两根线做了一个“交叉”,所以我们可以觉得MACD“金叉”了。从这里我们也能看出来用计算机的方法来处理我们人类所认知的困难靠的均为该种具体数值的计算,所以计算机依旧比较“死板”的,假使两根线“扭”在了一起那么用计算机程序很难分析出来,这些就是当前计算机程序的缺点。

0轴附近该种分析方法这里利用了一点数学方面的知识,然而不用担忧均为很简单的算法。把MACD值做绝对值运算然后分析能否大于指定的值,由于MACD将是负数做绝对值运算后直接分析能否大于设定的值就行了,这块相当于是简化了分析语句的条件。

均线的上升和下滑分析和“金叉”的算法差不多,得到目前均线值和前一根线的均线值,假使前一根均线值差于目前值那就表明均线是上升的。

if(MacdCurrent>0&&MacdCurrentSignalPrevious&& MacdCurrent>(MACDOpenLevel*Point) && MaCurrent

{

ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"macd sample",16384,0,Red);

if(ticket>0)

{

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice());

}

else

Print("Error opening SELL order : ",GetLastError());

return(0);

这段代码就是空单的进场条件,和上面的正相反。值得表明是这两个下单代码中会遇到下单失利的情形,由于当用OrderSend()函数下单后会返回一个大于0的整数订单号数值,利用这一点就可以很容易的知道下单能否成功了。

下面的代码是平仓和移动止损部分,这段代码比较难懂,但是却是非常重要的部分,由于在编撰EA中这些操作会经常遇到,让我们来一点一点的拆解开来理解下它们的含义。

for(cnt=0; cnt

目前存在的订单中我们要分析能否到达平仓的条件,所以第一步我们首先要对所有在下的单子执行一次遍历,一个一个的去分析它们能否高达平仓条件。

此代码中利用了一个循环语句从第一单开始一单一单的循环,这里值得注意的是所有单子均为依照下单的先后顺序存放的,第一张单子的编号是0并非是1,这是编程语言中一般都采取的方法,我们在编撰程序的时机一定要注意它的值要从0开始。

OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

上面是选择订单操作,当循环一次订单后,务必调用OrderSelect()函数来锁定这一订单,如此下面的操作才可以正常运行。这里最容易出错的地方是函数的第二个参数假使查一下文档我们会发现它有两个选项:SELECT_BY_POS和SELECT_BY_TICKET。第一种方式是依据订单的位置执行选定操作,这个例子中就是运用了该种方式,第二种方式是依据订单号来执行选定操作,由于我们并没有知道所有单子的订单号是多少所以我们只能运用第一种方式来选择订单,刚才说过订单是依照下单的先后顺序来存放的,所以假使是第一个单子那就是0,假使是第二个单子就是1,最后一个单子是总单子数减一。

if(OrderType()<=OP_SELL && // check for opened position

OrderSymbol()==Symbol()) // check for symbol

上面的代码段又运用了一个小技巧,它首先调用了OrderType()函数来得到所选定的订单是多单依旧空单,但是我们查下这个函数的定义(http://docs.mql4.com/cn/constants/trading)发现多单的值是0,空单的值是1,那么假使OrderType()函数差于等于空单的值那么相当于在分析目前订单能否是非挂单。

第二个条件是分析目前单子的货币对能否和目前图表相同,这个分析是为了防止我们处理订单过程中误操作了其余不是EA所下的单子。

if(OrderType()==OP_BUY) // long position is opened

{

// should it be closed?

if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point))

{

OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);

// close position

return(0);

// exit

}

多单的平仓部分代码,这里其实就是去掉均线条件的空单下单信号,平仓操作中一定要注意在平仓完成后务必终止这个遍历订单的循环,由于平仓后会打乱所有单子的顺序,产生误操作其余订单。

我们在这里举个例子就能明白为何要这么做:比如目前有三个单子没有平仓,依照顺序排列序号是0、1、2,假使第二个单子平仓后第三个单子序号就会提早,如此现在一次循环实施到OrderSelect()函数后会由于没有这个编号而显现错误。

if(TrailingStop>0)

{

if(Bid-OrderOpenPrice()>Point*TrailingStop)

{

if(OrderStopLoss()

{

OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);

return(0);

}

}

}

这段代码就是多单的移动止损部分,当参数TrailingStop大于0的时机EA就开启了移动止损功能(默认设定是30,也就是说默认情形下是开启移动止损的),我们就用我们这个例子EA的默认参数30点来看明,当单子的盈利大于30点而且单子的止损点和目前价位相差30点以上时,修改订单的止损到目前价格下方30点位置。

我们在上面的程序里屡次发现作者运用Point变量来计算点位,这个变量是MT4运行环境中自动设定的值,它在MQL语言中叫做预定义变量(有关预定义变量可以参考这里:http://docs.mql4.com/cn/predefined/variables),Point告诉我们目前货币对的单价最小点值是多少,举个例子:欧元对美元的单价总是X.XXXX该种形式,它的Point值就是0.0001,当我们想设定当价格大于30点该种情形时,我们只要用30乘以Point就可以计算这个货币对的事实30点值。然而Point常量在很多平台中不能正确的来达到它自身的功能了,原因是很多平台已经改为小数点后5名,如此Point值变成了0.00001,我们直接用他来乘以点位得到是却是事实点位的十分之一,如此会在EA的运行中显现致命的逻辑错误。所以假使是5名的平台,需要在那些点位的值上乘以10来修正这个困难。有关Point的完美处理方法我们将于后续的文章中继续讨论。

以上就是MT4例子EA的注解,这个程序尽管比较复杂但是它却是一个很好的例子,里面涉及到了我们在写EA程序过程中常用到的一部分功能,对于初学EA程序的人来看帮助很大,我们也可以修改这个程序的开仓、平仓部分直接变成我们自己的逻辑。

标签:

随机快审展示
加入快审,优先展示

加入VIP