当前位置:文档之家› MT4自带的EA

MT4自带的EA

MT4自带的EA
MT4自带的EA

MT4自带的EA :Moving Average 详解

//+------------------------------------------------------------------+

//| Moving Average.mq4 |

//| Copyright ?2005, MetaQuotes Software Corp. |

//| https://www.doczj.com/doc/e04953974.html,/ |

//+------------------------------------------------------------------+

#define MAGICMA 20050610 //定义本EA操作的订单的唯一标识号码,由此可以实现在同一账户上多系统操作,各操作EA的订单标识码不同,就不会互相误操作。凡是EA皆不可缺少,非常非常重要!!!

//宏定义命令#define用法https://www.doczj.com/doc/e04953974.html,/xyls7570/blog/item/9c9b43cfde98180b92457eb2.html

extern double Lots = 0.1;//每单的交易量

extern double MaximumRisk = 0.02;//本系统最大可以动用总资金的2%

extern double DecreaseFactor = 3;//作者定义的参数,作用要看程序中的用法

extern double MovingPeriod = 10;//EA中使用的均线的周期

extern double MovingShift =3;//EA中使用的均线向左的K线偏移量

//extern 确定从外部程序输入的变量,会直接显现输入数据窗口。数列本身不能作为外部变量。

//+------------------------------------------------------------------+

//| Calculate open positions |

//+------------------------------------------------------------------+

int CalculateCurrentOrders(string symbol)//函数作用,计算当前持仓订单的数量{

int buys=0,sells=0;//定义两个临时变量,准备用于后面的多空订单的个数计算

//----

for(int i=0;i

{

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;//挑出持仓单的每一个订单位置

if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)//根据订单位置,比较是否是当前K线商品以及订单唯一标识号是否和本程序设置的一致,即判断这个订单是不是当前EA操作的。(用于避免EA误操作其他程序控制的持仓单)

{

if(OrderType()==OP_BUY) buys++;//找到符合条件的持仓单后,如果是多单,则临时变量buys增加1

if(OrderType()==OP_SELL) sells++;//找到符合条件的持仓单后,如果是空单,则临时变量sells增加1

}

}

//---- return orders volume

if(buys>0) return(buys);

else return(-sells);//本函数返回查询计算结束时的持仓单的个数.这种模式返回是假设不存在锁单的。

}

//+------------------------------------------------------------------+

//| Calculate optimal lot size |

//+------------------------------------------------------------------+

double LotsOptimized()//函数目的,根据要求计算出订单交易量

{

double lot=Lots;

int orders=HistoryTotal(); // history orders total 历史出场订单的个数

int losses=0; // number of losses orders without a break

//---- select lot size

lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);//通过风险系数的计算获得当前入场单应该采用的交易量,除以1000是因为大多货币对汇价都在这个附近。

//---- calcuulate number of losses orders without a break

if(DecreaseFactor>0)

{

for(int i=orders-1;i>=0;i--)

{

if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }//循环查询出场单队列

if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;//

//----

if(OrderProfit()>0) break;

if(OrderProfit()<0) losses++;//循环计算所有出场亏损单的亏损总和

}

if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);//如果亏损额大于1,则下一入场单的交易量修正为新的计算结果。

}

//---- return lot size

if(lot<0.1) lot=0.1;//如果计算出的交易量小于帐户最小手数0.1,则下一入场单的交易手数使用0.1作为交易量

return(lot);

}

//+------------------------------------------------------------------+

//| Check for open order conditions |

//+------------------------------------------------------------------+

void CheckForOpen()//检查入场条件的情况并作处理

{

double ma;

int res;

//---- go trading only for first tiks of new bar,注意下面采用的Volume[0],Open[1]等可以确保交易是在当前周期下k线收盘价走完才发生的。

if(Volume[0]>1) return;//如果当前K线持仓量(成交量)大于1,说明不是K线的开盘时间点,

即当前k线还没收盘确定,则直接返回否则是K线第一个价格,则继续下面的过程

//---- get Moving Average

ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);//获得当前的均线数值

//---- sell conditions

if(Open[1]>ma && Close[1]

{

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);

return;

}

//---- buy conditions

if(Open[1]ma) //如当前K开盘价小于均线,而前一K收盘价大于均线,则发出入场空单

{

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);

