convert MQL4 into MQL5 indicator

 
Hey there,

I want to convert this indicator into mql5.

It´s really difficult written and i don´t know what possibly could be wrong. It draws the lines, but when i am going to compare it with the mql4 version, i can see differences between the plots.

Is there anyone who could help me further?

Here is the mql5 file:

//+------------------------------------------------------------------+
//|                                                           mladen | 
//+------------------------------------------------------------------+
#property link      "www.forex-tsd.com"
#property copyright "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrSandyBrown
#property indicator_width1  2
#property indicator_width2  2
#property strict

//
//
//
//
//

enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased   // Heiken ashi trend biased price
};
extern int      CalcPeriod = 20;       // Calculation period
extern enPrices Price      = pr_close; // Price 
extern double   Q1         = 0.8;      // K for entries
extern double   Q2         = 0.4;      // K for exits

//
//
//
//
//

double quot1[];
double quot2[],hp[],peak[],prices[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,quot1);
   SetIndexBuffer(1,quot2);
   SetIndexBuffer(2,hp);
   SetIndexBuffer(3,prices);
   SetIndexBuffer(4,peak);
   return(0); 
}
int deinit(){ return(0); }


//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

#define Pi 3.14159265358979323846264338327950288
int start()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1);
         
   //
   //
   //
   //
   //
    
      double angle = 0.707 * 2.0 * Pi /100;
      double alpha = (cos(angle)+sin(angle)-1.0)/cos(angle);
      for(int i=limit; i>=0; i--)
      {
         prices[i] = getPrice(Price,Open,Close,High,Low,i); 
         if (i>=Bars-2) 
         { 
            hp[i]   = prices[i]; 
            peak[i] = prices[i]; 
            continue; 
         }
         
         //
         //
         //
         //
         //
         
         hp[i]   = (1-alpha/2.0)*(1-alpha/2.0)*(prices[i]-2.0*prices[i+1]+prices[i+2]) + 2.0*(1-alpha)*hp[i+1] - (1-alpha)*(1-alpha)*hp[i+2];         
         peak[i] = 0.991*peak[i+1];
            double hps  = iSsm(hp[i],CalcPeriod,i);
                  if (MathAbs(hps)>peak[i]) peak[i] = MathAbs(hps);
            double x = 0; if (peak[i] != 0) x=hps/peak[i];
            
            //
            //
            //
            //
            //
            
            quot1[i] = (x+Q1)/(Q1*x+1.0);               
            quot2[i] = (x+Q2)/(Q2*x+1.0);               
      }       
      return(0);
}


//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

//
//
//
//
//

double workSsm[][2];
#define _tprice  0
#define _ssm     1

double workSsmCoeffs[][4];
#define _speriod 0
#define _sc1    1
#define _sc2    2
#define _sc3    3

double iSsm(double price, double period, int i, int instanceNo=0)
{
   if (period<=1) return(price);
   if (ArrayRange(workSsm,0) !=Bars)                 ArrayResize(workSsm,Bars);
   if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1);
   if (workSsmCoeffs[instanceNo][_speriod] != period)
   {
      workSsmCoeffs[instanceNo][_speriod] = period;
      double a1 = MathExp(-1.414*Pi/period);
      double b1 = 2.0*a1*MathCos(1.414*Pi/period);
         workSsmCoeffs[instanceNo][_sc2] = b1;
         workSsmCoeffs[instanceNo][_sc3] = -a1*a1;
         workSsmCoeffs[instanceNo][_sc1] = 1.0 - workSsmCoeffs[instanceNo][_sc2] - workSsmCoeffs[instanceNo][_sc3];
   }

   //
   //
   //
   //
   //

      int s = instanceNo*2;  i = Bars-i-1;
      workSsm[i][s+_ssm]    = price;
      workSsm[i][s+_tprice] = price;
      if (i>1)
      {  
          workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_sc1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + 
                               workSsmCoeffs[instanceNo][_sc2]*workSsm[i-1][s+_ssm]                                + 
                               workSsmCoeffs[instanceNo][_sc3]*workSsm[i-2][s+_ssm]; }
   return(workSsm[i][s+_ssm]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances*4];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= Bars) ArrayResize(workHa,Bars); instanceNo*=4;
         int r = Bars-i-1;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (r>0)
                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 
         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 
                                workHa[r][instanceNo+2] = haOpen;
                                workHa[r][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
   }
   return(0);
}   



