Please help, why does this indicator work fine in backtesting but cannot be displayed on the chart?

 
#property version   "1.00"
 
#define ND NormalizeDouble

#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   3
#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrDodgerBlue
#property indicator_color3 clrDodgerBlue
#property indicator_color4 clrGreen
#property indicator_color5 clrRed

#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_type3   DRAW_LINE
#property indicator_type4   DRAW_LINE
#property indicator_type5   DRAW_LINE

#property indicator_style1   STYLE_SOLID
#property indicator_style2   STYLE_DOT
#property indicator_style3   STYLE_DOT

#property indicator_style4   STYLE_SOLID
#property indicator_style5   STYLE_SOLID

#property indicator_label1   "PC Point"
#property indicator_label2   "PC Upper"
#property indicator_label3   "PC Lower"
#property indicator_label4   "PC Bull"
#property indicator_label5   "PC Bear"
  
input ENUM_TIMEFRAMES PCTF = PERIOD_D1;
input ENUM_APPLIED_PRICE PCMethod = PRICE_CLOSE;
input double PCDistance = 10.0;

ENUM_TIMEFRAMES PCTF_ = PERIOD_D1;
ENUM_APPLIED_PRICE PCMethod_ = PRICE_CLOSE;
double PCDistance_ = 10.0;


double PointBuffer[];
double UpperBuffer[];
double LowerBuffer[];
double BullBuffer[];
double BearBuffer[];