return;

}

//----

}

//+------------------------------------------------------------------+

//| Check for close order conditions |

//+------------------------------------------------------------------+

void CheckForClose()//检查出场条件的情况并作处理

{

double ma;

//---- 只在一个k收盘另一个新出现时交易

if(Volume[0]>1) return;

//---- get Moving Average

ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);

//----

for(int i=0;i

{

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;

if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;

//----确定是不是自己系统下的单子。

if(OrderType()==OP_BUY) //多单平仓

{

if(Open[1]>ma && Close[1]

}

if(OrderType()==OP_SELL) //空单平仓

{

if(Open[1]ma) OrderClose(OrderTicket(),OrderLots(),Ask,3,White););//如果持仓是空单,则当当前K开盘价大于均线,而前一K收盘价小于均线,则发出平仓指令

break;

}

}

//----

}

//+------------------------------------------------------------------+

//| Start function | //+------------------------------------------------------------------+

void start()//主循环过程

{

//---- check for history and trading

if(Bars<100 || IsTradeAllowed()==false) return;

//---- calculate open orders by current symbol

if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();

else CheckForClose();

//----

}

MT4自带EA:MACD Sample详解

//+------------------------------------------------------------------+

//| MACD Sample.mq4 |

//| ... [/quote]

extern double TakeProfit = 50; 盈利目标点数

extern double Lots = 0.1; 每单入场的手数

extern double TrailingStop = 30; 追踪止损的点数

extern double MACDOpenLevel=3; MACD开仓的参考位置

extern double MACDCloseLevel=2; MACD出场的参考位置

extern double MATrendPeriod=26; 条件中使用的MA均线的周期数

程序最上面extern开始的这些数据都是程序参数,也就是在使用者调用的时候可以修改的部分。

这个EA是个常见的技术指标条件入场,条件出场同时又移动止损功能的完成示意,很适合初学者研究。

先总结这个程序的基本条件的意思以方便大家对号入座,尽快理解。

多头入场条件:

MACD小于0 并且小于指定的参数MACDOpenLevel 并且MACD讯号下穿基准线(死叉)并且MA向上趋势

多头出场条件:

MACD大于0 并且大于指定的参数MACDCloseLevel 并且MACD信号线上传基准线(金叉)

空头入场条件:

MACD大于0 并且大于指定的参数MACDOpenLevel并且MACD讯号线上穿基准线(金叉)并且MA向下趋势

空头出场条件:

MACD小于0 并且小于制定的参数MACDCloseLevel 并且MACD讯号线下穿基准线(死叉)=============================================================

有了以上的初步了解,下面开始进行EA程序基本结构的分析:

1、start()函数是最重要的执行部分,价格只要变动,此函数都自动执行一次,所以主要的逻辑结构都在这个函数里

2、程序的基本流程都是按照以下步骤进行,我们先牢牢记住这个结构,然后再对号入座去理解程序。

先判断当前自身的仓位状态,因为start函数式循环运行的,所以中间的每个步骤都会使用start函数,因此,当函数开始的时候我们首先要通过MT4的仓位操作函数获得当前的仓位状态,并进一步根据状态进行不同分支的计算。

程序开始的以下两个部分不重要简单说一下:

if(Bars<100)

{

Print("bars less than 100");

return(0);

}

以上是说如果当前图形的K线个数少于100 则不进行运算直接返回。这种情况一般不会出现,所以我们自己写程序的时候可以不写这部分。

if(TakeProfit<10)

{

Print("TakeProfit less than 10");

return(0); // check TakeProfit

}

以上这段意思是参数TakeProfit移动止损点数的设定如果小于10点,则发出报警,并返回不进行运算。这是为了防止乱设数值,引起后面计算的错误。这部分,如果程序只是我们自己使用,估计不会犯这种低级错误,所以写程序的时候也可以忽略不写。

下面这段:

MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);

MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);

SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);

SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);

MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);

MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);

这部分是变量赋值部分,等于提前计算出为后面用到的当前MACD数值以及MA数值,这样提前写出来在后面直接使用赋值后的变量就很清楚了。是很好的编程习惯。

再下面开始最主要的程序逻辑部分,首先遇到的就是我们上面说过的通过仓位函数获得当前状态的部分。

total=OrdersTotal(); 通过函数获得当前持仓单的个数,如果持仓单个数小于1,则说明是空仓状态,那末就进行多头和空头的入场条件判断,如果满足条件则进行入场。代码如下:

if(total<1)

{

// no opened orders identified

if(AccountFreeMargin()<(1000*Lots)) 这句诗判断保证金余量是否够下单,如果不够则

直接返回,并不进行后续入场判断

{

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

return(0);

}

// check for long position (BUY) possibility

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious) 这句就是多头入场条件的判断,可以看到2个技巧,1、交叉的数学意思是“前面再下后面在上”或反之2、MA向上趋势的数学意思是当前K线的MA大于上一K线的MA数值{

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green); 这是入场语句记得一定要判断入场是否成功,因为很多服务器由于滑点或者服务器价格变动而不能入场成功,所以,要判断入场不成功后作出提示。ticket就是定单入场是否成功的标记。

if(ticket>0) 大于0说明入场成功

{

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

}

else Print("Error opening BUY order : ",GetLastError()); 入场不成功,输出不成功的系统原因。

return(0); 这里为什麽使用了返回呢。因为一种情况是入场成功,那末直接返回等待下一个价格到来的时候再执行start函数,另一种情况是入场不成功,则返回也是等待下一个价格到来的时候在此执行入场操作。

}

下面就是空单入场的判断了,大家自己对照观看即可

// check for short position (SELL) possibility

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);

}

return(0);

}

MT4自带EA:MACD Sample详解-2002

步骤3 –集中程序的结果代码

让我们打开智能交易的设定:使用按钮打开”属性…”菜单。在窗口内指定运行参量的外部设定:

从先前部分集中全部代码:

//+------------------------------------------------------------------+//|

MACD Sample.mq4 |//| Copyright ?2005, MetaQuotes Software Corp. |//| https://www.doczj.com/doc/e04953974.html,/ |//+------------------------------------------------------------------+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;//+------------------------------------------------------------------+//|

|//+------------------------------------------------------------------+int start() { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; int cnt, ticket, total;// 检测初始化数据// 确定智能交易在图表中运行正常非常重要// 用户在外部变量交易中不会产生任何错误// 外部变量(标准手数, 止损,赢利, // 追踪止损) 在这种情况下,我们检测图表中赢利水平要小于100 柱if(Bars<100) { Print("少于100柱"); return(0); } if(TakeProfit<10) { Print("赢利少于10"); return(0); // 检测赢利水平}// 简化代码和加速通道// 数据被放置在内部变量中MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);

MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);

SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);

SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);

MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);

MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1); total=OrdersTotal(); if(total<1) { // 没有指定开单if(AccountFreeMargin()<(1000*Lots))

{ Print("没有资金. 自由保证金= ", AccountFreeMargin()); return(0); } // 尽可能检测看涨仓位(BUY) 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 定单开仓: ",OrderOpenPrice()); } else Print("错误BUY定单开仓: ",GetLastError()); return(0); } // 尽可能检测卖空仓位(SELL) if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDOpenLevel*Point) && MaCurrent0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL 定单开仓: ",OrderOpenPrice()); } else Print("错误SELL定单开仓: ",GetLastError()); return(0); } return(0); } // 正确进入市场很重要, // 但正确退出市场更重要... for(cnt=0;cnt0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point))

{ OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); //平仓return(0); // 退出} // 检测追踪止损if(TrailingStop>0) { if(Bid-OrderOpenPrice()>Point*TrailingStop) { if(OrderStopLoss()

return(0); } } } } else // 去卖空仓位{ // 需要平仓吗? if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // 平仓return(0); //退出} // 检测追踪止损if(TrailingStop>0)

{ if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) { if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop, OrderTakeProfit(),0,Red);

return(0); } } } } } } return(0); }// 结束对于最后智能交易的确认,只需要指定外部变量值“Lots = 1″, “Stop Loss (S/L) = 0″(not used), “Take Profit (T/P) = 120″(appropriate for one-hour intervals), “Trailing Stop (T/S) = 30″. 当然,你可以使用自己的值。按“编写”按钮,如果没有任何错误信息出现(你可以从MetaEditor的列表中复制), 按“保存”键保存智能交易。

MT4编程:自带的DLL范例

俺不是编程高手,而且时间和精力都很有限,因此编程对于我来说最理想的境界是"知其然",而不必"知其所以然"。当然,如果程序出错,那就要好好研究一下"其所以然"了。所以每次编程都会经历一个预热的学习过程,看看范例--然后温故而知新......MT4自带的DLL 范例,就放在在文件夹MetaTrader 4\EXPERTS\SAMPLES中。该范例值得细细研究,是因为它展示了如何使用mq4语言来调用C++语言编写的DLL。而我们需要重点留意的,就是调用DLL函数时所展现的函数参数的传递方式;显然,针对不同类型的变量,都有其不同的传递方式,实现的结果亦各不相同。

1)变量传递。

对于mq4的double/int类型变量,与C++的通讯只需要用到值传递。

在C++里我们要定义一个函数,如func1(double x,int y){......;......;}

mq4里我们必须在头文件里做一个函数声明:func1(double,int),调用的时候以相应的变量值作为参数,如func1(10.56,8)。

对于mq4的String类型,在C++里可以用指针如char *str来代替String类型。

在C++里我们要定义一个函数,如func2(char *str){......;......;}

mq4里我们必须在头文件里做一个函数声明:func2(string),调用的时候以字符串作为参数,如func2("something")。

2)数组的传递。

对于mq4的double/int类型数组,C++通过指针来接收相应的参数。

关于数组与指针,在网上查阅了很多论述:其实,在C++中数据名作为函数形参时,等同于指向数组的指针!

于是,下面2个函数是等效的:

double sample1(double*); //在声明中,描述参数为(指向数组的)指针:double*;

......

double sample1(double aa[]) //在函数中,以aa[](数组)来接收该指针。

{

aa[4]=55.5;

return(aa[4]);

}

double sample2(double []); //在声明中,描述参数为数组:double [];

......

double sample2(double *aa) //在函数中,以*aa(指针)来接收该数组。

{

aa[4]=55.5;

return(aa[4]);

}

当然,2个函数的声明其实也是等效的。mq4中没有指针类型,所以传递数组的方式类似sample2。

3)行情数据的传递

mq4提供了ArrayCopyRates函数,用于复制一段走势图上的数据到一个二维数组,并返回复制柱子的总数。其第二维为固定的6个项目,从0到5分别为“时间、开盘价格、最低价格、最高价格、收盘价格、成交量”。

如:

double rates[][6];

int totalRecords = ArrayCopyRates(rates,Symbol(),0);

mq4调用DLL函数的时候,把该数组作为参数,向DLL函数提供二维数组的指针,这也就是就mq4程序实现行情数据传递的默认方式。

如:

ArrayCopyRates(rates);

price=GetRatesItemValue(rates,Bars,0,CLOSE_INDEX);

对应地,我们在C++代码中可以定义一个结构类型RateInfo:

struct RateInfo

{

unsigned int time; //时间

double open; //开盘价格

double low; //最低价格

double high; //最高价格

double close; //收盘价格

double volume; //成交量

};

这里的RateInfo结构定义正好对应mq4里二维数组的第二维,在DLL函数里,结构指针RateInfo*被映射为二维数组double rates[][6]。也就是说,当mq4调用DLL的时候,由操作系统根据内存指针完成了数据的访问,且结构定义中的unsigned int是从double类型转换后得到的。

需要注意的是:mq4数组顺序与DLL数组顺序完全相反。mq4数组顺序是:从Bars-1到0;而传递到DLL后,数组顺序变为0到Bars-1?

MT4自带EA:MACD Sample详解-2001

MetaQuotes语言4 是需要“外部变量”辅助的。外部变量可以从外部设定,在智能交易程序源代码设定之后不可以修改。提供一个额外的灵活性。在我们的程序中,MATrendPeriod 变量作为外部变量指定。在程序开始我们插入这个变量。

检测初始数据

该代码部分通常使用在所有的智能交易中。因为是一个标准的检测:

// 初始数据检测// 确认智能交易运行正常非常重要//图表和用户设置不能出现任何错误// 变量(Lots, StopLoss, TakeProfit, // TrailingStop) 我们的情况需要检测TakeProfit// 图表

中少于100 柱if(Bars<100) { Print("少于100柱"); return(0); } if(TakeProfit<10) { Print("赢利少于10"); return(0); // 检测TakeProfit }对于数据的快速通道设置内部变量

在源代码中经常需要注意指标值或计算值。简化代码和数据放置在内部变量中。

int start() { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; int cnt, ticket, total;// 简化代码//数据放置在内部变量中MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);

SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);

SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);

MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);

MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);现在,用iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0)代替,您可以在源代码中使用MacdCurrent。

检测交易终端–是空的吗?如果是:

在我们的智能交易中,我们仅使用开单和操作挂单。不过,使更安全,我们来认识一种对于先前定单交易终端检测:

total=OrdersTotal(); if(total<1) {检测: 账户上的可用保证金…

在分析市场状况之前,检测你的账户上可用的自由保证金可以开仓。

if(AccountFreeMargin()<(1000*Lots)) { Print("没有资金.自由保证金= ", AccountFreeMargin()); return(0); }可能是看涨仓位(BUY)?

进入看涨仓位的条件: MACD 低于零,向上并且穿过信号线向下。这就是我们在MQL4中描述的(注意我们在指标上的业务值保存在先前的变量中):

// 尽可能检测看涨仓位(BUY) if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious MathAbs(MacdCurrent)>(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 开单: ",OrderOpenPrice()); } else Print("错误opening BUY order : ",GetLastError()); return(0); }附加的检验‘山丘’的大小上面已经给出了描述。MACDOpenLevel变量是一个用户指定变量,它不可能改变程序文本,但是却有很大的灵活性。在程序开始我们插入这个变量的描述。

可能是卖空仓位(SELL)?

进入卖空仓位的条件: MACD高于零,向上并且穿过信号线向下。注解如下:

// 尽可能的检测卖空仓位(SELL) 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 开单: ",OrderOpenPrice()); } else Print("错误SELL定单开仓: ",GetLastError()); return(0); }return(0); }周期循环检验先前开仓

//进入市场的正确性非常重要// 但是更重要的是安全退出... for(cnt=0;cnt { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderType()<=OP_SELL && // 检验开仓OrderSymbol()==Symbol()) // 检验货币对{“cnt”–”是一个循环的变量必须在程序开始指定如下:

int cnt = 0;如果是看涨仓位

if(OrderType()==OP_BUY) // 打开看张仓位{应该平仓吗?

退出看涨仓位的条件: MACD 穿过信号线,MACD 高于零,向上并穿过信号线向下。

if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); //平仓return(0); //退出}应该重设追踪止损马?

我们设定追踪止损只有在仓位盈利已经超过追踪水平点,并且新的止损水平点好于先前的水平。

// 检测追踪止损if(TrailingStop>0) { if(Bid-OrderOpenPrice()>Point*TrailingStop) { if(OrderStopLoss() { OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop, OrderTakeProfit(),0,Green); return(0); } } }我们停止操作符。

}如果是卖空仓位

else //卖空仓位{应该平仓吗?

退出卖空仓位的条件: MACD穿过信号线,MACD低于零,向上并且穿过信号线向下。

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDCloseLevel*Point)) { OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); //平仓return(0); // 退出}应该重设追踪止损吗?

我们设定追踪止损只有在仓位盈利已经超过追踪水平点,并且新的止损水平点好于先前的水平。

// 检测追踪止损if(TrailingStop>0) { if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) { if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop, OrderTakeProfit(),0,Red); return(0); } } }关闭所有残留开仓。

} } } return(0);}

编制自动交易系统的基本知识

(2012-02-12 12:16:04)

分类:MT4编程入门

编制自动交易系统的基本知识

Introduction介绍

鉴于许多中国的交易者对交易系统了解不多,本文解释使用MQ4语言编制自动交易系统的基本知识.

Title 编制自动交易系统的基本知识

一个交易系统大致包括以下几个方面:

1 开仓策略,即什么条件满足时开仓, 如某条线和某条线上交叉或下交叉,

2 平仓策略,即什么条件满足时平仓, 包括止赢设置,止损设置,和跟踪止赢设置三个方面.

3 资金管理, 其中一个方面就是下单的大小

4 时间管理, 如持仓时间,开平仓时间间隔等

5 账户状态分析,如交易历史,当前资金/仓位/各仓为盈亏状态等.

当然一个交易系统不必包括全部内容,本文做为入门知识也仅通过实例介绍交易系统程序的基本构成.

