Failing to convert very simple indicator from MQL4 into MQL5

 

Hello everyone,


I have an extremely simple mq4 indicator that displays the upticks and downticks in the buffers for each candle. I am not competent with MQL5 and consequently have failed at converting the indicator into an MQ5 file. I would appreciate a clear explanation and solution as to what I am doing wrong.


Many thanks.



MQ4 Indicator code:


//+------------------------------------------------------------------+
//|                                          TicksSeparateVolume.mq4 |
//|                                           Copyright © MetaQuotes |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright @ MetaQuotes"
#property link      "http://www.metaquotes.net"
//-----
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_minimum 0


 // better to have no spaces or periods in file name
double UpTicks[];
double DownTicks[];
double dXecn = 1;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorShortName("TicksSeparateVolume("+Symbol()+")");
  
   SetIndexBuffer(0,UpTicks);
   SetIndexBuffer(1,DownTicks);
  
   SetIndexStyle(0,DRAW_NONE,0,3);
   SetIndexStyle(1,DRAW_NONE,0,2);
   
   SetIndexLabel(0,"UpTicks");
   SetIndexLabel(1,"DownTicks");
   
   if(Digits==3||Digits==5){
      dXecn=10;
   }
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
  
  Comment("");
  
  return(0);
  }
//+------------------------------------------------------------------+
//| Ticks Volume Indicator                                           |
//+------------------------------------------------------------------+
int start()
  {
  
   int i,counted_bars=IndicatorCounted();
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars;
   

//----
   for(i=0; i<limit; i++)
   {
      UpTicks[i]=(Volume[i]+(Close[i]-Open[i])/Point/dXecn)/2;
      DownTicks[i]=Volume[i]-UpTicks[i];
   }
  

//----
   return(0);
  }
//+------------------------------------------------------------------+



My failed MQL5 code:


//+------------------------------------------------------------------+
//|                                                  UpDownTicks.mq5 |
//|                                                        Max Pales |
//|                  https://www.fiverr.com/maxpales?up_rollout=true |
//+------------------------------------------------------------------+
#property copyright "Max Pales"
#property link      "https://www.fiverr.com/maxpales?up_rollout=true"
#property version   "1.00"
#property indicator_chart_window

#property indicator_buffers 2
#property indicator_plots   2

#property indicator_label1 "UpTicks"
#property indicator_type1 DRAW_NONE

#property indicator_label2 "DownTicks"
#property indicator_type2 DRAW_NONE


double UpTicks[];
double DownTicks[];
double dXecn = 1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,UpTicks,INDICATOR_DATA);
   SetIndexBuffer(1,DownTicks,INDICATOR_DATA);
   
   if(Digits()==3||Digits()==5){
      dXecn=10;
   }
   
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE); 
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE); 
//---
   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 bars = Bars(Symbol(),PERIOD_CURRENT);

      for(int i = prev_calculated;i<bars; i++)
      {
         UpTicks[i]=(iVolume(Symbol(),PERIOD_CURRENT,i)+(iClose(Symbol(),PERIOD_CURRENT,i)-iOpen(Symbol(),PERIOD_CURRENT,i)/Point()/dXecn)/2);
         DownTicks[i]=iVolume(Symbol(),PERIOD_CURRENT,i)-UpTicks[i];
      }
     

     
      return (rates_total-1);
  }
//+------------------------------------------------------------------+
 
RappNoyd:

Hello everyone,


I have an extremely simple mq4 indicator that displays the upticks and downticks in the buffers for each candle. I am not competent with MQL5 and consequently have failed at converting the indicator into an MQ5 file. I would appreciate a clear explanation and solution as to what I am doing wrong.


Many thanks.



MQ4 Indicator code:




My failed MQL5 code:


Here you go , i printed the buffers for debugging 

#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//--- plot upticks
#property indicator_label1  "upticks"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellowGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot downticks
#property indicator_label2  "downticks"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrFuchsia
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- indicator buffers
double         UpTicks[];
double         DownTicks[];
double dXecn = 1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,UpTicks,INDICATOR_DATA);
   SetIndexBuffer(1,DownTicks,INDICATOR_DATA);
   if(_Digits==3||_Digits==5){
      dXecn=10;
   }   
//---
   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 from=MathMax(0,prev_calculated-1);
  for(int i=from;i<rates_total;i++)
  {
  UpTicks[i]=(((double)tick_volume[i])+(close[i]-open[i])/_Point/dXecn)/2;
  DownTicks[i]=((double)tick_volume[i])-UpTicks[i];  
  }
//--- return value of prev_calculated for next call
  return(rates_total);
  }
//+------------------------------------------------------------------+
 
Lorentzos Roussos #:

Here you go , i printed the buffers for debugging 

Hey Lorentzos,


Thank you so much, it works perfectly. Forgive me for my stupid question but is variable 'from' the same as the lookback? Why do you subtract 1 from prev_calculated?


All the best and many thanks for your help!

 
RappNoyd #:

Hey Lorentzos,


Thank you so much, it works perfectly. Forgive me for my stupid question but is variable 'from' the same as the lookback? Why do you subtract 1 from prev_calculated?


All the best and many thanks for your help!

I confused myself too in the beggining but here is what happens . 

prev_calculated counts how many bars have been processed from the sum of rates_total.

But if we request i=prev_calculated in the for loop we have a problem , that we wont be accessing the live bar .

So if rates_total = 20 , (so we have 20 bars) and prev calculated is 0 , the first time it will execute from 0 to 19 , which is fine 

But then , with prev calculated 20 and rates total 20 it will try to go from 20 to 19 so it wont execute anything and it will perform a calculation when 

rates total becomes 21 but it will have skipped one bar . 

So the solution is to call from prev calculated - 1 , but then we have the issue that we cannot start from -1 when prev calculated is 0 (0-1=-1)

So we request the maximum from zero or prev calculated - 1, which handles all cases.