Author: Copyright 2018, MetaQuotes Software Corp.
2 Views
0 Downloads
0 Favorites
Avg_MA
ÿþ//+------------------------------------------------------------------+

//|                                                       Avg_MA.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

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

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property version   "1.00"

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

//| ;0AA A:>;L7OI8E A@54=8E                                         |

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

#include <Arrays\ArrayObj.mqh>

class CAvg : public CObject

  {

protected:

   ENUM_TIMEFRAMES      m_timeframe;

   string               m_symbol;

   int                  m_period;

   ENUM_MA_METHOD       m_method;

   ENUM_APPLIED_PRICE   m_price;

   int                  m_rates_total;

   double               m_prev_value;

   //---

   bool                 CheckPosition(const int rates_total,const int period,const int index)   const { return(period>=1 && index<=rates_total-period-1);   }

   double               Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)         const;

   double               High(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)         const;

   double               Low(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)          const;

   double               Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)        const;

   double               Median(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)       const;

   double               Typical(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)      const;

   double               Weighted(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index)     const;

public:

   void                 Timeframe(const ENUM_TIMEFRAMES timeframe)                                                   { this.m_timeframe=timeframe;          }

   void                 Method(const ENUM_MA_METHOD method)                                                          { this.m_method=method;                }

   void                 AppliedPrice(ENUM_APPLIED_PRICE price)                                                       { this.m_price=price;                  }

   void                 Symbol(const string symbol_name)                                                             { this.m_symbol=symbol_name;           }

   void                 Period(const int period)                                                                     { this.m_period=period;                }

   ENUM_TIMEFRAMES      Timeframe(void)                                                                        const { return this.m_timeframe;             }

   ENUM_MA_METHOD       Method(void)                                                                           const { return this.m_method;                }

   ENUM_APPLIED_PRICE   AppliedPrice(void)                                                                     const { return this.m_price;                 }

   string               Symbol(void)                                                                           const { return this.m_symbol;                }

   int                  Period(void)                                                                           const { return this.m_period;                }

   int                  RatesTotal(void)                                                                       const { return this.m_rates_total;           }

   double               AppliedPrice(const ENUM_APPLIED_PRICE applied_price,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const;

   double               AppliedPrice(const int index)                                                          const;

   double               SMA(const int rates_total,const int period,const int index,const double &price[]);

   double               EMA(const int rates_total,const int period,const int index,const double &price[]);

   double               SMMA(const int rates_total,const int period,const int index,const double &price[]);

   double               LWMA(const int rates_total,const int period,const int index,const double &price[]);

   double               GetMA(const int rates_total,const ENUM_MA_METHOD method,const int period,const int index,const double &price[]);

   double               GetMA(const int rates_total,const int index,const double &price[]);

   string               MethodToString(const ENUM_MA_METHOD method)     const { return ::StringSubstr(::EnumToString(method),5);       }

   string               MethodToString(void)                            const { return ::StringSubstr(::EnumToString(this.m_method),5);}

   string               PriceToString(const ENUM_APPLIED_PRICE price)   const { return ::StringSubstr(::EnumToString(price),6);        }

   string               PriceToString(void)                             const { return ::StringSubstr(::EnumToString(this.m_price),6); }

                        CAvg(const int rates_total,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int period);

                        CAvg(void) : m_prev_value(0){;}

                       ~CAvg(void){;}

  };

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

//| CAvg >=AB@C:B>@                                                 |

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

CAvg::CAvg(const int rates_total,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int period) : m_prev_value(0)

  {

   this.m_symbol=symbol_name;

   this.m_timeframe=timeframe;

   this.m_period=period;

   this.m_rates_total=rates_total;

  }

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

//| CAvg 2>72@0I05B 7=0G5=85 MA                                      |

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