int prevShift = 0;
datetime prevTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit() {
  PCDistance_ = ND(PCDistance * _Point, _Digits);
  if (_Digits % 2 == 1) PCDistance_ = 10.0 * PCDistance_;
  PCMethod_ = PCMethod;
  PCTF_ = PCTF;
 
  ArrayInitialize(PointBuffer, 0);
  ArrayInitialize(UpperBuffer, 0);
  ArrayInitialize(LowerBuffer, 0);
  ArrayInitialize(BullBuffer, 0);
  ArrayInitialize(BearBuffer, 0);
  SetIndexBuffer(0, PointBuffer, INDICATOR_DATA);
  SetIndexBuffer(1, UpperBuffer, INDICATOR_DATA);
  SetIndexBuffer(2, LowerBuffer, INDICATOR_DATA);
  SetIndexBuffer(3, BullBuffer, INDICATOR_DATA);
  SetIndexBuffer(4, BearBuffer, INDICATOR_DATA);

  return;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
//---

}
//+------------------------------------------------------------------+
//| Expert tick 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 pos = 0;
 
  if(prev_calculated > 1) pos = prev_calculated - 1;
  else pos = 0;

  double PCprice = 0;
  bool isOK = false; 
  for (int i = pos; i < rates_total; i++) {
    datetime curTime = time[i];
    int curDay = TimeDay(curTime);
    int prevDay = TimeDay(prevTime);
    int shift = iBarShift(NULL, PCTF_, curTime, false) + 1;
    //Print(TimeToString(curTime), " ", TimeToString(prevTime));
    if (shift < prevShift || curDay != prevDay || prevShift == 0) {

      prevShift = shift;
      prevTime = curTime;
      switch (PCMethod_) {
      case PRICE_CLOSE:
        PCprice = iCloseMQL4(NULL, PCTF_, shift);
        break;
      case PRICE_OPEN:
        PCprice = iOpen(NULL, PCTF_, shift);
        break;
      case PRICE_HIGH:
        PCprice = iHigh(NULL, PCTF_, shift);
        break;
      case PRICE_LOW:
        PCprice = iLow(NULL, PCTF_, shift);
        break;
      case PRICE_MEDIAN:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift)) / 2.0;
        break;
      case PRICE_TYPICAL:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift)) / 3.0;
        break;
      case PRICE_WEIGHTED:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift)) / 4.0;
        break;
      default:
        if (iOpen(NULL, PCTF_, shift) < iClose(NULL, PCTF_, shift)) isOK = true;
        else isOK = false;
      }
      if (PCprice <= 0 || PCprice == EMPTY_VALUE || PCprice > 10000000) {
        prevShift = 0;
        continue;
      }
      
      if (PCMethod_ < 7) {
        PointBuffer[i - 1] = EMPTY_VALUE;
        PointBuffer[i] = PCprice;
        //Print(i, " ", PointBuffer[i], " ", rates_total);
        if (PCDistance_ <= 0.0) continue;
        UpperBuffer[i - 1] = EMPTY_VALUE;
        LowerBuffer[i - 1] = EMPTY_VALUE;
        UpperBuffer[i] = PCprice + PCDistance_;
        LowerBuffer[i] = PCprice - PCDistance_;
        continue;
      }
      BearBuffer[i + 1] = EMPTY_VALUE;
      BullBuffer[i + 1] = EMPTY_VALUE;
      UpperBuffer[i + 1] = EMPTY_VALUE;
      LowerBuffer[i + 1] = EMPTY_VALUE;
      if (isOK) {
        BullBuffer[i] = close[i + 1];
        if (PCDistance_ <= 0.0) continue;
        UpperBuffer[i] = BullBuffer[i] + PCDistance_;
        continue;
      }
      BearBuffer[i] = close[i + 1];
      if (PCDistance_ > 0.0) LowerBuffer[i] = BearBuffer[i] - PCDistance_;
    } else if (shift == prevShift && curTime > prevTime) {
      if (PCMethod_ < 7) {
        PointBuffer[i] = PointBuffer[i - 1];
        Print(i, " ", PointBuffer[i], " ", rates_total);
        if (PCDistance_ > 0.0) {
          UpperBuffer[i] = PointBuffer[i] + PCDistance_;
          LowerBuffer[i] = PointBuffer[i] - PCDistance_;
        }
      } else {
        if (BullBuffer[i + 1] != EMPTY_VALUE) {
          BullBuffer[i] = BullBuffer[i + 1];
          if (PCDistance_ > 0.0) UpperBuffer[i] = BullBuffer[i] + PCDistance_;
        }
        if (BearBuffer[i + 1] != EMPTY_VALUE) {
          BearBuffer[i] = BearBuffer[i + 1];
          if (PCDistance_ > 0.0) LowerBuffer[i] = BearBuffer[i] - PCDistance_;
        }
      }
      prevTime = curTime;
    }


  }

  return rates_total;
}
int TimeDay(datetime date) {
  MqlDateTime tm;
  TimeToStruct(date, tm);
  return(tm.day);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double iCloseMQL4(string symbol, ENUM_TIMEFRAMES tf, int index) {
  if(index < 0) return(-1);
  double Arr[];
  if(CopyClose(symbol, tf, index, 1, Arr) > 0)
    return(Arr[0]);
  else return(-1);
}
//+------------------------------------------------------------------+
 
//+------------------------------------------------------------------+
string TFMigrate(int time) {
  switch (time) {
  case 43200:
    return ("MN1");
  case 10080:
    return ("W1");
  case 1440:
    return ("D1");
  case 240:
    return ("H4");
  case 60:
    return ("H1");
  case 30:
    return ("M30");
  case 15:
    return ("M15");
  case 5:
    return ("M5");
  case 1:
    return ("M1");
  }
  return ("Unknown");
}
//+------------------------------------------------------------------+

Please help, why does this indicator work fine in backtesting but cannot be displayed on the chart?


 
  1. hini: Please help, why does this indicator work fine in backtesting but cannot be displayed on the chart?

    If you can't display it on a chart, how can you possible know it is working fine in backtesting?


  2.   ArrayInitialize(PointBuffer, 0);
      ArrayInitialize(UpperBuffer, 0);
      ArrayInitialize(LowerBuffer, 0);
      ArrayInitialize(BullBuffer, 0);
      ArrayInitialize(BearBuffer, 0);
      SetIndexBuffer(0, PointBuffer, INDICATOR_DATA);
      SetIndexBuffer(1, UpperBuffer, INDICATOR_DATA);
      SetIndexBuffer(2, LowerBuffer, INDICATOR_DATA);
      SetIndexBuffer(3, BullBuffer, INDICATOR_DATA);
      SetIndexBuffer(4, BearBuffer, INDICATOR_DATA);

    How can you initialize empty arrays? They aren't buffers and haven't been resized yet. Why are you setting them to zero when you use EMPTY_VALUE later?

  3.     datetime curTime = time[i];

    Are you accessing arrays and buffers as time series or non-series. Did you set your arrays and buffers to match? Does it match iHigh's and iBarShift's direction?

    In MT5, you must set the direction.

    To define the indexing direction in the time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call the ArrayGetAsSeries() function. In order not to depend on defaults, call the ArraySetAsSeries() function for the arrays to work with.
              Event Handling / OnCalculate - Reference on algorithmic/automated trading language for MetaTrader 5
  4.   case 60:
        return ("H1");
    Use the proper enumeration, not ints. PERIOD_H1 is not 60 in MT5.
 
William Roeder #:
  1. If you can't display it on a chart, how can you possible know it is working fine in backtesting?


  2. How can you initialize empty arrays? They aren't buffers and haven't been resized yet. Why are you setting them to zero when you use EMPTY_VALUE later?

  3. Are you accessing arrays and buffers as time series or non-series. Did you set your arrays and buffers to match? Does it match iHigh's and iBarShift's direction?

    In MT5, you must set the direction.

  4. Use the proper enumeration, not ints. PERIOD_H1 is not 60 in MT5.

thank you for your reply.

When I click the debug button in MetaEditor, it starts the Strategy Tester and I can see the indicators displayed correctly. However, when I drag the indicators onto the MT5 chart, they do not show up, and I am not sure why. I have already resolved this issue by making some modifications, and now the indicators are displaying properly. After testing, I found that the "pos" variable needs to be added with a certain number in order to display correctly, which confuses me.

Additionally, I have tried to change the color of the indicator but was not successful. I attempted to use "DRAW_COLOR_LINE" but it did not work.

#define ND NormalizeDouble

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   3

#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_type3   DRAW_LINE

#property indicator_color1  clrRed,clrGreen,clrBlue
#property indicator_color2  clrDodgerBlue
#property indicator_color3  clrDodgerBlue

#property indicator_style1   STYLE_SOLID
#property indicator_style2   STYLE_DOT
#property indicator_style3   STYLE_DOT

#property indicator_label1   "PC Point"
#property indicator_label2   "PC Upper"
#property indicator_label3   "PC Lower"

enum MY_ENUM_APPLIED_PRICE {
  MY_PRICE_CLOSE = 1,
  MY_PRICE_OPEN = 2,
  MY_PRICE_HIGH = 3,
  MY_PRICE_LOW = 4,
  MY_PRICE_MEDIAN = 5,
  MY_PRICE_TYPICAL = 6,
  MY_PRICE_WEIGHTED = 7,
  MY_PC_IS_LONG_SHORT = 8
};
 
input ENUM_TIMEFRAMES PCTF = PERIOD_D1;
input MY_ENUM_APPLIED_PRICE PCMethod = MY_PC_IS_LONG_SHORT;
input double PCDistance = 10.0;

ENUM_TIMEFRAMES PCTF_ = PERIOD_D1;
int PCMethod_ = PRICE_CLOSE;
double PCDistance_ = 10.0;
 

double ColorBuffer[];
double PointBuffer[];
double UpperBuffer[];
double LowerBuffer[];
int prevShift = 0;
datetime prevTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit() {
  PCDistance_ = ND(PCDistance * _Point, _Digits);
  if (_Digits % 2 == 1) PCDistance_ = 10.0 * PCDistance_;
  PCMethod_ = PCMethod;
  PCTF_ = PCTF;
  
  SetIndexBuffer(0, PointBuffer, INDICATOR_DATA);
  SetIndexBuffer(1, UpperBuffer, INDICATOR_DATA);
  SetIndexBuffer(2, LowerBuffer, INDICATOR_DATA);
  SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); // 
  
  return;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
//---

}
//+------------------------------------------------------------------+
//| Expert tick 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 pos = 0;
  if(prev_calculated > 1) pos = prev_calculated - 1;
  else pos = 0;
   
  double PCprice = 0;
  bool isLong = false;

  if (_Period == PERIOD_M1 || _Period == PERIOD_M2 || _Period == PERIOD_M3) pos += 437;
  if (_Period == PERIOD_M5 || _Period == PERIOD_M6 || _Period == PERIOD_M10 || _Period == PERIOD_M12) pos += 88;
  if (_Period == PERIOD_M15 || _Period == PERIOD_M20) pos += 30;
  if (_Period == PERIOD_M30 || _Period == PERIOD_H1) pos += 15;
  if (_Period == PERIOD_H2 || _Period == PERIOD_H3) pos += 8;
  if (_Period == PERIOD_H4) pos += 3;
  //Print(pos, " ", (int)PERIOD_CURRENT, " ", (int)PERIOD_H1);
  for (int i = pos; i < rates_total; i++) {
    datetime curTime = time[i];
    int shift = iBarShift(NULL, PCTF_, curTime, false) + 1; 

    if (shift < prevShift || prevShift == 0) {
      prevShift = shift;
      prevTime = curTime;
      switch (PCMethod_) {
      case MY_PRICE_CLOSE:
        PCprice = iClose(NULL, PCTF_, shift);
        break;
      case MY_PRICE_OPEN:
        PCprice = iOpen(NULL, PCTF_, shift);
        break;
      case MY_PRICE_HIGH:
        PCprice = iHigh(NULL, PCTF_, shift);
        break;
      case MY_PRICE_LOW:
        PCprice = iLow(NULL, PCTF_, shift);
        break;
      case MY_PRICE_MEDIAN:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift)) / 2.0;
        break;
      case MY_PRICE_TYPICAL:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift)) / 3.0;
        break;
      case MY_PRICE_WEIGHTED:
        PCprice = (iHigh(NULL, PCTF_, shift) + iLow(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift) + iClose(NULL, PCTF_, shift)) / 4.0;
        break;
      default: //8
        if (iOpen(NULL, PCTF_, shift) < iClose(NULL, PCTF_, shift)) isLong = true; //short
        else isLong = false; //long
        break;
      }

      if (PCMethod_ < MY_PC_IS_LONG_SHORT) {
        if (PCprice <= 0 || PCprice == EMPTY_VALUE || PCprice > 10000000) {
          continue;
        }
        PointBuffer[i - 1] = EMPTY_VALUE;
        PointBuffer[i] = PCprice;
        if (PCDistance_ <= 0.0) continue;
        UpperBuffer[i - 1] = EMPTY_VALUE;
        LowerBuffer[i - 1] = EMPTY_VALUE;
        UpperBuffer[i] = PCprice + PCDistance_;
        LowerBuffer[i] = PCprice - PCDistance_;
        continue;
      }
      //Print("isLong: ",isLong);
      PointBuffer[i - 1] = EMPTY_VALUE;
      UpperBuffer[i - 1] = EMPTY_VALUE;
      LowerBuffer[i - 1] = EMPTY_VALUE;
      PointBuffer[i] = close[i - 1];
      LowerBuffer[i] = PointBuffer[i] - PCDistance_;
      UpperBuffer[i] = PointBuffer[i] + PCDistance_;
      //PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, clrBlue);
      if (isLong) {
        
        //PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, clrBlue);           
        //ColorBuffer[i] = 1;
      } else {
        //PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, clrRed); 
        //ColorBuffer[i] = 2;
      }
    } else if (shift == prevShift && curTime > prevTime) {
 
      if (PCMethod_ < MY_PC_IS_LONG_SHORT) {
        PointBuffer[i] = PointBuffer[i - 1];
        if (PCDistance_ > 0.0) {
          UpperBuffer[i] = PointBuffer[i] + PCDistance_;
          LowerBuffer[i] = PointBuffer[i] - PCDistance_;
        }
      } else {
        PointBuffer[i] = PointBuffer[i - 1];
        if (PointBuffer[i - 1] != EMPTY_VALUE && isLong) {
          if (PCDistance_ > 0.0) {
            UpperBuffer[i] = PointBuffer[i] + PCDistance_;
            LowerBuffer[i] = EMPTY_VALUE;
          }
        }
        if (PointBuffer[i - 1] != EMPTY_VALUE && !isLong) {
          if (PCDistance_ > 0.0) {
            LowerBuffer[i] = PointBuffer[i] - PCDistance_;
            UpperBuffer[i] = EMPTY_VALUE;
          }
        }
      }
      prevTime = curTime;
    }


  }

  return rates_total;
}

//+------------------------------------------------------------------+
Reason: