外汇EA——基于均线的简单EA

上次写了一个简单的均线ea,在图标中同时显示SMA,WMA,EMA,今天写了一个基于SMA和EMA的简单ea,当然,想靠他盈利是不可能的,看代码吧

//+------------------------------------------------------------------+
//|                                                        ma_ea.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                          http://coderaladdin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://coderaladdin.com"
#property version   "1.00"
#property strict

#define MAGIC_NUM 20150312

//--- input parameters
input int      period=19;
input int      max_orders=10;
input double      per_lot=0.01;
input double   risk_rate=0.1;

double calcLots() {
   double   lot=per_lot;   
   double minLot = MarketInfo(Symbol(),MODE_MINLOT);
   
   lot=NormalizeDouble(risk_rate*AccountFreeMargin()/AccountLeverage(),1);
   
   if(lot<0.1) lot=0.1;
   if(lot<minLot) lot=minLot;
   return(lot);
}

void CheckForOpen()
  {
   double ema;
   double sma;
   int    res;
//--- go trading only for first tiks of new bar
//   if(Volume[0]>1) return;
//--- get Moving Average 
    sma=iMA(NULL,0,period,0,MODE_SMA,PRICE_CLOSE,0);
    ema=iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,0);
   
//--- sell conditions
   if(Open[1]>ema && Open[1]>sma && ema<sma && Close[1]<ema && Close[1]<sma)
     {
      res=OrderSend(Symbol(),OP_SELL,calcLots(),Bid,3,0,0,"",MAGIC_NUM,0,Red);
      return;
     }
//--- buy conditions
   if(Open[1]<ema && Open[1]<sma && Close[1]>sma && Close[1]>ema && ema>sma)
     {
      res=OrderSend(Symbol(),OP_BUY,calcLots(),Ask,3,0,0,"",MAGIC_NUM,0,Blue);
      return;
     }
//---
  }
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
  {
   double sma;
   double ema;
//--- go trading only for first tiks of new bar
//   if(Volume[0]>1) return;
//--- get Moving Average 
    sma=iMA(NULL,0,period,0,MODE_SMA,PRICE_CLOSE,0);
    ema=iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,0);
//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderMagicNumber()!=MAGIC_NUM || OrderSymbol()!=Symbol()) continue;
      //--- check order type 
      if(OrderType()==OP_BUY)
        {
         if(Open[1]>sma && Open[1]>ema && Close[1]<ema && Close[1]<sma && ema<sma)
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White))
               Print("OrderClose error ",GetLastError());
           }
         break;
        }
      if(OrderType()==OP_SELL)
        {
         if(Open[1]<sma && Open[1]<ema && Close[1]>ema && Close[1]>sma && ema>sma)
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White))
               Print("OrderClose error ",GetLastError());
           }
         break;
        }
     }
//---
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(Bars<100 || IsTradeAllowed()==false) return;
   
   if(OrdersTotal() <=10) CheckForOpen();                            //  
   else  CheckForClose();
  }
//+------------------------------------------------------------------+

再来看下这个ea下的单
QQ截图20150314102731

外汇指标——Moving Averages

今天开始争取每周一到两篇外汇指标原理分析以及mql4样例代码,今天要剖析的是最简单而又常用的移动平均线(Moving Averages)。
移动平均线又分为简单移动平均线(Simple Moving Averages),加权移动平均线(Weighted Moving Averages),指数移动平均线(Exponential Moving Averages)等
例如当前有XAUUSD的10天收盘价信息
2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55
2015.01.06 1218.15
2015.01.07 1210.64
2015.01.08 1208.42
2015.01.09 1222.65
2015.01.12 1227.33
根据以上数据我们可以拿到5天的SMA数据
00a1563f5d7e4a9957c71b90e454e08c
226058487602d8729ea847567d39c54d
2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55 1191.548
2015.01.06 1218.15 1198.584
2015.01.07 1210.64 1200.708
2015.01.08 1208.42 1205.96
2015.01.09 1222.65 1212.882
2015.01.12 1227.33 1217.438
再来看加权移动平均(线性加权)
指计算平均值时将数据乘以不同数值,在技术分析中,n日WMA的最近期一个数值乘以n、次近的乘以n-1,如此类推,一直到0:

上式可以推导出72f344ddd46baa0134d886e42df195fc

