Custom Indicator: iCustom values do not correspond to values on chart

 

Hi All

Newbie MQL developer, so bare with me please. Created a custom indicator which plots what I need, exactly as I need it on the graph. However, when I try to get the values at a particular bar, through iCustom - I don't get the same values as the chart and I can't understand what I am doing wrong.

Here's the iCustom call:

      double main = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 0, 0);
      double signal = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 1, 0);

Here's the indicator code:

#property copyright "Copyright © 2017, Sameer Shariff"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum    -1.0
#property indicator_maximum    1.0
#property indicator_buffers    2
#property indicator_color1     Red
#property indicator_color2     DodgerBlue
#property indicator_level1     0.7
#property indicator_level2     0.5
#property indicator_level3     -0.5
#property indicator_levelcolor White
#property indicator_levelstyle STYLE_DASHDOT
//--- Input Parameters
extern int FastPeriod = 24;
extern int SlowPeriod = 90;
extern string Instrument1 = "EURUSD";
extern string Instrument2 = "AUDUSD";
//--- Buffers
double ExtMainBuffer[];
double ExtSignalBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   if (FastPeriod < 2)
   {
      Print("Incorrect value for input variable FastPeriod = ", FastPeriod);
      return(INIT_FAILED);
   }
   
   if (SlowPeriod < 2)
   {
      Print("Incorrect value for input variable SlowPeriod = ", SlowPeriod);
      return(INIT_FAILED);
   }
   
   if (Instrument1 == "")
   {
      Print("Incorrect value for input variable Instrument1 = ", Instrument1);
      return(INIT_FAILED);
   }
   
   if (Instrument2 == "")
   {
      Print("Incorrect value for input variable Instrument2 = ", Instrument2);
      return(INIT_FAILED);
   }

   IndicatorBuffers(2);
   
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, ExtMainBuffer);
   SetIndexLabel(0, "Slow Period(" + IntegerToString(SlowPeriod) + ")");
   
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, ExtSignalBuffer);
   SetIndexLabel(1, "Fast Period(" + IntegerToString(FastPeriod) + ")");

   IndicatorShortName("CDI(" + Instrument1 + "-" + Instrument2 + "[" + IntegerToString(FastPeriod) + "," + IntegerToString(SlowPeriod) + "])");

   SetIndexDrawBegin(0, SlowPeriod);
   SetIndexDrawBegin(1, FastPeriod);
   
   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[])
{
   for (int shift = 0; shift < rates_total; shift++)
   {
      ExtMainBuffer[shift] = GetData(PERIOD_D1, SlowPeriod, shift);
      ExtSignalBuffer[shift] = GetData(PERIOD_H1, FastPeriod, shift);
      
      Print(ExtMainBuffer[shift]);
   }

   return(rates_total);
}

double GetData(int timeframe, int period, int shift)
{
   return NormalizeDouble(0.0 + 1.0 * MathRand() / 32768.0,2) * (shift % 2 == 0 ? 1 : -1);
}
 

You'll need to show what makes you think you're not getting the correct values... screenshots or print statements.

 

The code you have posted won't compile,  you will need to show GetMainData() and GetSignalData() if you want anyone to try to replicate the issue.

 

That's not really how it works...

I know iCustom works, so the problem is in your code somewhere. 

If you're sure there is an issue, I suggest you post up code that compiles (using 1.0 and -1.0 if you wish, rather than disclosing your secret sauce) but which does not return correct values.

Good luck :)

 
honest_knave:

That's not really how it works...

I know iCustom works, so the problem is in your code somewhere. 

If you're sure there is an issue, I suggest you post up code that compiles (using 1.0 and -1.0 if you wish, rather than disclosing your secret sauce) but which does not return correct values.

Good luck :)


Updated the code. Mocked the actual indicator logic / data. But now it should compile and you should be able to see it.
 
Sameer Shariff:

