Trying to port MQL4 indicator into MQL5 but getting nothing but a blank window.

 

I wanted to port Kase Peak Oscillator indicator from mt4 to mt5 because couldn't find it by googling. I am new to mql that is why I don't know much about it but I have a little experience with coding. Below I've provided a code which I modified from mql4 using this guide https://www.mql5.com/en/articles/81. Calculation part is unchanged from the original apart from corrected functions and variables that were missing in mql5, but after I put it into the chart there is no data, it is just a blank window under main chart and I can't seem to understand where I have messed up. Please can you help me find my mistake?

//+------------------------------------------------------------------+
//|                                                    kase peak.mq4 |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"
#property version   "1.00"
#property description "Kase Peak Oscillator"
#property indicator_separate_window
#property indicator_buffers  5
#property indicator_plots 5

//---plot KP Histogram
#property indicator_label1 "KPH"
#property indicator_type1    DRAW_HISTOGRAM
#property indicator_color1   clrDimGray
#property indicator_style1   STYLE_SOLID
#property indicator_width1   2 
//---plot KP Oscillator
#property indicator_label2 "KPO"
#property indicator_type2    DRAW_NONE
#property indicator_color2   clrDimGray

//---plot KP d
#property indicator_label3 "KPD"
#property indicator_type3    DRAW_LINE
#property indicator_color3   clrMagenta
#property indicator_style3   STYLE_SOLID
#property indicator_width3   2

//---plot KPM
#property indicator_label4 "KPM"
#property indicator_type4    DRAW_LINE
#property indicator_color4   clrDeepSkyBlue
#property indicator_style4   STYLE_SOLID
#property indicator_width4   2


//---plot KPP Histogram last value
#property indicator_label5   "KPP"
#property indicator_type5    DRAW_HISTOGRAM
#property indicator_color5   clrMagenta
#property indicator_style5   STYLE_SOLID
#property indicator_width5   2 


#property indicator_level1   0
#property indicator_levelcolor clrDimGray 
//
//
//
//

input double kpoDeviations  = 2.0;
input int    kpoShortCycle  = 8;
input int    kpoLongCycle   = 65;
input double kpoSensitivity = 40; 
input bool   allPeaksMode   = false;

//
//
//
//
//

double kphBuffer[];
double kpoBuffer[];
double kpdBuffer[];
double kpmBuffer[];
double kppBuffer[];
double wrkBuffer[][6];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int OnInit()
{
   SetIndexBuffer(0,kphBuffer,INDICATOR_DATA);// SetIndexStyleMQL4(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,kpoBuffer,INDICATOR_DATA); //PlotIndexSetString(1,PLOT_LABEL, NULL);
   SetIndexBuffer(2,kpdBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,kpmBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,kppBuffer,INDICATOR_DATA); //SetIndexStyleMQL4(4,DRAW_HISTOGRAM);
   
   IndicatorSetString(INDICATOR_SHORTNAME,"Kase peak oscillator ("+DoubleToString(kpoDeviations,2)+","+kpoShortCycle+","+kpoLongCycle+","+DoubleToString(kpoSensitivity,2)+")");   
   
   PlotIndexSetString(0,PLOT_LABEL,"KPH");
   PlotIndexSetString(1,PLOT_LABEL,"KPD");
   PlotIndexSetString(3,PLOT_LABEL,"KPM");
   PlotIndexSetString(4,PLOT_LABEL,"KPP");
   
   //ArrayResize(kphBuffer,Bars(_Symbol,PERIOD_CURRENT));
  //ArrayResize(kpoBuffer,Bars(_Symbol,PERIOD_CURRENT));
  // ArrayResize(kpdBuffer,Bars(_Symbol,PERIOD_CURRENT));
  // ArrayResize(kpmBuffer,Bars(_Symbol,PERIOD_CURRENT));
  // ArrayResize(kppBuffer,Bars(_Symbol,PERIOD_CURRENT));
   
  // ArraySetAsSeries(kphBuffer,true);
  // ArraySetAsSeries(kpoBuffer,true);
  // ArraySetAsSeries(kpdBuffer,true);
  // ArraySetAsSeries(kpmBuffer,true);
  // ArraySetAsSeries(kppBuffer,true);
   
   return(INIT_SUCCEEDED);
}





//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define ccLog 0
#define ccDev 1
#define x1    2
#define xs    3
#define xp    4
#define xpAbs 5