2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55 1191.548 1193.626667
2015.01.06 1218.15 1198.584 1202.494
2015.01.07 1210.64 1200.708 1206.512667
2015.01.08 1208.42 1205.96 1209.083333
2015.01.09 1222.65 1212.882 1214.646667
2015.01.12 1227.33 1217.438 1219.462667
再来看指数移动平均数
是以指数式递减加权的移动平均。各数值的加权影响力随时间而指数式递减,越近期的数据加权影响力越重,但较旧的数据也给予一定的加权值
加权的程度以常数α决定,α数值介乎0至1。α也可用天数N来代表:0c3be7f0484ec9ee2888b7b2cb901dc1,所以,N=19天,代表α=0.1。
设时间t的实际数值为Yt,而时间t的EMA则为St;时间t-1的EMA则为St-1,计算时间t≥2是方程式为:
a8b4b375513994c0561fb5df58f10f26
EMA的公式推导见
QQ截图20150311003022
根据我们这边给N=5(通常用12和26比较常用)
那么可以知道k=20.7,也就是说我们要至少拿到前20天的数据才能推导出第一个EMA的值了(实际计算中并没有严格按照这样的数学逻辑计算,而是把第一天的收盘价当成第一个EMA值)
这边我们就不去计算了,因为mt4中都有现成的API计算好了,以上所有的指标都是有的
可以到
Include文件夹下看MovingAverages.mqh这个头文件

//+------------------------------------------------------------------+
//|                                               MovingAverages.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//+------------------------------------------------------------------+
//| Simple Moving Average                                            |
//+------------------------------------------------------------------+
double SimpleMA(const int position,const int period,const double &price[])
  {
//---
   double result=0.0;
//--- check position
   if(position>=period-1 && period>0)
     {
      //--- calculate value
      for(int i=0;i<period;i++) result+=price[position-i];
      result/=period;
     }
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Exponential Moving Average                                       |
//+------------------------------------------------------------------+
double ExponentialMA(const int position,const int period,const double prev_value,const double &price[])
  {
//---
   double result=0.0;
//--- calculate value
   if(period>0)
     {
      double pr=2.0/(period+1.0);
      result=price[position]*pr+prev_value*(1-pr);
     }
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Smoothed Moving Average                                          |
//+------------------------------------------------------------------+
double SmoothedMA(const int position,const int period,const double prev_value,const double &price[])
  {
//---
   double result=0.0;
//--- check position
   if(period>0)
     {
      if(position==period-1)
        {
         for(int i=0;i<period;i++) result+=price[position-i];
         result/=period;
        }
      if(position>=period)
         result=(prev_value*(period-1)+price[position])/period;
     }
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Linear Weighted Moving Average                                   |
//+------------------------------------------------------------------+
double LinearWeightedMA(const int position,const int period,const double &price[])
  {
//---
   double result=0.0,sum=0.0;
   int    i,wsum=0;
//--- calculate value
   if(position>=period-1 && period>0)
     {
      for(i=period;i>0;i--)
        {
         wsum+=i;
         sum+=price[position-i+1]*(period-i+1);
        }
      result=sum/wsum;
     }
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Simple moving average on price array                             |
//+------------------------------------------------------------------+
int SimpleMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
                     const int period,const double& price[],double& buffer[])
  {
   int i,limit;
//--- check for data
   if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);
   if(as_series_price)  ArraySetAsSeries(price,false);
   if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
   if(prev_calculated==0) // first calculation
     {
      limit=period+begin;
      //--- set empty value for first bars
      for(i=0;i<limit-1;i++) buffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
         firstValue+=price[i];
      firstValue/=period;
      buffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total;i++)
      buffer[i]=buffer[i-1]+(price[i]-price[i-period])/period;
//--- restore as_series flags
   if(as_series_price)  ArraySetAsSeries(price,true);
   if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
    return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Exponential moving average on price array                       |
//+------------------------------------------------------------------+
int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
                          const int period,const double& price[],double& buffer[])
  {
   int    i,limit;
//--- check for data
   if(period<=1 || rates_total-begin<period) return(0);
   double dSmoothFactor=2.0/(1.0+period);
//--- save as_series flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);
   if(as_series_price)  ArraySetAsSeries(price,false);
   if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      limit=period+begin;
      //--- set empty value for first bars
      for(i=0;i<begin;i++) buffer[i]=0.0;
      //--- calculate first visible value
      buffer[begin]=price[begin];
      for(i=begin+1;i<limit;i++)
         buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total;i++)
      buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);
//--- restore as_series flags
   if(as_series_price)  ArraySetAsSeries(price,true);
   if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
    return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Linear weighted moving average on price array                   |
//+------------------------------------------------------------------+
int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
                             const int period,const double& price[],double& buffer[],int &weightsum)
  {
   int        i,limit;
   double     sum;
//--- check for data
   if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);
   if(as_series_price)  ArraySetAsSeries(price,false);
   if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      weightsum=0;
      limit=period+begin;
      //--- set empty value for first bars
      for(i=0;i<limit;i++) buffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
        {
         int k=i-begin+1;
         weightsum+=k;
         firstValue+=k*price[i];
        }
      firstValue/=(double)weightsum;
      buffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total;i++)
     {
      sum=0;
      for(int j=0;j<period;j++) sum+=(period-j)*price[i-j];
      buffer[i]=sum/weightsum;
     }
//--- restore as_series flags
   if(as_series_price)  ArraySetAsSeries(price,true);
   if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
    return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Smoothed moving average on price array                          |
//+------------------------------------------------------------------+
int SmoothedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
                       const int period,const double& price[],double& buffer[])
  {
   int i,limit;
//--- check for data
   if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);
   if(as_series_price)  ArraySetAsSeries(price,false);
   if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      limit=period+begin;
      //--- set empty value for first bars
      for(i=0;i<limit-1;i++) buffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
         firstValue+=price[i];
      firstValue/=period;
      buffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total;i++)
      buffer[i]=(buffer[i-1]*(period-1)+price[i])/period;
//--- restore as_series flags
   if(as_series_price)  ArraySetAsSeries(price,true);
   if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
    return(rates_total);
  }
//+------------------------------------------------------------------+

今天写了一个涵盖SMA,WMA,EMA的indicator,同时显示在图表上,代码如下(EMA第一个值默认和第一个收盘价相同)

//+------------------------------------------------------------------+
//|                                              moving_averages.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                          http://coderaladdin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://coderaladdin.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3
//--- plot SMA
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot WMA
#property indicator_label2  "WMA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot EMA
#property indicator_label3  "EMA"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- input parameters
input int      period=19;
//--- indicator buffers
double         SMABuffer[];
double         WMABuffer[];
double         EMABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorBuffers(3);
//--- indicator buffers mapping
   SetIndexBuffer(0,SMABuffer);
   SetIndexBuffer(1,WMABuffer);
   SetIndexBuffer(2,EMABuffer);
   string shortname = "EMA("+string(MODE_SMA)+")WMA("+string(MODE_LWMA)+")EMA("+string(MODE_EMA)+"["+string(period)+"]";
   IndicatorShortName(shortname);
   SetIndexLabel(0,"SMA");
   SetIndexLabel(1,"WMA");
   SetIndexLabel(2,"EMA");
   SetIndexDrawBegin(0,period);
   SetIndexDrawBegin(1,period);
   SetIndexDrawBegin(2,period);
   IndicatorDigits(Digits);
   
   if(period<2)
      return(INIT_FAILED);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
if(rates_total < period -1 || period <2)
  {
   return 0;
  }
ArraySetAsSeries(SMABuffer,false);
ArraySetAsSeries(WMABuffer,false);
ArraySetAsSeries(EMABuffer,false);
ArraySetAsSeries(close,false);
if(prev_calculated==0){
      ArrayInitialize(SMABuffer,0);
      ArrayInitialize(WMABuffer,0);
      ArrayInitialize(EMABuffer,0);
      }
      
       CalculateSimpleMA(rates_total,prev_calculated,close); 
       CalculateLWMA(rates_total,prev_calculated,close);
       CalculateEMA(rates_total,prev_calculated,close);
       
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total,int prev_calculated,const double &price[])
  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
   
     {
      limit=period;
      //--- calculate first visible value
      double firstValue=0;
      for(i=0; i<limit; i++)
         firstValue+=price[i];
      firstValue/=period;
      SMABuffer[limit-1]=firstValue;
     }
   else
      limit=prev_calculated-1;
//--- main loop
   for(i=limit; i<rates_total && !IsStopped(); i++)
      SMABuffer[i]=SMABuffer[i-1]+(price[i]-price[i-period])/period;
//---
  }
//+------------------------------------------------------------------+
//|  exponential moving average                                      |
//+------------------------------------------------------------------+
void CalculateEMA(int rates_total,int prev_calculated,const double &price[])
  {
   int    i,limit;
   double SmoothFactor=2.0/(1.0+period);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      limit=period;
      EMABuffer[0]=price[0];
      for(i=1; i<limit; i++)
         EMABuffer[i]=price[i]*SmoothFactor+EMABuffer[i-1]*(1.0-SmoothFactor);
     }
   else
      limit=prev_calculated-1;
//--- main loop
   for(i=limit; i<rates_total && !IsStopped(); i++)
      EMABuffer[i]=price[i]*SmoothFactor+EMABuffer[i-1]*(1.0-SmoothFactor);
//---
  }
//+------------------------------------------------------------------+
//|  linear weighted moving average                                  |
//+------------------------------------------------------------------+
void CalculateLWMA(int rates_total,int prev_calculated,const double &price[])
  {
   int        i,limit;
   static int weightsum;
   double     sum;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      weightsum=0;
      limit=period;
      //--- calculate first visible value
      double firstValue=0;
      for(i=0;i<limit;i++)
        {
         int k=i+1;
         weightsum+=k;
         firstValue+=k*price[i];
        }
      firstValue/=(double)weightsum;
      WMABuffer[limit-1]=firstValue;
     }
   else
      limit=prev_calculated-1;
//--- main loop
   for(i=limit; i<rates_total && !IsStopped(); i++)
     {
      sum=0;
      for(int j=0;j<period;j++)
         sum+=(period-j)*price[i-j];
      WMABuffer[i]=sum/weightsum;
     }
     }

来看下这个指标的具体效果,在图标中同时显示EMA,SMA,WMA
QQ截图20150314102843
Ok,今天介绍的MA指标就这样了,下次介绍MACD指标