Why would this work on the chart window and not on separate window?

 

Hello fellow coders. Been trying something out on MT5 and this code works well on the chart window but doesn't work if set to draw on separate window. Code simplified for forum purposes.

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1

//--- plot Slope_up
#property indicator_label1  "Slope_line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// User inputs
input string    MaSettings="MA settings";
input int       Maperiod=14;
input int       Mashift=0;
input ENUM_MA_METHOD       Mamethod=MODE_SMA;
input ENUM_APPLIED_PRICE       MaappliedPrice=PRICE_CLOSE;


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

//--- indicator buffers
double         Slope_Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Slope_Buffer,INDICATOR_DATA);
//---
   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 count=rates_total-prev_calculated-1;



    for(int i=count; i>=0&& !IsStopped(); i--)
     {
      double SlopeBufferRaw=0;
      double IndNow=MyInd(count,PERIOD_CURRENT);
    
      Slope_Buffer[count]=IndNow;


     }
//  }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|      Fetch  indicator value by shift                                          |
//+------------------------------------------------------------------+
/*
input string    MaSettings="First MA settings";
input int       Maperiod=14;
input int       Mashift=0;
input ENUM_MA_METHOD       Mamethod=MODE_SMA;
input int       MaappliedPrice=PRICE_CLOSE;

e.g. MyInd(0,0);
*/
double MyInd(int miShift,ENUM_TIMEFRAMES miTimeFrame)
  {
   double IndiValue;
   double      IndArray[];
   int         Ind_handle;
   Ind_handle=iMA(NULL,miTimeFrame,Maperiod,Mashift,Mamethod,MaappliedPrice);

//--- report if there was an error in object creation
   if(Ind_handle<0)
     {
      Print("The creation of iMA has failed: MA_handle=",INVALID_HANDLE);
      Print("Runtime error = ",GetLastError());
      //--- forced program termination
     }

   CopyBuffer(Ind_handle,0,0,3,IndArray);
   ArraySetAsSeries(IndArray,true);
   IndiValue=IndArray[miShift];

   return(IndiValue);
  }
//+------------------------------------------------------------------+
 
DO NOT CREATE AN INDICATOR HANDLE ON EACH TICK !!! The indicator handle SHOULD be created ONLY ONCE !!! And you need to do this in OnInit !!!
 
Vladimir Karputov #:
DO NOT CREATE AN INDICATOR HANDLE ON EACH TICK !!! The indicator handle SHOULD be created ONLY ONCE !!! And you need to do this in OnInit !!!

Code works okay on the chart window only doesn't work on separate window.

 
Tonny Obare # :

Code works okay on the chart window only doesn't work on separate window.

The MQL5 style implies that the indicator handle MUST be created ONCE. Please correct this error. Only then will it be possible to look at your code.

 
Vladimir Karputov #:

The MQL5 style implies that the indicator handle MUST be created ONCE. Please correct this error. Only then will it be possible to look at your code.

Hello. Thanks for that lead. It actually did improve it. The previous code seems fine now. Now I have added a bit more code. What happens now is the indie shows blank when I output out a simple calculation.

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1

//--- plot Slope_up
#property indicator_label1  "Slope_line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// User inputs
input string    MaSettings="MA settings";
input int       Maperiod=14;
input int       Mashift=0;
input ENUM_MA_METHOD       Mamethod=MODE_SMA;
input ENUM_APPLIED_PRICE       MaappliedPrice=PRICE_CLOSE;
input string SlopeSettings="Settings for slope";
input int Slope_LookBack=3;
//----------------

//--- indicator buffers
double         Slope_Buffer[];


double IndiValue;
double      IndArray[];
int         Ind_handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   Ind_handle=iMA(NULL,PERIOD_CURRENT,Maperiod,Mashift,Mamethod,MaappliedPrice);

//--- report if there was an error in object creation
   if(Ind_handle<0)
     {
      Print("The creation of iMA has failed: MA_handle=",INVALID_HANDLE);
      Print("Runtime error = ",GetLastError());
      //--- forced program termination
     }

//--- indicator buffers mapping
   SetIndexBuffer(0,Slope_Buffer,INDICATOR_DATA);