//
//
//
//
//

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[])
{
   //--- Установка массивов буферов как таймсерий
  // ArraySetAsSeries(high,true);
  // ArraySetAsSeries(low,true);
  // ArraySetAsSeries(tick_volume,true);
   
   int IndicatorCountedMQL4 = 0;
   if(prev_calculated>0) IndicatorCountedMQL4 = (prev_calculated-1);
   if(prev_calculated==0) IndicatorCountedMQL4 = 0;


   int counted_bars=IndicatorCountedMQL4;
   int myBars = Bars(_Symbol,PERIOD_CURRENT);
   int i,r,limit;
   
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = MathMin(myBars-counted_bars,myBars-kpoLongCycle);
         if (ArrayRange(wrkBuffer,0) != myBars) ArrayResize(wrkBuffer,myBars);
         
   //
   //
   //
   //
   //

   for(i=limit,r=myBars-i-1; i>=0; i--,r++)
   {
      wrkBuffer[r][x1]    = wrkBuffer[r-1][x1];
      wrkBuffer[r][xs]    = wrkBuffer[r-1][xs];
      wrkBuffer[r][ccLog] = MathLog(close[i]/close[i+1]);
      wrkBuffer[r][ccDev] = iDeviation(ccLog,9,r);

      //
      //
      //
      //
      //
      
      double avg = iSma(ccDev,30,r);
         if (avg>0)
         {
            double max1 = 0;
            double maxs = 0;
               for (int k=kpoShortCycle; k<kpoLongCycle; k++)
               {
                  max1 = MathMax(MathLog(high[i]/low[i+k])/MathSqrt(k),max1);
                  maxs = MathMax(MathLog(high[i+k]/low[i])/MathSqrt(k),maxs);
               }                  
            wrkBuffer[r][x1] = max1/avg;
            wrkBuffer[r][xs] = maxs/avg;
         }
         wrkBuffer[r][xp]    = kpoSensitivity*(iSma(x1,3,r)-iSma(xs,3,r));
         wrkBuffer[r][xpAbs] = MathAbs(wrkBuffer[r][xp]);

         //
         //
         //
         //
         //

         kppBuffer[i+1] = EMPTY_VALUE;      
         kpoBuffer[i]   = wrkBuffer[r][xp];
         kphBuffer[i]   = wrkBuffer[r][xp];

            double tmpVal = iSma(xpAbs,50,r)+kpoDeviations*(iDeviation(xpAbs,50,r));
            double maxVal = MathMax(90.0,tmpVal);
            double minVal = MathMin(90.0,tmpVal);
      
         if (kpoBuffer[i] > 0) { kpdBuffer[i] =  maxVal; kpmBuffer[i] =  minVal; }
         else                  { kpdBuffer[i] = -maxVal; kpmBuffer[i] = -minVal; }
      
      //
      //
      //
      //
      //

      if (!allPeaksMode)
      {         
         if (kpoBuffer[i+1]>0 && kpoBuffer[i+1]>kpoBuffer[i] && kpoBuffer[i+1]>=kpoBuffer[i+2] && kpoBuffer[i+1]>= maxVal) kppBuffer[i+1] = kpoBuffer[i+1];
         if (kpoBuffer[i+1]<0 && kpoBuffer[i+1]<kpoBuffer[i] && kpoBuffer[i+1]<=kpoBuffer[i+2] && kpoBuffer[i+1]<=-maxVal) kppBuffer[i+1] = kpoBuffer[i+1];
      }
      else
      {
         if (kpoBuffer[i+1]>0 && kpoBuffer[i+1]>kpoBuffer[i] && kpoBuffer[i+1]>=kpoBuffer[i+2]) kppBuffer[i+1] = kpoBuffer[i+1];
         if (kpoBuffer[i+1]<0 && kpoBuffer[i+1]<kpoBuffer[i] && kpoBuffer[i+1]<=kpoBuffer[i+2]) kppBuffer[i+1] = kpoBuffer[i+1];
      }         
   }
   return(0);
}



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double iDeviation(int forDim, int period, int pos)
{
   double dMA  = iSma(forDim,period,pos);
   double dSum = 0;
      for(int i=0; i<period; i++,pos--) dSum += (wrkBuffer[pos][forDim]-dMA)*(wrkBuffer[pos][forDim]-dMA);
   return(MathSqrt(dSum/period));
}

//
//
//
//
//

double iSma(int forDim, int period, int pos)
{
   double sum = wrkBuffer[pos][forDim];
      for(int i=1; i<period; i++) sum += wrkBuffer[pos-i][forDim];
   return(sum/period);
}
Migrating from MQL4 to MQL5
Migrating from MQL4 to MQL5
  • www.mql5.com
This article is a quick guide to MQL4 language functions, it will help you to migrate your programs from MQL4 to MQL5. For each MQL4 function (except trading functions) the description and MQL5 implementation are presented, it allows you to reduce the conversion time significantly. For convenience, the MQL4 functions are divided into groups, similar to MQL4 Reference.
 