and here the mql5 code:


#property link      "www.forex-tsd.com"
#property copyright "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrSandyBrown
#property indicator_width1  2
#property indicator_width2  2
#property indicator_plots 2
#property strict
#define Pi 3.14159265358979323846264338327950288
#property indicator_style1 STYLE_SOLID
#property indicator_type1 DRAW_LINE
#property indicator_label1 "Quotient1"

#property indicator_style2 STYLE_SOLID
#property indicator_type2 DRAW_LINE
#property indicator_label2 "Quotient2"




double workSsm[][2];
#define _tprice  0
#define _ssm     1

double workSsmCoeffs[][4];
#define _speriod 0
#define _sc1    1
#define _sc2    2
#define _sc3    3


enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased   // Heiken ashi trend biased price
};

input int      CalcPeriod = 20;       // Calculation period
input enPrices Price      = pr_close; // Price 
input double   Q1         = 0.8;      // K for entries
input double   Q2         = 0.4;      // K for exits


double quot1[];
double quot2[],hp[],peak[],prices[];


int OnInit()
  {

   SetIndexBuffer(0,quot1);
   SetIndexBuffer(1,quot2);
   SetIndexBuffer(2,hp);
   SetIndexBuffer(3,prices);
   SetIndexBuffer(4,peak);
   
 
   

   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[])
  {
int counted_bars=IndicatorCountedMQL4(prev_calculated);
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars(_Symbol,PERIOD_CURRENT)-counted_bars,Bars(_Symbol,PERIOD_CURRENT)-1);
         
   //
   //
   //
   //
   //
    
      double angle = 0.707 * 2.0 * Pi /100;
      double alpha = (cos(angle)+sin(angle)-1.0)/cos(angle);
      for(int i=limit; i>=0; i--)
      {
         prices[i] = getPrice(Price,open,close,high,low,i); 
         if (i>=Bars(_Symbol,PERIOD_CURRENT)-2) 
         { 
            hp[i]   = prices[i]; 
            peak[i] = prices[i]; 
            continue; 
         }
         
         //
         //
         //
         //
         //
         
         hp[i]   = (1-alpha/2.0)*(1-alpha/2.0)*(prices[i]-2.0*prices[i+1]+prices[i+2]) + 2.0*(1-alpha)*hp[i+1] - (1-alpha)*(1-alpha)*hp[i+2];         
         peak[i] = 0.991*peak[i+1];
            double hps  = iSsm(hp[i],CalcPeriod,i);
                  if (MathAbs(hps)>peak[i]) peak[i] = MathAbs(hps);
            double x = 0; if (peak[i] != 0) x=hps/peak[i];
            
            //
            //
            //
            //
            //
            
            quot1[i] = (x+Q1)/(Q1*x+1.0);               
            quot2[i] = (x+Q2)/(Q2*x+1.0);               
      }       
     ;
      
   return(rates_total);
  }




