咱们安装好MT4交易软件之后,在导航窗口可以看到两个MT4自带的EA,一个名叫 Moving Average,另一个叫 MACD Sample,作为官方给出的两个EA案例,非常值得编程学习。这是其中的Moving Average,一个均线EA,本文详细的做出了中文注释,欢迎喜欢编程的小伙伴们一起切磋研究!
//+------------------------------------------------------------------+ //| Moving Average.mq4 | //| Copyright 2005-2014, MetaQuotes Software Corp. | //| http://www.mql4.com | //+------------------------------------------------------------------+ #property copyright "2005-2014, MetaQuotes Software Corp." #property link "http://www.mql4.com" #property description "Moving Average sample expert advisor" #define MAGICMA 20050610 //定义本EA操作的订单的唯一标识号码,由此可以实现在同一账户上多系统操作,各操作EA的订单标识码不同,就不会互相误操作,非常重要! //extern 确定从外部程序输入的变量,会直接显现输入数据窗口。数列本身不能作为外部变量。 extern double Lots=0.1; //每单的交易量 extern double MaximumRisk=0.5; //本系统最大风险系数,即可以动用总资金的2% extern double DecreaseFactor=3; //下跌因素个数 extern double MovingPeriod=12; //均线的计算周期=12根K线; extern double MovingShift=6; //均线在K线图中向右显示的偏移量=6 根K线; //+------------------------------------------------------------------+ //| Calculate open positions 自定义函数(返回-整数型数据) 仓单查询与统计 | //+------------------------------------------------------------------+ int CalculateCurrentOrders(string symbol)//函数作用,计算当前持仓单的数量 { int buys=0,sells=0; //定义两个局部变量,整数型,buys——多单数,sells——空单数,用于订单的统计 //---- for(int i=0;i<OrdersTotal();i++) //计次循环(i=0 至订单数目,i=i+1)-循环检测当前的订单队列 { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; //如果 没有本系统交易的仓单类型,则跳出循环 if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA) //如果 仓单货币对是当前货币对 且 仓单编号是本系统编号 时(判断这个订单是不是当前EA操作的,避免EA 误操作其他程序控制的持仓单) { if(OrderType()==OP_BUY) buys++; //如果仓单类型=多单,则:在多单数上加1; if(OrderType()==OP_SELL) sells++; //如果仓单类型=空单,则,在空单数上加1。 } } //---- return orders volume-返回订单数目 if(buys>0) return(buys); //如果多单>0,则返回(多单数) else return(-sells); //否则,返回(-空单数) //本函数返回查询计算结束时的持仓单的个数.这种模式返回是假设不存在锁单的。 } //+------------------------------------------------------------------+ //| 自定义函数(返回-小数型数据) 资金管理 | //+------------------------------------------------------------------+ double LotsOptimized()//开仓量计算函数(根据要求计算出订单交易量,小数型) { double lot=Lots; //定义局部变量los 小数型(=0.1) int orders=HistoryTotal(); //历史平仓单数(已平仓) int losses=0; // 亏损单 //---- select lot size lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1); //计算 开仓下单量=帐户可用资金*最大风险系数(=2%)/1000.0,并将结果保留小数点1位 //(通过风险系数的计算获得当前入场单应该采用的交易量,除以1000 是因为大多货币对汇价都在这个附近。) //---- -计算亏损单数目 if(DecreaseFactor>0) //如果下跌因素个数(=3)>0 { for(int i=orders-1;i>=0;i--) //计次循环(i=历史平仓单数-1,到i=0, 递减1) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; } //如果 没有本系统交易记录,输出“无交易历史!”,跳出 if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue; //如果 订单的货币对不是当前货币对,或者 订单类型为挂单时,继续运行 //订单类型为整数型,0-BUY,1-SELL,2-BUYLIMT,3-BUYSTOP,4-SELLLIMT,5-SELLSTOP,其中“>OP_SELL”代表挂单 if(OrderProfit()>0) break; //如果 盈利单数目>0,跳出循环 if(OrderProfit()<0) losses++; //如果 盈利单数目<0,则在:亏损单数上加1 } if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1); //如果 亏损单数>1 时,则重新计算下单量,并保留小数点后1位,其计算公式为:下单量=(lot-lot*losses/DecreaseFactor(=3))。 } //----返回下单量 if(lot<0.1) lot=0.1; //如果 算出的交易量小于0.1 手,则取交易量为0.1手 return(lot);//返回(下单量) } //+------------------------------------------------------------------+ //| 自定义函数(无返回值) 开仓策略 | //+------------------------------------------------------------------+ void CheckForOpen()//开仓检查(判断开仓条件及其处理) { double ma; //定义局部变量ma为小数型 int res; //定义局部变量res为整数型 //---- go trading only for first tiks of new bar, //只有在新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); //获取当前以收盘价为基准计算出的均线数值iMA(NULL,0,12,6,MOD_SMA,PRICE_CLOSE,0) //---- sell conditions-卖出条件 if(Open[1]>ma && Close[1]<ma) //如果前1 根K 线下穿均线(即 K线的开盘价大于均线值、收盘价小于均线值) { res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); //发送仓单(当前货币对,卖出方向,开仓量计算(),买价,滑点=3,无止损,无止赢,订单编号,标上红色箭头) return; //返回 } //---- buy conditions-买入条件 if(Open[1]<ma && Close[1]>ma) //如果前1根K线上穿均线(即 K线的开盘价小于均线值、收盘价大于均线值) { res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue); //发送仓单(当前货币对,买入方向,开仓量计算(),卖价,滑点=3,无止损,无止赢,订单编号,标上蓝色箭头) return;//返回 } //---- } //+------------------------------------------------------------------+ //| Check for close order conditions 自定义函数(无返回值) 平仓策略 | //+------------------------------------------------------------------+ void CheckForClose()//平仓检查(判断平仓条件及其处理) { double ma;//定义局部变量ma小数型 //---- 只在一个k 收盘另一个新出现时交易 if(Volume[0]>1) return;//如果当前K 线的成交价次数>1 时,则返回 //---- get Moving Average //获取均线数值 ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0); //获取当前以收盘价为基准计算出的均线数值 for(int i=0;i<OrdersTotal();i++) //计次循环(变量i=0至定单总数,每次递增1) { 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]<ma) { //如果第1 根K 线开盘价下穿均线时(即开盘价高于均价而收盘价低于均价时),则进行多头平仓(仓单编号,持仓数量,买价,滑点=3,用白色箭头显示) if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White)) Print("OrderClose error ",GetLastError()); } break;//跳出循环 } if(OrderType()==OP_SELL) //如果是空单 { if(Open[1]<ma && Close[1]>ma) { //如果第1根K线开盘价上穿均线时(即开盘价低于均价而收盘价高于均价时),则进行空头平仓(仓单编号,持仓数量,卖价,滑点=3,用白色箭头显示) if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White)) Print("OrderClose error ",GetLastError()); } break;//跳出循环 } } //---- } //+------------------------------------------------------------------+ //| Start function | //+------------------------------------------------------------------+ void start()//主程序—-每次成交价所驱动的运算过程 { //---- check for history and trading—对交易历史进行检查 if(Bars<100 || IsTradeAllowed()==false) return; //如果K 线数少于100 根,或者 如果允许智能交易交易=假时,返回 //---- calculate open orders by current symbol-计算当前货币对的开仓订单 if(CalculateCurrentOrders(Symbol())==0) CheckForOpen(); //如果 计算出当前货币对开仓订单数=0 (即没有仓单),则进行开仓检查。 else CheckForClose(); //否则(即当前已经有仓单时),则进行平仓检查。 //---- } //+------------------------------------------------------------------
发表评论