In MT5 you can manage buffers for data storage and calculations (as well as plotting), it isn't a necessity to use multidimensional arrays to log the calculations

You'll rather use functions with a signature like this:

double iDeviation(double closePrice, double &data[], int period, int pos){

}


double iSma(double closePrice, double &data[], int period, int pos){

}

I can help more tomorrow maybe

 
Conor Mcnamara #:

In MT5 you can manage buffers for data storage and calculations (as well as plotting), it isn't a necessity to use multidimensional arrays to log the calculations

You'll rather use functions with a signature like this:

I can help more tomorrow maybe

The multidimentional array is what was used in the mt4 original indicator that I could find and I leaved it at that because I wasn't confident in my understanding what it was meant to do. I didn't change anything regarding the calculation.  

 
suvroc #:

The multidimentional array is what was used in the mt4 original indicator that I could find and I leaved it at that because I wasn't confident in my understanding what it was meant to do. I didn't change anything regarding the calculation.  

Yes but mql4 is a different architecture to mql5, and what you might have in the start() function of a mql4 indicator cannot be "copy-paste" 1:1 to mql5. Mql5 has a different approach to process data...buffer handling is different for plotting the data.

 
Conor Mcnamara #:

Yes but mql4 is a different architecture to mql5, and what you might have in the start() function of a mql4 indicator cannot be "copy-paste" 1:1 to mql5. Mql5 has a different approach to process data...buffer handling is different for plotting the data.

I understand it , but apart from the multi dimentional array I can't find any problem there, I tried to change the buffer handling part in the provided code if I understood you correctly .

 
suvroc #:

I understand it , but apart from the multi dimentional array I can't find any problem there, I tried to change the buffer handling part in the provided code if I understood you correctly .

You have the properties and OnInit setup correctly, but I had to make 3 new calculation buffers to make this work in MT5. I can show what I did later

 
Conor Mcnamara #:

You have the properties and OnInit setup correctly, but I had to make 3 new calculation buffers to make this work in MT5. I can show what I did later

Thank you, I will be waiting for you to show me.

 
suvroc #:I understand it , but apart from the multi dimentional array I can't find any problem there, I tried to change the buffer handling part in the provided code if I understood you correctly .

Please note that in MQL4, the time-series data in the OnCalculate parameters are treated as a series by default, but in MQL5 they are treated as normal arrays by default.

You will have to reverse the loop sequence or force the parameter arrays to be treated as a series.

 
here is my conversion for mql5. I don't often convert mql4 scripts as that's not what I do. I simply hope it's educational in regard to mql5 indicator scripting
Files:
Kase_peak.mq5  14 kb
 

here's an attempt to make things work while maintaining the multi-dim arrays... it plots things, not sure how the original mt4 indicator plot looked exactly...eitherway there's an exception occurring that I couldn't seem to resolve no matter what I tried

I'm aware of how to tackle the array out of range exception, although this time it's lost on me

Files:
Kase_peak2.mq5  16 kb
 
Conor Mcnamara #:

here's an attempt to make things work while maintaining the multi-dim arrays... it plots things, not sure how the original mt4 indicator plot looked exactly...eitherway there's an exception occurring that I couldn't seem to resolve no matter what I tried

I'm aware of how to tackle the array out of range exception, although this time it's lost on me

Thank you for your effort, I really appreciate it. I will look into your code and see what can I learn from it. But it seems that your code plot is different output than what the original mt4 does.

Mt4 chart : 

MetaTrader Trading Platform Screenshots

EURUSD.i, D1, 2023.10.07

EightCap Global Ltd, MetaTrader 4, Demo

EURUSD.i, D1, 2023.10.07, EightCap Global Ltd, MetaTrader 4, Demo


your code chart : 


Original mt4 code :


//+------------------------------------------------------------------+
//|                                                    kase peak.mq4 |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers  5
#property indicator_color1   DimGray
#property indicator_color2   DimGray
#property indicator_color3   Magenta
#property indicator_color4   DeepSkyBlue
#property indicator_color5   Magenta
#property indicator_width3   2
#property indicator_width4   2
#property indicator_width5   2
#property indicator_level1   0
#property indicator_levelcolor DimGray 

//
//
//
//
//

extern double kpoDeviations  = 2.0;
extern int    kpoShortCycle  = 8;
extern int    kpoLongCycle   = 65;
extern double kpoSensitivity = 40; 
extern bool   allPeaksMode   = false;

//
//
//
//
//