double CAvg::GetMA(const int rates_total,const int index,const double &price[])

  {

   this.m_rates_total=rates_total;

   switch(this.m_method)

     {

      case MODE_EMA  :  return this.EMA(this.m_rates_total,this.m_period,index,price);

      case MODE_SMMA :  return this.SMMA(this.m_rates_total,this.m_period,index,price);

      case MODE_LWMA :  return this.LWMA(this.m_rates_total,this.m_period,index,price);

      //---MODE_SMA

      default        :  return this.SMA(this.m_rates_total,this.m_period,index,price);

     }

  }

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

//| CAvg 2>72@0I05B 7=0G5=85 MA                                      |

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

double CAvg::GetMA(const int rates_total,const ENUM_MA_METHOD method,const int period,const int index,const double &price[])

  {

   switch(method)

     {

      case MODE_EMA  :  return this.EMA(rates_total,period,index,price);

      case MODE_SMMA :  return this.SMMA(rates_total,period,index,price);

      case MODE_LWMA :  return this.LWMA(rates_total,period,index,price);

      //---MODE_SMA

      default        :  return this.SMA(rates_total,period,index,price);

     }

  }

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

//| CAvg Simple Moving Average                                       |

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

double CAvg::SMA(const int rates_total,const int period,const int index,const double &price[])

  {

//---

   double result=0.0;

//--- check position

   if(!this.CheckPosition(rates_total,period,index))

      return 0;

//--- calculate value

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

     result=result+price[index+i];

   result/=period;

//---

   return result;

  }

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

//| CAvg Exponential Moving Average                                  |

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

double CAvg::EMA(const int rates_total,const int period,const int index,const double &price[])

  {

//---

   //static double prev_value=0;

   double result=0.0;

//--- check position

   if(!this.CheckPosition(rates_total,period,index))

      return 0;

   double pr=2.0/(period+1.0);

//--- SMA for first data

   if(index==rates_total-period-1 || this.m_prev_value==0)

      this.m_prev_value=result=this.SMA(rates_total,period,index,price);

//--- EMA

   else

     {

      result=this.m_prev_value+pr*(price[index]-this.m_prev_value);

      //--- new bar

      if(index!=0)

         this.m_prev_value=result;

     }

//---

   return result;

  }

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

//| CAvg Smoothed Moving Average                                     |

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

double CAvg::SMMA(const int rates_total,const int period,const int index,const double &price[])

  {

//---

   //static double prev_value=0;

   double result=0.0;

//--- check position

   if(!this.CheckPosition(rates_total,period,index))

      return 0;

//--- SMA for first data

   if(index==rates_total-period-1 || this.m_prev_value==0)

      this.m_prev_value=result=this.SMA(rates_total,period,index,price);

//--- SMMA

   else

     {

      result=(this.m_prev_value*(period-1)+price[index])/period;

      //--- new bar

      if(index!=0)

         this.m_prev_value=result;

     }

//---

   return result;

  }

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

//| CAvg Linear Weighted Moving Average                              |

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

double CAvg::LWMA(const int rates_total,const int period,const int index,const double &price[])

  {

//---

   double result=0.0,count=0,total=0,k=0;

//--- check position

   if(!this.CheckPosition(rates_total,period,index))

      return 0;

//--- calculate value

   for(int j=index+period-1; j>=index; j--)

     {

      count++;

      k+=count;

      total+=price[j]*count;

     }

   result=total/k;

//---

   return(result);

  }

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

//| CAvg >72@0I05B F5=C ?> 8=45:AC                                  |

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

double CAvg::AppliedPrice(const int index) const

  {

   switch(this.m_price)

     {

      case PRICE_OPEN      :  return this.Open(this.m_symbol,this.m_timeframe,index);

      case PRICE_HIGH      :  return this.High(this.m_symbol,this.m_timeframe,index);

      case PRICE_LOW       :  return this.Low(this.m_symbol,this.m_timeframe,index);

      case PRICE_CLOSE     :  return this.Close(this.m_symbol,this.m_timeframe,index);

      case PRICE_MEDIAN    :  return this.Median(this.m_symbol,this.m_timeframe,index);

      case PRICE_TYPICAL   :  return this.Typical(this.m_symbol,this.m_timeframe,index);

      //---PRICE_WEIGHTED

      default              :  return this.Weighted(this.m_symbol,this.m_timeframe,index);

     }

  }

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

//| CAvg >72@0I05B F5=C ?> 8=45:AC                                  |

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

double CAvg::AppliedPrice(const ENUM_APPLIED_PRICE applied_price,const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   switch(applied_price)

     {

      case PRICE_OPEN      :  return this.Open(symbol_name,timeframe,index);

      case PRICE_HIGH      :  return this.High(symbol_name,timeframe,index);

      case PRICE_LOW       :  return this.Low(symbol_name,timeframe,index);

      case PRICE_CLOSE     :  return this.Close(symbol_name,timeframe,index);

      case PRICE_MEDIAN    :  return this.Median(symbol_name,timeframe,index);

      case PRICE_TYPICAL   :  return this.Typical(symbol_name,timeframe,index);

      //---PRICE_WEIGHTED

      default              :  return this.Weighted(symbol_name,timeframe,index);

     }

  }

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

//| CAvg >72@0I05B F5=C Open ?> 8=45:AC                             |

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

double CAvg::Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   return(::CopyOpen(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);

  }  

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

//| CAvg >72@0I05B F5=C High ?> 8=45:AC                             |

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

double CAvg::High(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   return(::CopyHigh(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);

  }  

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

//| CAvg >72@0I05B F5=C Low ?> 8=45:AC                              |

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

double CAvg::Low(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   return(::CopyLow(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);

  }  

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

//| CAvg >72@0I05B F5=C Close ?> 8=45:AC                            |

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

double CAvg::Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   return(::CopyClose(symbol_name,timeframe,index,1,array)==1 ? array[0] : 0);

  }  

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

//| CAvg >72@0I05B <5480==CN F5=C ?> 8=45:AC                        |

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

double CAvg::Median(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   double high=this.High(symbol_name,timeframe,index);

   double low=this.Low(symbol_name,timeframe,index);

   return(high>0 && low>0 ? (high+low)/2.0 : 0);

  }  

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

//| CAvg >72@0I05B B8?8G=CN F5=C ?> 8=45:AC                         |

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

double CAvg::Typical(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   double high=this.High(symbol_name,timeframe,index);

   double low=this.Low(symbol_name,timeframe,index);

   double close=this.Close(symbol_name,timeframe,index);

   return(high>0 && low>0 && close>0 ? (high+low+close)/3.0 : 0);

  }  

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

//| CAvg >72@0I05B 2725H5==CN F5=C ?> 8=45:AC                       |

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

double CAvg::Weighted(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int index) const

  {

   double array[];

   double high=this.High(symbol_name,timeframe,index);

   double low=this.Low(symbol_name,timeframe,index);

   double close=this.Close(symbol_name,timeframe,index);

   return(high>0 && low>0 && close>0 ? (high+low+close+close)/4.0 : 0);

  }  

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

//|                                                       Avg_MA.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

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

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property description "Average from MA"

#property indicator_chart_window

#property indicator_buffers 2

#property indicator_plots   1

//--- plot AvgMA

#property indicator_label1  "AvgMA"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrMediumSlateBlue

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- enums

enum ENUM_MODE_INC

  {

   MODE_ADD,   // Addition

   MODE_MLT    // Multiplication

  };

//--- input parameters

input uint                 InpPeriodFirst    =  5;             // First MA period

input ENUM_MA_METHOD       InpMethod         =  MODE_SMA;      // Method

input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price

input uint                 InpCountMA        =  5;             // Count

input uint                 InpCoeff          =  2;             // Coefficient of increment

input ENUM_MODE_INC        InpModeInc        =  MODE_ADD;      // Incremental method

//--- indicator buffers

double         BufferAvgMA[];

double         BufferPrice[];

//--- global variables

int            period_first;

int            cnt;

int            coeff;

int            handle_ma;

CArrayObj      array_ma;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- set global variables

   period_first=int(InpPeriodFirst<1 ? 1 : InpPeriodFirst);

   cnt=int((int)InpCountMA<1 ? 1 : InpCountMA);

   uchar k=(InpModeInc==MODE_ADD ? 1 : 2);

   coeff=int(InpCoeff<k ? k : InpCoeff);

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferAvgMA,INDICATOR_DATA);

   SetIndexBuffer(1,BufferPrice,INDICATOR_CALCULATIONS);