Updated the code. Mocked the actual indicator logic / data. But now it should compile and you should be able to see it.
double GetData(int timeframe, int period, int shift)
{
   return NormalizeDouble(0.0 + 1.0 * MathRand() / 32768.0,2) * (shift % 2 == 0 ? 1 : -1);
}


Are you using random numbers in GetMainData() and GetSignalData() too?

If you use a random number to generate the values of your buffers, they probably aren't going to be the same between the iCustom instance of your indicator and the chart instance of your indicator.

If you change your indicator mock logic to something indisputable (e.g. Bar volume and time):

   for (int shift = 0; shift < rates_total; shift++)
   {
      ExtMainBuffer[shift] = (double)Time[shift];
      ExtSignalBuffer[shift] = (double)Volume[shift];
      
      printf("Indicator | Shift: %i ExtMainBuffer: %f ExtSignalBuffer: %f",
              shift, ExtMainBuffer[shift], ExtSignalBuffer[shift]);
   }

And then your call:

      int shift = 0;
      double main = iCustom(Symbol(), PERIOD_CURRENT, "Test", 0, shift);
      double signal = iCustom(Symbol(), PERIOD_CURRENT, "Test", 1, shift);
      printf("iCustom | Shift: %i main: %f signal: %f",
              shift, main, signal);

You can see from the print statements there is no disparity (remember you count up in your loop, so we need to check the oldest print statement, not the newest) :


If you weren't using random numbers, my best guess is that you are comparing the newest print statement (oldest bar) with an iCustom call to the newest bar.

 

Forum on trading, automated trading systems and testing trading strategies

Custom Indicator: Values on Chart differ from Backtest

Sameer Shariff, 2017.04.02 04:27

Hi

Need urgent help. Have a custom indicator, which I call like this:

double main = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 0, 0);
double signal = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 1, 0);

The custom indicator code is like this:

#property copyright "Copyright © 2017, Sameer Shariff"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum    -1.0
#property indicator_maximum    1.0
#property indicator_buffers    2
#property indicator_color1     Red
#property indicator_color2     DodgerBlue
#property indicator_level1     0.7
#property indicator_level2     0.5
#property indicator_level3     -0.5
#property indicator_levelcolor White
#property indicator_levelstyle STYLE_DASHDOT
//--- Input Parameters
extern int FastPeriod = 24;
extern int SlowPeriod = 90;
extern string Instrument1 = "EURUSD";
extern string Instrument2 = "AUDUSD";
//--- Buffers
double ExtMainBuffer[];
double ExtSignalBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   if (FastPeriod < 2)
   {
      Print("Incorrect value for input variable FastPeriod = ", FastPeriod);
      return(INIT_FAILED);
   }
   
   if (SlowPeriod < 2)
   {
      Print("Incorrect value for input variable SlowPeriod = ", SlowPeriod);
      return(INIT_FAILED);
   }
   
   if (Instrument1 == "")
   {
      Print("Incorrect value for input variable Instrument1 = ", Instrument1);
      return(INIT_FAILED);
   }
   
   if (Instrument2 == "")
   {
      Print("Incorrect value for input variable Instrument2 = ", Instrument2);
      return(INIT_FAILED);
   }

   IndicatorBuffers(2);
   
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, ExtMainBuffer);
   SetIndexLabel(0, "Slow Period(" + IntegerToString(SlowPeriod) + ")");
   
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, ExtSignalBuffer);
   SetIndexLabel(1, "Fast Period(" + IntegerToString(FastPeriod) + ")");

   IndicatorShortName("CDI(" + Instrument1 + "-" + Instrument2 + "[" + IntegerToString(FastPeriod) + "," + IntegerToString(SlowPeriod) + "])");

   SetIndexDrawBegin(0, SlowPeriod);
   SetIndexDrawBegin(1, FastPeriod);
   
   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[])
{
   for (int shift = rates_total - 1; shift >= 0; shift--)
   {
      ExtMainBuffer[shift] = GetData(PERIOD_D1, SlowPeriod, shift);
      ExtSignalBuffer[shift] = GetData(PERIOD_H1, FastPeriod, shift);
   }

   return(rates_total);
}
//+------------------------------------------------------------------+
//| Custom indicator get data function                               |
//+------------------------------------------------------------------+
double GetData(int timeframe, int period, int shift)
{
   return timeframe == PERIOD_D1 ? NormalizeDouble(MathMod(MathSin((double)Close[shift]-1.0 * period * 100.0) * 100000000000000, 1.0), 2) : NormalizeDouble(MathMod(MathSin((double)Volume[shift]-1.0 * period * 100.0) * 100000000000000, 1.0), 2);
}

Chart output is this:

Backtester output is this:


As you can see, even if you run it locally - the chart output and backtest output don't match. Notice signal is constant, but on the chart it's not. At 23:00 Main is -0.52 on chart, but -0.47 in backtest. Someone please have a look and tell me where I am going wrong.

Many thanks!

 

I've moved your new thread to here - please don't duplicate threads.

I've answered your query above - you are looking at the wrong print statements. 

 

 
honest_knave:

I've moved your new thread to here - please don't duplicate threads.

I've answered your query above - you are looking at the wrong print statements. 

 


Hi

I appreciate your answer and  looked at what you were saying, but it doesn't tie up. In the backtester indicator and iCustom do return the same values, however those values are not the same as whats on the chart.

I don't understand why not. I am not using random in my actual method - it's doing a consistent calculation.

Kind Regards,

Sameer

 
Sameer Shariff:


Hi

I appreciate your answer and  looked at what you were saying, but it doesn't tie up. In the backtester indicator and iCustom do return the same values, however those values are not the same as whats on the chart.

I don't understand why not. I am not using random in my actual method - it's doing a consistent calculation.

Kind Regards,

Sameer


The screenshot I posted above was not from a backtest, and it was using the indicator as you posted it.

I'm almost certain the problem is that you're confusing the index when you print the iCustom value.

Try this:

Add your CDI indicator to a chart

Save this script to your scripts folder

void OnStart()
  {
   int shift = 0;
   double main = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 0, shift);
   double signal = iCustom(Symbol(), PERIOD_CURRENT, "CDI", 1, shift);
   printf("iCustom | Shift: %i main: %f signal: %f", shift, main, signal);
  }

Drop the script onto your chart.

The printed value should match the latest values on your chart.

 
honest_knave:


The screenshot I posted above was not from a backtest, and it was using the indicator as you posted it.

I'm almost certain the problem is that you're confusing the index when you print the iCustom value.

Try this:

Add your CDI indicator to a chart

Save this script to your scripts folder

Drop the script onto your chart.

The printed value should match the latest values on your chart.


Here's results for getting the last bar, which should be shift = 0, to represent the current bar.

BACKTESTER
2017.04.02 22:33:06.713 2017.03.31 23:00:00  Fake Move Scalper EURAUD,H1: iCustom | Shift: 0 main: -0.340000 signal: 0.020000
2017.04.02 22:33:06.713 2017.03.31 23:00:00  CDI EURAUD,H1: Indicator | Shift: 0 ExtMainBuffer: -0.340000 ExtSignalBuffer: 0.020000 FastPeriod: 24 SlowPeriod: 90 Instrument1: EURUSD Instrument2: AUDUSD

CHART
2017.04.02 22:31:37.996 Test EURAUD,H1: iCustom | Shift: 0 main: 0.860000 signal: 0.310000
2017.04.02 22:31:37.995 CDI EURAUD,H1: Indicator | Shift: 0 ExtMainBuffer: 0.860000 ExtSignalBuffer: 0.310000 FastPeriod: 24 SlowPeriod: 90 Instrument1: EURUSD Instrument2: AUDUSD

I don't understand what's going on. Try dropping the indicator on a chart and do a backtest with some test EA that uses iCustom and you will see that chart and backtest just don't tie up.

Reason: