Cant find error in indicator

 

Hi All,

Can i trouble you to look into this?

Cant seem to find the error in this, the indicator repaints/recalculates.

Thank you.

//+------------------------------------------------------------------+
//|                                            Adaptive_DeMarker.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers   16
#property indicator_plots     1
#property indicator_level1    0.7
#property indicator_level2    0.5
#property indicator_level3    0.3
//--- plot DeMarker Indicator
#property indicator_label1 "DeMarker"
#property indicator_type1  DRAW_LINE
#property indicator_color1 clrGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- indicator inputs

//--- indicator buffers
double val[],valt[];
double Cycle_val[],PriceCP[],Smooth[],Cycle[],Q1[],I1[],DeltaPhase[],InstPeriod[],CyclePeriod[];      //--- CP Buffers
int p_length;
int length;
//---
double ExtDeMaxBuffer[],ExtDeMinBuffer[],ExtAvgDeMaxBuffer[],ExtAvgDeMinBuffer[],ExtDeMarkerBuffer[]; //--- FT Buffers
//--- indicator handles
int bars_calculated = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,val,INDICATOR_DATA);
   SetIndexBuffer(1,valt,INDICATOR_DATA);
//--- CP Buffers
   SetIndexBuffer(2,Cycle_val,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,PriceCP,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,Smooth,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,Cycle,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,Q1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,I1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(8,DeltaPhase,INDICATOR_CALCULATIONS);
   SetIndexBuffer(9,InstPeriod,INDICATOR_CALCULATIONS);
   SetIndexBuffer(10,CyclePeriod,INDICATOR_CALCULATIONS); 
//--- FT Buffers
   SetIndexBuffer(11,ExtDeMaxBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(12,ExtDeMinBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(13,ExtAvgDeMaxBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(14,ExtAvgDeMinBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(15,ExtDeMarkerBuffer,INDICATOR_CALCULATIONS);   
//---
   IndicatorSetString(INDICATOR_SHORTNAME,"Adaptive DeMarker");   
//---
   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<13)
      return(0);
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      {
         limit=13;
      }
   for(int i=limit;i<rates_total;i++){
         
      Cycle_val[i] = GetCyclePeriod(open,high,low,close,i,rates_total);
      p_length = int(floor((4.0*Cycle_val[i]+3*Cycle_val[i-1]+2*Cycle_val[i-2]+Cycle_val[i-3])/20.0));
//---
      length = MathMax(p_length,1);
      val[i]   = DeMarker(high,low,length,i);
      valt[i]  =  val[i-1];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Get Price                                                        |
//+------------------------------------------------------------------+
double getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars)
  {
   if(i>=0)
      switch(tprice)
        {
         case PRICE_CLOSE:     return(close[i]);
         case PRICE_OPEN:      return(open[i]);
         case PRICE_HIGH:      return(high[i]);
         case PRICE_LOW:       return(low[i]);
         case PRICE_MEDIAN:    return((high[i]+low[i])/2.0);
         case PRICE_TYPICAL:   return((high[i]+low[i]+close[i])/3.0);
         case PRICE_WEIGHTED:  return((high[i]+low[i]+close[i]+close[i])/4.0);
        }
   return(0);
  } 
//+------------------------------------------------------------------+
//| Cycle Period                                                     |
//+------------------------------------------------------------------+  
double GetCyclePeriod(const double& open[],const double& high[],const double& low[],const double& close[] , int shift, int bars)
{
   double DC, MedianDelta;
   double InpAlpha = 0.07;
   
   PriceCP[shift] = getPrice(PRICE_MEDIAN,open,close,high,low,shift,bars);
   
   Smooth[shift] = (PriceCP[shift] + 2.0*PriceCP[shift-1] + 2.0*PriceCP[shift-2]+PriceCP[shift-3])/6.0;
   
   if (shift>bars-7){
      Cycle[shift] = (1.0-0.5*InpAlpha) * (1.0-0.5*InpAlpha) * (Smooth[shift]-2.0*Smooth[shift-1]+Smooth[shift-2])+2.0*(1.0-InpAlpha)*Cycle[shift-1]-(1.0-InpAlpha)*(1.0-InpAlpha)*Cycle[shift-2];
   }
   else {
      Cycle[shift]=(PriceCP[shift]-2.0*PriceCP[shift-1]+PriceCP[shift-2])/4.0;
   }   
   
   Q1[shift] = (0.0962*Cycle[shift]+0.5769*Cycle[shift-2]-0.5769*Cycle[shift-4]-0.0962*Cycle[shift-6])*(0.5+0.08*InstPeriod[shift-1]);
   I1[shift] = Cycle[shift-3];

   if (Q1[shift]!=0.0 && Q1[shift-1]!=0.0)
      DeltaPhase[shift] = (I1[shift]/Q1[shift]-I1[shift-1]/Q1[shift-1])/(1.0+I1[shift]*I1[shift-1]/(Q1[shift]*Q1[shift-1]));
   if (DeltaPhase[shift] < 0.1)
      DeltaPhase[shift] = 0.1;
   if (DeltaPhase[shift] > 0.9)
      DeltaPhase[shift] = 0.9;
      
   MedianDelta = Median(DeltaPhase, shift, 5);
   
   if (MedianDelta == 0.0)
      DC = 15.0;
   else
      DC = (6.28318/MedianDelta) + 0.5;
      
   InstPeriod[shift] = 0.33*DC + 0.67*InstPeriod[shift-1];
   CyclePeriod[shift] = 0.15*InstPeriod[shift] + 0.85*CyclePeriod[shift-1];
      
   return(CyclePeriod[shift]);
}
// Median 
double Median(double& arr[], int idx, int m_len)
{
   double MedianArr[];
   int copied;
   double result = 0.0;
   
   ArrayResize(MedianArr, m_len);
   
   copied = ArrayCopy(MedianArr, arr, 0, idx-4, m_len);
   if (copied == m_len)
   {
      ArraySort(MedianArr);
      if (m_len %2 == 0) 
            result = (MedianArr[m_len/2] + MedianArr[(m_len/2)+1])/2.0;
      else
            result = MedianArr[m_len / 2];     
   }
   else Print(__FILE__+" "+__FUNCTION__+" median error - wrong number of elements copied. "); 
   return result; 
}
//+------------------------------------------------------------------+ 
//+------------------------------------------------------------------+
//| Demarker                                                         |
//+------------------------------------------------------------------+
double DeMarker(const double& high[],const double& low[],int period,int shift)
{
   if(high[shift]>high[shift-1])
      ExtDeMaxBuffer[shift] = high[shift] - high[shift-1];
   else
      ExtDeMaxBuffer[shift] = 0.0;
   
   if(low[shift-1]>low[shift])
      ExtDeMinBuffer[shift] = low[shift-1] - low[shift];
   else
      ExtDeMinBuffer[shift]=0.0;
      
   //ExtAvgDeMaxBuffer[shift]=SimpleMA(shift,period,ExtDeMaxBuffer);
   //ExtAvgDeMinBuffer[shift]=SimpleMA(shift,period,ExtDeMinBuffer); 
   
   double smaMax = 0.0;
   for(int j=0;j<period;j++){
      smaMax   += ExtDeMaxBuffer[shift-j];
   }
   ExtAvgDeMaxBuffer[shift] = smaMax/(double)period;
   
   double smaMin = 0.0;
   for(int j=0;j<period;j++){
      smaMin   += ExtDeMinBuffer[shift-j];
   }
   ExtAvgDeMinBuffer[shift] = smaMin/(double)period;
   
   double dnum = ExtAvgDeMaxBuffer[shift] + ExtAvgDeMinBuffer[shift];
   if(dnum!=0)
      ExtDeMarkerBuffer[shift] = ExtAvgDeMaxBuffer[shift]/dnum;
   else
      ExtDeMarkerBuffer[shift] = 0.0;
   
   return(ExtDeMarkerBuffer[shift]); 
}

Regards,

John

 

Don't double post! You already had another thread open.

          General rules and best pratices of the Forum. - General - MQL5 programming forum (2017)
 
I have deleted your other topic.
 

Hi William, Keith,

Noted on the double post.

Thanks for the removing of it.

By any chance would you know where the issue lies in?

Thank you.

Regards,

John

 

If an error occurs. Is there a compilation error? If yes, what compilation error does your IDE print? If no, the indicator is not working the way you want it to. So, to get an answer, you need to explain what exactly is not working.

Apart from that, it is always recommended to print output in case of errors. E.g. >> if (first_operation_was_successful) Print("Step 1 successful. Value:", calculatedValue) << And then you can look at the output and see where the error occurs, look in the associated code and discover and fix the error there.

 
  1. You have your buffers (that default to as-series), the OHLCV arrays (that default to non-series), and your loop (non-series).

    1. Arrays must be manually sized. They have no direction. You must move elements if you want a stack/as-series (set non-series, enlarge the array, set as-series).

    2. Buffers are automatically size, are as-series, and elements are moved for you, new elements are set to EMPTY_VALUE (or your designated. They can also draw on the chart automatically.

    3. In MT4, buffers and the predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.

      To determine the indexing direction of time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[], call ArrayGetAsSeries(). In order not to depend on default values, you should unconditionally call the ArraySetAsSeries() function for those arrays, which are expected to work with.
                Event Handling Functions - Functions - Language Basics - MQL4 Reference

    4. In MT5, you must set the direction.

      To define the indexing direction in the time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call the ArrayGetAsSeries() function. In order not to depend on defaults, call the ArraySetAsSeries() function for the arrays to work with.
                Event Handling / OnCalculate - Reference on algorithmic/automated trading language for MetaTrader 5
  2. See How to do your lookbacks correctly #9#14 & #19. (2016)