Having challenges as how to use "SimpleMA", "ExponentialMA" and "LinearWeightedMA" function from MovingAverages.mqh

 

Hello ALL

I have created CIndicatorBase, CiMA.mqh and iMA.mq5.

The challenge I am facing is as how to use Moving Average Functions for calculating MA on a single Index. I have populated custom price array (for input to the function) for required number of bars needed for MAPeriod.

I have tried to use price_CLOSE and MODE_LWMA and created CustomFunction: CiMA::GetLinearWeightedMA(int pPosition,int pMAPeriod,double &pPrice[]), as I found at some index price returned was zero, and MQL function was averaging including zero values.

The Blue line in the png file represents Indicator plotted by Custom iMA.mq5 where as the Red line represent MQL5 iMA Indicator plot with same settings.

As clear from it, blue line is lagging behind, and I am just wondering if I am using MA Functions correctly or some other error I am not able to realize.

The purpose of this exercise is important for me as I have quite a few custom indicators to create with custom price data, and averaging is integral part of it.

Support from experts are highly appreciated.

Thanks in Advance.

CODE FOR CIndicatorBase.mqh [Could not paste here as message exceeded 64000 characters limit. Hence attached as file]

CODE FOR CiMA.mqh

#include "../../Include/Base/IndicatorBase.mqh"

//+-----------------------------------------------------------------------------------------------------------------------------+
//| CLASS:                              CiMA.mqh
//| APPLICATION:        CLASS FOR MOVING AVERAGE
//+-----------------------------------------------------------------------------------------------------------------------------+
class CiMA final : public CIndicatorBase {

private:

        int                                     mMAPeriod;                                                                                                                                                                      // AVERAGING PERIOD

        // MEMBER ARRAYs FOR INTERNAL CALCULATIONS
        double                  mBufferPrice[];                                                                                                                                                 // TEMPORARY ARRAY TO HOLD 'n' PERIODS PRICE DATA
        double                  mBufferMA[];
        double                  GetLinearWeightedMA(int pPosition,int pMAPeriod,double &pPrice[]);

public:

  CiMA() : CIndicatorBase() { }
  CiMA(string pSymbol,ENUM_TIMEFRAMES pTimeFrame,int pMAPeriod,CENUM_APPLIED_PRICE pAppliedPrice,
                 ENUM_MA_METHOD pAppliedMAMode)
        : CIndicatorBase()
        { InitClass(pSymbol,pTimeFrame,pMAPeriod,pAppliedPrice,pAppliedMAMode); }
 ~CiMA();

        // METHOD OF INITIALIZE INDICATOR HANDLES
        void                            InitClass(string pSymbol,ENUM_TIMEFRAMES pTimeFrame,int pMAPeriod,CENUM_APPLIED_PRICE pAppliedPrice,
                                                                                                 ENUM_MA_METHOD pAppliedMAMode);