//---
   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[])
  {
   CopyBuffer(Ind_handle,0,0,3,IndArray);
   ArraySetAsSeries(IndArray,true);

//---
   int count=rates_total-prev_calculated-1;

   while(count>=0)
     {
     if(count<100){
      double SlopeBufferRaw=0;
      double IndNow=IndArray[count];
      double IndAgo=IndArray[count-Slope_LookBack];

      SlopeBufferRaw=((IndNow-IndAgo))/(Slope_LookBack+1);
      Slope_Buffer[count]=NormalizeDouble(SlopeBufferRaw/Point(), 2 );
}
      count--;
     }
//  }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
  1.    int count=rates_total-prev_calculated-1;
    
       while(count>=0)

    You return rates_total, so on the next tick count is minus one, and you never update bar zero.
              How to do your lookbacks correctly #9#14 & #19

  2.    CopyBuffer(Ind_handle,0,0,3,IndArray);
       ⋮
         if(count<100){
          double IndNow=IndArray[count];
    You only read three (3) values. So invalid access when count is three or greater.
 
Tonny Obare # :

Hello. Thanks for that lead. It actually did improve it. The previous code seems fine now. Now I have added a bit more code. What happens now is the indie shows blank when I output out a simple calculation.

An example of how to copy data from the iMA indicator correctly

Documentation on MQL5: Technical Indicators / iMA
Documentation on MQL5: Technical Indicators / iMA
  • www.mql5.com
iMA - Technical Indicators - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
William Roeder #:
  1. You return rates_total, so on the next tick count is minus one, and you never update bar zero.
              How to do your lookbacks correctly #9#14 & #19

  2. You only read three (3) values. So invalid access when count is three or greater.

Thanks but still not okay. It shows a line with positive values only while it should also show negative when current iMA value is lower than iMA value a few bars ago. The code now.

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1

//--- plot Slope_up
#property indicator_label1  "Slope_line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// User inputs
input string    MaSettings="MA settings";
input int       Maperiod=14;
input int       Mashift=0;
input ENUM_MA_METHOD       Mamethod=MODE_SMA;
input ENUM_APPLIED_PRICE       MaappliedPrice=PRICE_CLOSE;
input string SlopeSettings="Settings for slope";
input int Slope_LookBack=3;
//----------------

//--- indicator buffers
double         Slope_Buffer[];


double IndiValue;
double      IndArray[];
int         Ind_handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   Ind_handle=iMA(NULL,PERIOD_CURRENT,Maperiod,Mashift,Mamethod,MaappliedPrice);

//--- report if there was an error in object creation
   if(Ind_handle<0)
     {
      Print("The creation of iMA has failed: MA_handle=",INVALID_HANDLE);
      Print("Runtime error = ",GetLastError());
      //--- forced program termination
     }

//--- indicator buffers mapping
   SetIndexBuffer(0,Slope_Buffer,INDICATOR_DATA);
//---
   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[])
  {

   CopyBuffer(Ind_handle,0,0,Bars(Symbol(),PERIOD_CURRENT),IndArray);
   ArraySetAsSeries(IndArray,true);

//---
   int count=Bars(Symbol(),PERIOD_CURRENT)-prev_calculated-1;

   while(count>=0)
     {

      if(count<1000)
        {
         double SlopeBufferRaw=0;
         double IndNow=IndArray[count];
         double IndAgo=IndArray[count+Slope_LookBack];

         SlopeBufferRaw=((IndNow-IndAgo)/(Slope_LookBack+1));
         Slope_Buffer[count]=NormalizeDouble(SlopeBufferRaw,0);
        }
      count--;
     }
//  }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

The calculation below should sometimes give values less than 0

         SlopeBufferRaw=((IndNow-IndAgo)/(Slope_LookBack+1)); // If IndAgo > than IndNow result should be negative
         Slope_Buffer[count]=NormalizeDouble(SlopeBufferRaw,0); // If IndAgo > than IndNow output should be negative

As you can see below. line is all positive. Its like its guessing its own values.


 

Just to update, I have done an mt4 equivalent and it works okay. Problem is the mt5 version. Here is the mt4 code.

#property indicator_buffers 1
#property indicator_plots 1

//--- plot Slope_up
#property indicator_label1  "Slope_line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// User inputs
input string    MaSettings="MA settings";
input int       Maperiod=14;
input int       Mashift=0;
input ENUM_MA_METHOD       Mamethod=MODE_SMA;
input ENUM_APPLIED_PRICE       MaappliedPrice=PRICE_CLOSE;
input string SlopeSettings="Settings for slope";
input int Slope_LookBack=3;
//----------------

//--- indicator buffers
double         Slope_Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Slope_Buffer,INDICATOR_DATA);
//---
   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=IndicatorCounted(); // Number of counted bars
 int  i=Bars-Counted_bars-1;           // Index of the first uncounted
   while(i>=0) 
     {
      double SlopeBufferRaw=0;
      double IndNow=iMA(NULL,0,Maperiod,Mashift,Mamethod,MaappliedPrice,i); 
      double IndAgo=iMA(NULL,0,Maperiod,Mashift,Mamethod,MaappliedPrice,i+Slope_LookBack); 
      SlopeBufferRaw=((IndNow-IndAgo))/(Slope_LookBack+1);
      Slope_Buffer[i]=NormalizeDouble(SlopeBufferRaw/Point(),_Digits);

i--;
     }
//  }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Below is how the line is correctly plotted on mt4.


The chart should actually show points. In mt5 it either shows blank or it displays wrong values. Could it be a bug in mt5 system?
 

Nothing wrong with MT5 in your case - but your code



Files:
test.mq5  4 kb
 
Mladen Rakic #:

Nothing wrong with MT5 - but your code



Your code gives completely different values from the mt4 version that is fine. If for example MaNow is say 1.00090 and Ma 3 bars ago 1.00080 then ( 1.00092 - 1.00080 )/(3+1) = 0.00003 so 

0.00003/_Point
Should show a value of 3 on the chart.
Reason: