MA_Trend_v1

Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Series array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains close prices for each bar
Indicators Used
Moving average indicator
0 Views
0 Downloads
0 Favorites
MA_Trend_v1
ÿþ//+------------------------------------------------------------------+

//|                                                     MA_Trend.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"

#property description "MA Trend oscillator"

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

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

  {

//---

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

  {

//---

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

  }  

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

//| =48:0B>@                                                        |

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

#property indicator_separate_window

#property indicator_buffers 4

#property indicator_plots   2

//--- plot MATrend

#property indicator_label1  "MA Trend"

#property indicator_type1   DRAW_COLOR_HISTOGRAM

#property indicator_color1  clrGreen,clrMediumSeaGreen,clrRed,clrDarkSalmon,clrDarkGray

#property indicator_style1  STYLE_SOLID

#property indicator_width1  2

//--- plot Edge

#property indicator_label2  "Edge"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrDarkGray

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- input parameters

input uint                 InpPeriodStart    =  10;            // First MA period

input uint                 InpPeriodStep     =  10;            // Step

input uint                 InpCountMA        =  50;            // MA count

input ENUM_MA_METHOD       InpMethod         =  MODE_SMA;      // Method

input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price

//--- indicator buffers

double         BufferMATrend[];

double         BufferColors[];

double         BufferEdge[];

double         BufferPrice[];

//--- global variables

int            period_first;

int            period_step;

int            cnt;

int            handle_ma;

CArrayObj      array_ma;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- set global variables

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

   period_step=int(InpPeriodStep<1 ? 1 : InpPeriodStep);

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

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferMATrend,INDICATOR_DATA);

   SetIndexBuffer(1,BufferColors,INDICATOR_COLOR_INDEX);

   SetIndexBuffer(2,BufferEdge,INDICATOR_DATA);

   SetIndexBuffer(3,BufferPrice,INDICATOR_DATA);

//--- setting indicator parameters

   IndicatorSetString(INDICATOR_SHORTNAME,"MA Trend "+(string)cnt+" "+MethodToString(InpMethod)+" (Periods from "+(string)period_first+", step "+(string)period_step+")");

   IndicatorSetInteger(INDICATOR_DIGITS,Digits()+1);

//--- setting plot buffer parameters

   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferMATrend,true);

   ArraySetAsSeries(BufferColors,true);

   ArraySetAsSeries(BufferEdge,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+=period_step;

     }

//--- :>=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(close,true);

//--- @>25@:0 :>;8G5AB20 4>ABC?=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-2;

      ArrayInitialize(BufferMATrend,EMPTY_VALUE);

      ArrayInitialize(BufferColors,4);

      ArrayInitialize(BufferEdge,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;

      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)

            continue;

            

         if(close[i]>ma)

            sum+=1;

         else if(close[i]<ma)

            sum-=1;

        }

      BufferMATrend[i]=BufferEdge[i]=sum/cnt;

      BufferColors[i]=

        (

         BufferMATrend[i]>0 ? (BufferMATrend[i]>BufferMATrend[i+1] ? 0 : BufferMATrend[i]<BufferMATrend[i+1] ? 3 : 4) : 

         BufferMATrend[i]<0 ? (BufferMATrend[i]<BufferMATrend[i+1] ? 2 : BufferMATrend[i]>BufferMATrend[i+1] ? 1 : 4) : 4

        );

     }

   

//--- 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

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---