double kphBuffer[];
double kpoBuffer[];
double kpdBuffer[];
double kpmBuffer[];
double kppBuffer[];
double wrkBuffer[][6];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,kphBuffer); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,kpoBuffer); SetIndexLabel(1,NULL);
   SetIndexBuffer(2,kpdBuffer);
   SetIndexBuffer(3,kpmBuffer);
   SetIndexBuffer(4,kppBuffer); SetIndexStyle(4,DRAW_HISTOGRAM);
   
   IndicatorShortName("Kase peak oscillator ("+DoubleToStr(kpoDeviations,2)+","+kpoShortCycle+","+kpoLongCycle+","+DoubleToStr(kpoSensitivity,2)+")");   
   return(0);
}
int deinit() { return(0); }




//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define ccLog 0
#define ccDev 1
#define x1    2
#define xs    3
#define xp    4
#define xpAbs 5

//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,r,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = MathMin(Bars-counted_bars,Bars-kpoLongCycle);
         if (ArrayRange(wrkBuffer,0) != Bars) ArrayResize(wrkBuffer,Bars);
         
   //
   //
   //
   //
   //

   for(i=limit,r=Bars-i-1; i>=0; i--,r++)
   {
      wrkBuffer[r][x1]    = wrkBuffer[r-1][x1];
      wrkBuffer[r][xs]    = wrkBuffer[r-1][xs];
      wrkBuffer[r][ccLog] = MathLog(Close[i]/Close[i+1]);
      wrkBuffer[r][ccDev] = iDeviation(ccLog,9,r);

      //
      //
      //
      //
      //
      
      double avg = iSma(ccDev,30,r);
         if (avg>0)
         {
            double max1 = 0;
            double maxs = 0;
               for (int k=kpoShortCycle; k<kpoLongCycle; k++)
               {
                  max1 = MathMax(MathLog(High[i]/Low[i+k])/MathSqrt(k),max1);
                  maxs = MathMax(MathLog(High[i+k]/Low[i])/MathSqrt(k),maxs);
               }                  
            wrkBuffer[r][x1] = max1/avg;
            wrkBuffer[r][xs] = maxs/avg;
         }
         wrkBuffer[r][xp]    = kpoSensitivity*(iSma(x1,3,r)-iSma(xs,3,r));
         wrkBuffer[r][xpAbs] = MathAbs(wrkBuffer[r][xp]);

         //
         //
         //
         //
         //

         kppBuffer[i+1] = EMPTY_VALUE;      
         kpoBuffer[i]   = wrkBuffer[r][xp];
         kphBuffer[i]   = wrkBuffer[r][xp];

            double tmpVal = iSma(xpAbs,50,r)+kpoDeviations*(iDeviation(xpAbs,50,r));
            double maxVal = MathMax(90.0,tmpVal);
            double minVal = MathMin(90.0,tmpVal);
      
         if (kpoBuffer[i] > 0) { kpdBuffer[i] =  maxVal; kpmBuffer[i] =  minVal; }
         else                  { kpdBuffer[i] = -maxVal; kpmBuffer[i] = -minVal; }
      
      //
      //
      //
      //
      //

      if (!allPeaksMode)
      {         
         if (kpoBuffer[i+1]>0 && kpoBuffer[i+1]>kpoBuffer[i] && kpoBuffer[i+1]>=kpoBuffer[i+2] && kpoBuffer[i+1]>= maxVal) kppBuffer[i+1] = kpoBuffer[i+1];
         if (kpoBuffer[i+1]<0 && kpoBuffer[i+1]<kpoBuffer[i] && kpoBuffer[i+1]<=kpoBuffer[i+2] && kpoBuffer[i+1]<=-maxVal) kppBuffer[i+1] = kpoBuffer[i+1];
      }
      else
      {
         if (kpoBuffer[i+1]>0 && kpoBuffer[i+1]>kpoBuffer[i] && kpoBuffer[i+1]>=kpoBuffer[i+2]) kppBuffer[i+1] = kpoBuffer[i+1];
         if (kpoBuffer[i+1]<0 && kpoBuffer[i+1]<kpoBuffer[i] && kpoBuffer[i+1]<=kpoBuffer[i+2]) kppBuffer[i+1] = kpoBuffer[i+1];
      }         
   }
   return(0);
}



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double iDeviation(int forDim, int period, int pos)
{
   double dMA  = iSma(forDim,period,pos);
   double dSum = 0;
      for(int i=0; i<period; i++,pos--) dSum += (wrkBuffer[pos][forDim]-dMA)*(wrkBuffer[pos][forDim]-dMA);
   return(MathSqrt(dSum/period));
}

//
//
//
//
//

double iSma(int forDim, int period, int pos)
{
   double sum = wrkBuffer[pos][forDim];
      for(int i=1; i<period; i++) sum += wrkBuffer[pos-i][forDim];
   return(sum/period);
}