double iSsm(double price, double period, int i, int instanceNo=0)
{
   if (period<=1) return(price);
   if (ArrayRange(workSsm,0) !=Bars(_Symbol,PERIOD_CURRENT))                 ArrayResize(workSsm,Bars(_Symbol,PERIOD_CURRENT));
   if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1);
   if (workSsmCoeffs[instanceNo][_speriod] != period)
   {
      workSsmCoeffs[instanceNo][_speriod] = period;
      double a1 = MathExp(-1.414*Pi/period);
      double b1 = 2.0*a1*MathCos(1.414*Pi/period);
         workSsmCoeffs[instanceNo][_sc2] = b1;
         workSsmCoeffs[instanceNo][_sc3] = -a1*a1;
         workSsmCoeffs[instanceNo][_sc1] = 1.0 - workSsmCoeffs[instanceNo][_sc2] - workSsmCoeffs[instanceNo][_sc3];
   }

   //
   //
   //
   //
   //

      int s = instanceNo*2;  i = Bars(_Symbol,PERIOD_CURRENT)-i-1;
      workSsm[i][s+_ssm]    = price;
      workSsm[i][s+_tprice] = price;
      if (i>1)
      {  
          workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_sc1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + 
                               workSsmCoeffs[instanceNo][_sc2]*workSsm[i-1][s+_ssm]                                + 
                               workSsmCoeffs[instanceNo][_sc3]*workSsm[i-2][s+_ssm]; }
   return(workSsm[i][s+_ssm]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances*4];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= Bars(_Symbol,PERIOD_CURRENT)) ArrayResize(workHa,Bars(_Symbol,PERIOD_CURRENT)); instanceNo*=4;
         int r = Bars(_Symbol,PERIOD_CURRENT)-i-1;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (r>0)
                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 
         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 
                                workHa[r][instanceNo+2] = haOpen;
                                workHa[r][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
   }
   return(0);
}   


int IndicatorCountedMQL4(int prev_calculated)
  {
   if(prev_calculated>0) return(prev_calculated-1);
   if(prev_calculated==0) return(0);
   return(0);
  }


Thanks for your help!

 

There are quite a few subtle difference between how MQL5 and MQL4 handle data.

I did not take a hard look at your code, and only skimmed it, but the first thing I noticed in your code, is that in your MQL5 code you are still treating the buffers and data arrays as "series" (current data is at index [0]), like how MQL4 does it, but in MQL5 they are treated ad normal arrays (current data is at the end [last]).

Either change the ordering of how you process the data, or simply use the "ArraySetAsSeries()" function to set all the buffer and data arrays so they are treated as "series", like in MQL4.

Fix that first, then come back with whatever other difficulties you face!

Documentation on MQL5: Array Functions / ArraySetAsSeries
Documentation on MQL5: Array Functions / ArraySetAsSeries
  • www.mql5.com
ArraySetAsSeries - Array Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Thanks for your response. Meanwhile i found exactly the same issue. I´ve solved it with the arraysetasseries() function.

The corrected Code is below. The results are better, but nevertheless not the same. By the way, the Indicator is called "qoutient transformation"


#property link      "www.forex-tsd.com"
#property copyright "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrSandyBrown
#property indicator_width1  2
#property indicator_width2  2
#property indicator_plots 2
#property strict
#define Pi 3.14159265358979323846264338327950288
#property indicator_style1 STYLE_SOLID
#property indicator_type1 DRAW_LINE
#property indicator_label1 "Quotient1"

#property indicator_style2 STYLE_SOLID
#property indicator_type2 DRAW_LINE
#property indicator_label2 "Quotient2"




double workSsm[][2];
#define _tprice  0
#define _ssm     1

double workSsmCoeffs[][4];
#define _speriod 0
#define _sc1    1
#define _sc2    2
#define _sc3    3


enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased   // Heiken ashi trend biased price
};

input int      CalcPeriod = 20;       // Calculation period
input enPrices Price      = pr_close; // Price 
input double   Q1         = 0.8;      // K for entries
input double   Q2         = 0.4;      // K for exits


double quot1[];
double quot2[],hp[],peak[],prices[];