//#property copyright "Copyright 2007 , Dxd, China."

#define MAGICMA 200610011231

//+------------------------------------------------------------------+

//| 注意没有指标文件那些property |

//+------------------------------------------------------------------+

extern int whichmethod = 1; //1~4 种下单方式 1 仅开仓, 2 有止损无止赢, 3 有止赢无止损, 4 有止赢也有止损

extern double TakeProfit = 100; //止赢点数

extern double StopLoss = 20; //止损点数

extern double MaximumRisk = 0.3; //资金控制,控制下单量

extern double TrailingStop =25; //跟踪止赢点数设置

extern int maxOpen = 3; //最多开仓次数限制

extern int maxLots = 5; //最多单仓持仓量限制

extern int bb = 0; //非零就允许跟踪止赢

extern double MATrendPeriod=26;//使用26均线开仓条件参数本例子

int i, p2, xxx,p1, res;

double Lots;

datetime lasttime; //时间控制, 仅当一个时间周期完成才检查条件

int init() //初始化

Lots = 1;

lasttime = NULL;

return(0);

}

int deinit() { return(0); } //反初始化

//主程序

int start()

{

CheckForOpen(); //开仓平仓条件检查和操作

if (bb>0) CTP(); //跟踪止赢

return(0);

}

//+------下面是各子程序--------------------------------------------+ double LotsOptimized() //确定下单量,开仓调用资金控制

{

double lot=Lots;

int orders=HistoryTotal(); // history orders total

int losses=0; // number of losses orders without a break

//MarketInfo(Symbol(),MODE_MINLOT); 相关信息

//MarketInfo(Symbol(),MODE_MAXLOT);

//MarketInfo(Symbol(),MODE_LOTSTEP);

lot=NormalizeDouble(MaximumRisk *

AccountBalance()/AccountLeverage(),1); //开仓量计算

if(lot<0.1) lot=0.1;

if(lot>maxLots) lot=maxLots;

return(lot);

}

//平仓持有的买单

void CloseBuy()

{

if (OrdersTotal( ) > 0 )

{

for(i=OrdersTotal()-1;i>=0;i--)

{

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;

if(OrderType()==OP_BUY)

{

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

Sleep(5000);

}

}

}

//平仓持有的卖单

void CloseSell()

{

if (OrdersTotal( ) > 0 )

{

for(i=OrdersTotal()-1;i>=0;i--)

{

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;

if(OrderType()==OP_SELL)

{

OrderClose(OrderTicket(),OrderLots(),Ask,3,White);

Sleep(5000);

}

}

}

}

//判断是否买或卖或平仓

int buyorsell() //在这个函数计算设置你的交易信号这里使用MACD 和MA 做例子

{

double MacdCurrent, MacdPrevious, SignalCurrent;

double SignalPrevious, MaCurrent, MaPrevious;

MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);

if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&

MacdPrevious

&& MaCurrent>MaPrevious)

return (1); // 买 Ma在上升,Macd在0线上,并且两线上交叉

if(MacdCurrent>0 && MacdCurrent

MacdPrevious>SignalPrevious

&& MaCurrent

return (-1); // 卖

return (0); //不交易

}

int nowbuyorsell = 0;

void CheckForOpen()

{

if (Time[0] == lasttime ) return; //每时间周期检查一次时间控制lasttime = Time[0];

nowbuyorsell = buyorsell(); //获取买卖信号

if (nowbuyorsell == 1) //买先结束已卖的

CloseSell();

if (nowbuyorsell == -1) //卖先结束已买的

CloseBuy();

if (TimeDayOfWeek(CurTime()) == 1)

{

if (TimeHour(CurTime()) < 3 ) return; //周一早8点前不做具体决定于你的时区和服务器的时区时间控制

}

if (TimeDayOfWeek(CurTime()) == 5)

{

if (TimeHour(CurTime()) > 19 ) return; //周五晚11点后不做

}

if (OrdersTotal( ) >= maxOpen) return ;

//如果已持有开仓次数达到最大,不做

if (nowbuyorsell==0) return; //不交易

TradeOK(); //去下单交易

}

void TradeOK() //去下单交易

{

int error ;

if (nowbuyorsell == 1) //买

{

switch (whichmethod)

{

case 1:

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0 ,Blue);break;

case 2:

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Poi nt,0,"",MAGICMA,0,Blue); break;

case 3:

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,Ask+TakeProfit *Point,"",MAGICMA,0,Blue);break;

case 4:

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Poi nt,Ask+TakeProfit*Point,"",MAGICMA,0,Blue);break;

default :

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0 ,Blue);break;

}

if (res <=0)

{

error=GetLastError();

if(error==134)Print("Received 134 Error after OrderSend() !! "); // not enough money

if(error==135) RefreshRates(); // prices have changed

}

Sleep(5000);

return ;

}

if (nowbuyorsell == -1) //卖

{

switch (whichmethod)

{

case 1:

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA, 0,Red); break;

case 2:

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Po int,0,"",MAGICMA,0,Red); break;

case 3:

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,Bid-TakeProfi t*Point,"",MAGICMA,0,Red); break;

case 4:

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Po int,Bid-TakeProfit*Point,"",MAGICMA,0,Red); break;

default :

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA, 0,Red); break;

}

if (res <=0)

{

error=GetLastError();

if(error==134) Print("Received 134 Error after OrderSend() !! "); // not enough money

if(error==135) RefreshRates(); // prices have changed

}

Sleep(5000);

return ;

}

}

void CTP() //跟踪止赢

{

bool bs = false;

for (int i = 0; i < OrdersTotal(); i++)

{

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;

if (OrderType() == OP_BUY)

{

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

MarketInfo(OrderSymbol(), MODE_POINT))) //开仓价格当前止损和当前价格比较判断是否要修改跟踪止赢设置

{

if (OrderStopLoss() < Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT))

{

bs = OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Green); }

}

}

else if (OrderType() == OP_SELL)

{

if ((OrderOpenPrice() - Ask) > (TrailingStop *

MarketInfo(OrderSymbol(), MODE_POINT))) //开仓价格当前止损和当前价格比较判断是否要修改跟踪止赢设置

{

if ((OrderStopLoss()) > (Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))

{

bs = OrderModify(OrderTicket(), OrderOpenPrice(),

Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Tan);

}

}

}

}

}

EA框架模型,大部分地方做了注释

现在我学会了EA基本的东西,并且按照框架思路建立了EA框架模型,大部分地方做了注释。希望对大家有用;

程序代码如下:

//+------------------------------------------------------------------+

//| ganendexin's 模板.mq4 |

//| Copyright ?2008, MetaQuotes Software Corp. |

//| https://www.doczj.com/doc/e04953974.html,

//+------------------------------------------------------------------+

#property copyright "ganendexin"

#property link "https://www.doczj.com/doc/e04953974.html,"

//---- input parameters

extern double TakeProfit=250.0;

extern double Lots=0.1;

extern double TrailingStop=35.0;

//+------------------------------------------------------------------+

//| expert initialization function |

//+------------------------------------------------------------------+

int init()

{

//----

//----

return(0);

}

//+------------------------------------------------------------------+

//| expert deinitialization function |

//+------------------------------------------------------------------+

int deinit()

{

//----

//----

return(0);

}

//信号部分,下面这部分给出的是买卖信号,这个信号可以是自己编写的,也可以是用iCustom来调用的。以后需要修改的大部分是在这里面改

int Crossed (double line1 , double line2)

{

static int last_direction = 0;

static int current_direction = 0;

if(line1>line2)current_direction = 1; //up

if(line1

if(current_direction != last_direction) //changed

{

last_direction = current_direction;

return (last_direction);

}

else

{

return (0);

}

}

//+------------------------------------------------------------------+

//| expert start function |

//+------------------------------------------------------------------+

int start()

{

//----

//程序开始前,先定义变量。

int cnt, ticket, total; //用于检查订单的个数及类型,cnt是按照索引来计算,ticket是按照ticket 来计算。在算类型之前,要先OrderSelect

double shortEma, longEma; //这个地方是定义买卖信号的参数的,根据实际需要来定个数和类型。

int counted_bars;

//如果需要控制最低的K线个数,可用下面的

//提示获利点,这个是有的系统对最小获利点有要求的情况下使用。例如FXDD要求为10. if(TakeProfit<10)

{

Print("TakeProfit less than 10");

return(0); // check TakeProfit

}

相关主题
文本预览
相关文档 最新文档