        // METHODS TO RETURN INDICATOR VALUES TO CALLING EA / CLASS
        void                            GetArray(int pCount,double &pMA[]);
        double                  GetIndex(int pIndex);

}; // END Of Class Definition
//+-----------------------------------------------------------------------------------------------------------------------------+
//| METHOD:       ~CiMA()
//| APPLICATION:  DECONSTRUCTOR METHOD
//+-----------------------------------------------------------------------------------------------------------------------------+
CiMA::~CiMA() {


} // END Of default deconstructor ~CiMA()
//+-----------------------------------------------------------------------------------------------------------------------------+
//| METHOD:                             InitClass()
//| APPLICATION:        METHOD TO INITIALIAZE MEMBER VARIABLES OF THE INDICATOR CLASS
//+-----------------------------------------------------------------------------------------------------------------------------+
void CiMA::InitClass(string pSymbol,ENUM_TIMEFRAMES pTimeFrame,int pMAPeriod,CENUM_APPLIED_PRICE pAppliedPrice,
                                                                                 ENUM_MA_METHOD pAppliedMAMode) {

        // ASSIGN SYMBOL AND TIME FRAME
        mSymbol          = pSymbol;
        mTimeFrame = pTimeFrame;

        // ASSIGN INDICATOR DEFAULTS
        mMAPeriod                        = pMAPeriod;
        mAppliedPrice  = pAppliedPrice;                                                                                                                         // OVERRIDE CIndicatorBase DEFAULT
        mAppliedMAMode = pAppliedMAMode;                                                                                                                        // OVERRIDE CIndicatorBase DEFAULT

} // END Of method InitClass()
//+-----------------------------------------------------------------------------------------------------------------------------+
//| METHOD:                     GetArray()
//| APPLICATION:  METHOD TO RETURN MOVING AVERAGE VALUES INTO PASSED IN STRUCTURE ARRAY
//+-----------------------------------------------------------------------------------------------------------------------------+
void CiMA::GetArray(int pCount,double &pMA[]) {


} // END Of method GetArray()
//+-----------------------------------------------------------------------------------------------------------------------------+
//| METHOD:                     GetIndex()
//| APPLICATION:  METHOD TO RETURN MA VALUE ON SPECIFIED INDEX
//+-----------------------------------------------------------------------------------------------------------------------------+
double CiMA::GetIndex(int pIndex) {

        // COLLECT PRICE DATA INTO TEMPORARY ARRAY FOR 5 ADDITIONAL BARS OVER mMAPeriod + pIndex
        double result = 0.00;
        int posStart  = pIndex;                                                                                                         // START GETTING DATA FROM pIndex VALUE
        int count               = pIndex + mMAPeriod;                                                           // END   GETTING DATA

        // PREPARE ARRAY
        //ArraySetAsSeries(mBufferPrice,true);
        ArrayFree(mBufferPrice);                                                                                                        // FREE ARRAY ELEMENTS FOR NEXT CALCULATION
        ArrayResize(mBufferPrice,count);

        // GET DATA IN DEFAULT ARRAY INDEXING ORDER. i.e. ArrayNotSeries
        for(int i = count -1; i >= pIndex && !IsStopped(); i--) {

                // CALCULATE APPLIED PRICE AND POPULATE mBufferPrice ARRAY FOR AVERAGE CALCULATION
                switch(mAppliedPrice) {
                        case price_CLOSE:                                       mBufferPrice[i] = GetIndexPrice(price_CLOSE,i);
                        case price_OPEN:                                        mBufferPrice[i] = GetIndexPrice(price_OPEN,i);
                        case price_HIGH:                                        mBufferPrice[i] = GetIndexPrice(price_HIGH,i);
                        case price_LOW:                                         mBufferPrice[i] = GetIndexPrice(price_LOW,i);
                        case price_MEDIAN:                              mBufferPrice[i] = GetIndexPrice(price_MEDIAN,i);
                        case price_TYPICAL:                             mBufferPrice[i] = GetIndexPrice(price_TYPICAL,i);
                        case price_WEIGHTED:                    mBufferPrice[i] = GetIndexPrice(price_WEIGHTED,i);
                        case priceHA_CLOSE:                             mBufferPrice[i] = GetIndexPrice(priceHA_CLOSE,i);
                        PrintFormat("Index[%i] %s[%.1f]",i,EnumToString(mAppliedPrice),mBufferPrice[i]);
                }

                // NOTE: mBufferPrice NOW CONTAINS NO OF ELEMENTS = mMAPeriod INDEX[mMAPeriod] TO INDEX[0]
                // CALCULATE MOVING AVERAGE BASED ON mAppliedMAMethod FOR POSITION INDEX[0]
                switch(mAppliedMAMode) {

                        //case MODE_EMA:                                                result = ExponentialMA(pIndex,mMAPeriod,mPrevValue,mBufferPrice);
                        case MODE_LWMA:                                         result = GetLinearWeightedMA(pIndex,mMAPeriod,mBufferPrice);
                        case MODE_SMA:                                          result = SimpleMA(pIndex,mMAPeriod,mBufferPrice);
                }
        } // end of for..loop

        // IF NONE OF ABOVE
        //PrintFormat("Result[%i] MA[%.1f]",pIndex,result);
        return(result);

} // END Of method GetIndex()
//+-----------------------------------------------------------------------------------------------------------------------------+

//+-----------------------------------------------------------------------------------------------------------------------------+
//| Linear Weighted Moving Average
//| Custom function created for cross checking with printout and ignoring Zero Price values in average
//+-----------------------------------------------------------------------------------------------------------------------------+
double CiMA::GetLinearWeightedMA(int pPosition,int pMAPeriod,double &pPrice[]) {

        double result = 0.0;

        // CHECK PERIOD IS VALID FOR CALCULATION
        if(pMAPeriod > 0 && pMAPeriod <= (pPosition + 1)) {

                int    wsum = 0;
          double sum  = 0.00;
        
          for(int i = pMAPeriod; i > 0; i--) {

                        double posPrice = pPrice[pPosition-i+1];
                        if(posPrice != 0.00) {
                                wsum += i;
                                sum  += posPrice * (pMAPeriod-i+1);
                                PrintFormat("Index[%i] pPrice[%.1f] * weight(pMAPeriod-i+1)[%i] = weightedPrice[%.1f]",(pPosition-i+1),posPrice,(pMAPeriod-i+1),(posPrice * (pMAPeriod-i+1)));
                        }
                }
        
                result = sum / wsum;
                PrintFormat("result[%.1f] sum[%.1f] wsum[%i]",result,sum,wsum);
        }

        return(result);

} // END Of method GetLinearWeightedMA()
//+-----------------------------------------------------------------------------------------------------------------------------+

CODE FOR Custom CiMA.mql INDICATOR

  #property description "Moving Average"
  #property description "1) Selectable Price Method (including Heiken Ashi Price) DEFAULT price_TYPICAL"
  #property description "2) Selectable Moving Average Method DEFAULT MODE_LWMA"

  #property indicator_chart_window
  #property indicator_buffers  1
  #property indicator_plots    1

        #include        "../../../Experts/AKTAlgo/Indicator/Trend/iMA.mqh"
        #define         _BufferMA               MAIN_LINE

//+-----------------------------------------------------------------------------------------------------------------------------+
//| Define Input Parameters
//+-----------------------------------------------------------------------------------------------------------------------------+
  input int                     MAPeriod      = 21;
  input CENUM_APPLIED_PRICE     AppliedPrice  = price_CLOSE;            // APPLIED PRICE
        input ENUM_MA_METHOD                            AppliedMethod = MODE_LWMA;                              // APPLIED MA METHOD
        input color                                                                     AppliedColor  = clrDodgerBlue;          // COLOR OF MA LINE
//+-----------------------------------------------------------------------------------------------------------------------------+
//| Define Indicator Handle(s) and Buffer(s)
//+-----------------------------------------------------------------------------------------------------------------------------+
        string                          DataLabel = NULL;
  double                                BufferMA[];
        CiMA                                    *MA;

//+-----------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function
//+-----------------------------------------------------------------------------------------------------------------------------+
int OnInit() {
  //+---------------------------------------------------------------------------------------------------------------------------+
  //| Indicator SubWindow common 'properties'
  //+---------------------------------------------------------------------------------------------------------------------------+
    IndicatorSetString(INDICATOR_SHORTNAME,"iMA ("+IntegerToString(MAPeriod)+", "+EnumToString(AppliedPrice)+", "+
                                                                         EnumToString(AppliedMethod)+") ");
    IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
  //+---------------------------------------------------------------------------------------------------------------------------+
  //| Indicator Buffers mapping / binding
  //+---------------------------------------------------------------------------------------------------------------------------+
    SetIndexBuffer(_BufferMA,BufferMA,INDICATOR_DATA);
                ArraySetAsSeries(BufferMA,true);
  //+---------------------------------------------------------------------------------------------------------------------------+
  //| Plot Indicator Labels in DataWindow
  //+---------------------------------------------------------------------------------------------------------------------------+
                if(AppliedMethod == MODE_LWMA)          DataLabel = "MA LWMA";
                if(AppliedMethod == MODE_EMA)                   DataLabel = "MA EMA";
                if(AppliedMethod == MODE_SMMA)          DataLabel = "MA SMMA";
                if(AppliedMethod == MODE_SMA)           DataLabel = "MA SMA";

    PlotIndexSetString(_BufferMA,PLOT_LABEL,DataLabel+" ("+IntegerToString(MAPeriod)+")");
    PlotIndexSetInteger(_BufferMA,PLOT_DRAW_TYPE,DRAW_LINE);
    PlotIndexSetInteger(_BufferMA,PLOT_LINE_STYLE,STYLE_SOLID);
    PlotIndexSetInteger(_BufferMA,PLOT_LINE_COLOR,AppliedColor);
    PlotIndexSetInteger(_BufferMA,PLOT_LINE_WIDTH,2);
    PlotIndexSetDouble(_BufferMA,PLOT_EMPTY_VALUE,EMPTY_VALUE);

        //
        MA = new CiMA(_Symbol,(ENUM_TIMEFRAMES)_Period,MAPeriod,AppliedPrice,AppliedMethod);

  //---
   return(INIT_SUCCEEDED);

} // End of OnInit()
//+-----------------------------------------------------------------------------------------------------------------------------+
//| OnDeinit()
//+-----------------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason) {

        delete MA;

} // END Of OnDeinit()
//+-----------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator iteration function
//+-----------------------------------------------------------------------------------------------------------------------------+
int OnCalculate(const int    rates_total,
                const int    prev_calculated,
                const int    begin,
                const double &price[]) {

        if(rates_total < MAPeriod)                                                                                      return(0);                      // ENOUGH BARS AVAILABLE

  // SET HOW MANY BARS TO CALCULATE
        int limit = rates_total - prev_calculated - MAPeriod;
        if(prev_calculated > 0)                                                                                                 limit++;                                // FORCE TO RECALCULATE INDEX[0]

        for(int i = limit-1; i >= 0 && !IsStopped(); i--) {
                BufferMA[i] = MA.GetIndex(i);
        }

  // OnCalculate() DONE. RETURN NEW prev_calculated FOR NEXT ITIRATION
        return(rates_total);

} // END Of OnCalculate())
//+-----------------------------------------------------------------------------------------------------------------------------+
Documentation on MQL5: Timeseries and Indicators Access / Bars
Documentation on MQL5: Timeseries and Indicators Access / Bars
  • www.mql5.com
Bars - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
Files:
US30M15.png  200 kb
 

use CHATGPT 4.o together with the metaEditor for MQL5. You will have got a clever combination at solving challenges in your coding endeavours.