int OnInit()
  {

   SetIndexBuffer(0,quot1);
   SetIndexBuffer(1,quot2);
   SetIndexBuffer(2,hp);
   SetIndexBuffer(3,prices);
   SetIndexBuffer(4,peak);
   ArraySetAsSeries(quot1,true);
   ArraySetAsSeries(quot2,true);
   ArraySetAsSeries(hp,true);
   ArraySetAsSeries(prices,true);
   ArraySetAsSeries(peak,true);

   

   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[])
  {
int counted_bars=IndicatorCountedMQL4(prev_calculated);
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars(_Symbol,PERIOD_CURRENT)-counted_bars,Bars(_Symbol,PERIOD_CURRENT)-1);
         
   //
   //
   //
   //
   //
    
      double angle = 0.707 * 2.0 * Pi /100;
      double alpha = (cos(angle)+sin(angle)-1.0)/cos(angle);
      for(int i=limit; i>=0; i--)
      {
         prices[i] = getPrice(Price,open,close,high,low,i); 
         if (i>=Bars(_Symbol,PERIOD_CURRENT)-2) 
         { 
            hp[i]   = prices[i]; 
            peak[i] = prices[i]; 
            continue; 
         }
         
         //
         //
         //
         //
         //
         
         hp[i]   = (1-alpha/2.0)*(1-alpha/2.0)*(prices[i]-2.0*prices[i+1]+prices[i+2]) + 2.0*(1-alpha)*hp[i+1] - (1-alpha)*(1-alpha)*hp[i+2];         
         peak[i] = 0.991*peak[i+1];
            double hps  = iSsm(hp[i],CalcPeriod,i);
                  if (MathAbs(hps)>peak[i]) peak[i] = MathAbs(hps);
            double x = 0; if (peak[i] != 0) x=hps/peak[i];
            
            //
            //
            //
            //
            //
            
            quot1[i] = (x+Q1)/(Q1*x+1.0);               
            quot2[i] = (x+Q2)/(Q2*x+1.0);               
      }       
     ;
      
   return(rates_total);
  }




double iSsm(double price, double period, int i, int instanceNo=0)
{
   if (period<=1) return(price);
   if (ArrayRange(workSsm,0) !=Bars(_Symbol,PERIOD_CURRENT))                 ArrayResize(workSsm,Bars(_Symbol,PERIOD_CURRENT));
   if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1);
   if (workSsmCoeffs[instanceNo][_speriod] != period)
   {
      workSsmCoeffs[instanceNo][_speriod] = period;
      double a1 = MathExp(-1.414*Pi/period);
      double b1 = 2.0*a1*MathCos(1.414*Pi/period);
         workSsmCoeffs[instanceNo][_sc2] = b1;
         workSsmCoeffs[instanceNo][_sc3] = -a1*a1;
         workSsmCoeffs[instanceNo][_sc1] = 1.0 - workSsmCoeffs[instanceNo][_sc2] - workSsmCoeffs[instanceNo][_sc3];
   }

   //
   //
   //
   //
   //

      int s = instanceNo*2;  i = Bars(_Symbol,PERIOD_CURRENT)-i-1;
      workSsm[i][s+_ssm]    = price;
      workSsm[i][s+_tprice] = price;
      if (i>1)
      {  
          workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_sc1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + 
                               workSsmCoeffs[instanceNo][_sc2]*workSsm[i-1][s+_ssm]                                + 
                               workSsmCoeffs[instanceNo][_sc3]*workSsm[i-2][s+_ssm]; }
   return(workSsm[i][s+_ssm]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances*4];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= Bars(_Symbol,PERIOD_CURRENT)) ArrayResize(workHa,Bars(_Symbol,PERIOD_CURRENT)); instanceNo*=4;
         int r = Bars(_Symbol,PERIOD_CURRENT)-i-1;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (r>0)
                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 
         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 
                                workHa[r][instanceNo+2] = haOpen;
                                workHa[r][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
   }
   return(0);
}   


int IndicatorCountedMQL4(int prev_calculated)
  {
   if(prev_calculated>0) return(prev_calculated-1);
   if(prev_calculated==0) return(0);
   return(0);
  }
 
Claudius Marius Walter: Thanks for your response. Meanwhile i found exactly the same issue. I´ve solved it with the arraysetasseries() function. The corrected Code is below. The results are better, but nevertheless not the same. By the way, the Indicator is called "qoutient transformation"

You also have to the e "ArraySetAsSeries()" for the data arrays at the beginning of the OnCalculate() function:

// Set Arrays as Series (example)
ArraySetAsSeries( time,        true );
ArraySetAsSeries( open,        true );
ArraySetAsSeries( high,        true );
ArraySetAsSeries( low,         true );
ArraySetAsSeries( close,       true );
ArraySetAsSeries( tick_volume, true );