//--- setting indicator parameters

   IndicatorSetString(INDICATOR_SHORTNAME,"Average of "+(string)cnt+" "+MethodToString(InpMethod)+" (Periods from "+(string)period_first+", step "+(string)coeff+")");

   IndicatorSetInteger(INDICATOR_DIGITS,Digits()+1);

//--- setting plot buffer parameters

   PlotIndexSetString(0,PLOT_LABEL,"Avg "+(string)cnt+" "+MethodToString(InpMethod));

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferAvgMA,true);

   ArraySetAsSeries(BufferPrice,true);

//--- create MA handle

   ResetLastError();

   handle_ma=iMA(NULL,PERIOD_CURRENT,1,0,MODE_SMA,InpAppliedPrice);

   if(handle_ma==INVALID_HANDLE)

     {

      Print("The iMA(1) object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

//---

   int period_cnt=period_first;

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

     {

      CAvg* avg=new CAvg();

      if(avg==NULL)

         continue;

      avg.Period(period_cnt);

      avg.AppliedPrice(InpAppliedPrice);

      avg.Method(InpMethod);

      avg.Symbol(Symbol());

      avg.Timeframe(Period());

      array_ma.Add(avg);

      period_cnt=(InpModeInc==MODE_ADD ? period_cnt+coeff : period_cnt*coeff);

     }

//--- :>=B@>;L 7=0G5=89 @0AAG8B0==KE 

   //int total=array_ma.Total();

   //string pr="\n";

   //for(int i=0;i<total;i++)

   //  {

   //   CAvg* avg=array_ma.At(i);

   //   int p=avg.Period();

   //   pr+=MethodToString(InpMethod)+"#"+string(i+1)+" : Period "+(string)p+"\n";

   //  }

   //Comment(pr);

//---

   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[])

  {

//--- #AB0=>2:0 <0AA82>2 1CD5@>2 :0: B09<A5@89

   ArraySetAsSeries(open,true);

   ArraySetAsSeries(high,true);

   ArraySetAsSeries(low,true);

   ArraySetAsSeries(close,true);

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   if(rates_total<4) return 0;

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-1;

      ArrayInitialize(BufferAvgMA,EMPTY_VALUE);

      ArrayInitialize(BufferPrice,0);

     }



//--- >43>B>2:0 40==KE

   int count=(limit>1 ? rates_total : 1);

   int copied=CopyBuffer(handle_ma,0,0,count,BufferPrice);

   if(copied!=count) return 0;



//---  0AGQB 8=48:0B>@0

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      double sum=0;

      double num=0;

      int total=array_ma.Total();

      for(int j=0; j<total; j++)

        {

         CAvg* avg=array_ma.At(j);

         if(avg==NULL)

            continue;

         double ma=avg.GetMA(rates_total,i,BufferPrice);

         if(ma!=0)

           {

            sum+=ma;

            num++;

           }

        }

      if(num>0)

         BufferAvgMA[i]=sum/num;

     }

   

//--- return value of prev_calculated for next call

   return(rates_total);

  }

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

//| >72@0I05B =08<5=>20=85 <5B>40                                 |

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

string MethodToString(ENUM_MA_METHOD method)

  {

   return StringSubstr(EnumToString(method),5);

  }

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

Comments