Also, don't use the "Bars(_Symbol,PERIOD_CURRENT)", use the "rates_total" returned by the OnCalculate() function.

EDIT: and pass down the "rates_total" value to sub functions called so that they don't use "Bars()" either.

Documentation on MQL5: Array Functions / ArraySetAsSeries
Documentation on MQL5: Array Functions / ArraySetAsSeries
  • www.mql5.com
ArraySetAsSeries - Array Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Fernando Carreiro:

You also have to the e "ArraySetAsSeries()" for the data arrays at the beginning of the OnCalculate() function:

Also, don't use the "Bars(_Symbol,PERIOD_CURRENT)", use the "rates_total" returned by the OnCalculate() function.

EDIT: and pass down the "rates_total" value to sub functions called so that they don't use "Bars()" either.

This helped me a lot! Thank you fernandes!

I have  all OnCalculate() parameters SetAsSeries. The Indicator seems to work after this little changing and I am very happy now.
Now i also understand, what rates_total mean..

Here is the code and by the way. it´s a very good trend Indicator:

#property link      "www.forex-tsd.com"
#property copyright "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrSandyBrown
#property indicator_width1  2
#property indicator_width2  2
#property indicator_plots 2
#property strict
#define Pi 3.14159265358979323846264338327950288
#property indicator_style1 STYLE_SOLID
#property indicator_type1 DRAW_LINE
#property indicator_label1 "Quotient1"

#property indicator_style2 STYLE_SOLID
#property indicator_type2 DRAW_LINE
#property indicator_label2 "Quotient2"




double workSsm[][2];
#define _tprice  0
#define _ssm     1

double workSsmCoeffs[][4];
#define _speriod 0
#define _sc1    1
#define _sc2    2
#define _sc3    3


enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased   // Heiken ashi trend biased price
};

input int      CalcPeriod = 20;       // Calculation period
input enPrices Price      = pr_close; // Price 
input double   Q1         = 0.8;      // K for entries
input double   Q2         = 0.4;      // K for exits


double quot1[];
double quot2[],hp[],peak[],prices[];


int OnInit()
  {

   SetIndexBuffer(0,quot1);
   SetIndexBuffer(1,quot2);
   SetIndexBuffer(2,hp);
   SetIndexBuffer(3,prices);
   SetIndexBuffer(4,peak);
   ArraySetAsSeries(quot1,true);
   ArraySetAsSeries(quot2,true);
   ArraySetAsSeries(hp,true);
   ArraySetAsSeries(prices,true);
   ArraySetAsSeries(peak,true);

   

   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[])
  {
  
      ArraySetAsSeries( time,        true );
      ArraySetAsSeries( open,        true );
      ArraySetAsSeries( high,        true );
      ArraySetAsSeries( low,         true );
      ArraySetAsSeries( close,       true );
      ArraySetAsSeries( tick_volume, true );


int counted_bars=IndicatorCountedMQL4(prev_calculated);
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(rates_total-counted_bars,rates_total-1);
         
   //
   //
   //
   //
   //
    
      double angle = 0.707 * 2.0 * Pi /100;
      double alpha = (cos(angle)+sin(angle)-1.0)/cos(angle);
      for(int i=limit; i>=0; i--)
      {
         prices[i] = getPrice(rates_total,Price,open,close,high,low,i); 
         if (i>=rates_total-2) 
         { 
            hp[i]   = prices[i]; 
            peak[i] = prices[i]; 
            continue; 
         }
         
         //
         //
         //
         //
         //
         
         hp[i]   = (1-alpha/2.0)*(1-alpha/2.0)*(prices[i]-2.0*prices[i+1]+prices[i+2]) + 2.0*(1-alpha)*hp[i+1] - (1-alpha)*(1-alpha)*hp[i+2];         
         peak[i] = 0.991*peak[i+1];
            double hps  = iSsm(rates_total,hp[i],CalcPeriod,i);
                  if (MathAbs(hps)>peak[i]) peak[i] = MathAbs(hps);
            double x = 0; if (peak[i] != 0) x=hps/peak[i];
            
            //
            //
            //
            //
            //
            
            quot1[i] = (x+Q1)/(Q1*x+1.0);               
            quot2[i] = (x+Q2)/(Q2*x+1.0);               
      }       
     ;
      
   return(rates_total);
  }




double iSsm(int rates_total, double price, double period, int i, int instanceNo=0)
{
   if (period<=1) return(price);
   if (ArrayRange(workSsm,0) !=Bars(_Symbol,PERIOD_CURRENT))                 ArrayResize(workSsm,Bars(_Symbol,PERIOD_CURRENT));
   if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1);
   if (workSsmCoeffs[instanceNo][_speriod] != period)
   {
      workSsmCoeffs[instanceNo][_speriod] = period;
      double a1 = MathExp(-1.414*Pi/period);
      double b1 = 2.0*a1*MathCos(1.414*Pi/period);
         workSsmCoeffs[instanceNo][_sc2] = b1;
         workSsmCoeffs[instanceNo][_sc3] = -a1*a1;
         workSsmCoeffs[instanceNo][_sc1] = 1.0 - workSsmCoeffs[instanceNo][_sc2] - workSsmCoeffs[instanceNo][_sc3];
   }

   //
   //
   //
   //
   //

      int s = instanceNo*2;  i = rates_total-i-1;
      workSsm[i][s+_ssm]    = price;
      workSsm[i][s+_tprice] = price;
      if (i>1)
      {  
          workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_sc1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + 
                               workSsmCoeffs[instanceNo][_sc2]*workSsm[i-1][s+_ssm]                                + 
                               workSsmCoeffs[instanceNo][_sc3]*workSsm[i-2][s+_ssm]; }
   return(workSsm[i][s+_ssm]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances*4];
double getPrice(int rates_total, int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= rates_total) ArrayResize(workHa,rates_total); instanceNo*=4;
         int r = rates_total-i-1;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (r>0)
                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 
         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 
                                workHa[r][instanceNo+2] = haOpen;
                                workHa[r][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
   }
   return(0);
}   


int IndicatorCountedMQL4(int prev_calculated)
  {
   if(prev_calculated>0) return(prev_calculated-1);
   if(prev_calculated==0) return(0);
   return(0);
  }
 

Please note that Ehler´s Quotient Transform, is used for Up-Trends and going Long or Buying. It is not designed for Down-Trends or going Short or Selling. It was invented mostly for stocks and other instruments which have a tendency to trend up.

Forex (and other similar instruments) are more bidirectional for which this indicator is not designed. You would have to reverse the logic in order to have an Indicator for working with Down-Trends, Shorting or Selling.

 

I don't think that it is a good idea to convert metatrader 4 indicator to metatrader 5 and trying to keep the metatrader 4 "way of working" (a lot of reasons not to do that)

So posted one "pure metatrader 5 version" here : https://www.mql5.com/en/forum/368391

Indicators: Ehlers Quotient Transform
Indicators: Ehlers Quotient Transform
  • 2021.05.01
  • www.mql5.com
Articles, Library comments: Indicators: Ehlers Quotient Transform
 
Mladen Rakic:

I don't think that it is a good idea to convert metatrader 4 indicator to metatrader 5 and trying to keep the metatrader 4 "way of working" (a lot of reasons not to do that)

So posted one "pure metatrader 5 version" here : https://www.mql5.com/en/forum/368391

Mladen the King! :D


Fernando Carreiro:

Please note that Ehler´s Quotient Transform, is used for Up-Trends and going Long or Buying. It is not designed for Down-Trends or going Short or Selling. It was invented mostly for stocks and other instruments which have a tendency to trend up.

Forex (and other similar instruments) are more bidirectional for which this indicator is not designed. You would have to reverse the logic in order to have an Indicator for working with Down-Trends, Shorting or Selling.

Yeah. I´ve read this in a Book, called "Trading Systems and Methods" from Perry Kaufman. It´s exactly as you said. it doesn´t work properly in the forex market. It´s better for Stocks or Crypto.

Nevertheless, thank you both!
Reason: