Calls to iCustom on launch or period switch causes 2s delay

 

Hi everyone,

I made a dashboard that scans 7 pairs for price action candlesticks on 5 different time frames. Rather than waste time explaining it further, I'll just show a picture.


Anyway, the dashboard calls on iCustom for 4 different indicators.

When the indicator launches, or when you switch timeframes on the chart, there's a 2 second delay.

I've done some research into this, and I read that it could be if the indicator code is not optimized or iCustom has some wrong input parameters that are causing the issue.

Originally, I didn't specify any parameters of the indicators for iCustom, so I thought I'd try specifying parameters. No difference; the dashboard still takes 2 seconds to load and 2 seconds when switching timeframes.

I also looked back at the code to see if that was it. People mentioned that it could be the indicators are calculating every bar on every tick. I wasn't using "counted_bars = IndicatorCounted();", so I added it to OnCalculate (as per the example in the help manual), but it still doesn't make a difference in terms of loading time and when switching timeframes.

Anyway, here's some relevant code:

Dashboard call to check indicators

void checkIndicators(){
   for (int x = 0; x <= ArraySize(pairDB)-1; x++){
      for (int y = 0; y <= 4; y++){
         int timeframe        = findTF(y);
         int shift            = 1;         
         double checkSignal   = 0;      
         bool foundSignal     = false;   
         //--- Pinbar
         if (!foundSignal){
            foundSignal = checkPinbars(checkSignal,x,timeframe,shift); 
         }         
         //--- Outside Bar        
         if (!foundSignal){  
            foundSignal = checkEngulfing(checkSignal,x,timeframe,shift); 
         }
         //--- Piercing Pattern / Darkcloud Cover         
         if (!foundSignal){
            foundSignal = checkPiercingDarkCloud(checkSignal,x,timeframe,shift);
         }
         //--- Inside Bar
         if (!foundSignal){
            foundSignal = checkHarami(checkSignal,x,timeframe,shift);
         }
      }
   }
}

Dashboard calls to iCustom

bool checkPinbars(double checkSignal, int x, int timeframe, int shift){
   checkSignal = iCustom(pairDB[x],timeframe,"Candlesticks\\PinBar Scanner.ex4",1,clrWhite,3,3.5,2.5,0,shift);
   if (checkSignal != EMPTY_VALUE){            
      double low     = iLow(pairDB[x],timeframe,shift);
      string name    = tfName(timeframe);
      //--- Check if Bullish Signal
      if (low > checkSignal){
         //--- Signal is Bullish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrGreen);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Hammer");
         return(true);
      }
      else{
         //--- Signal is Bearish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrRed);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Shooting Star");
         return(true);
      }
   }
   return(false);
}

bool checkEngulfing(double checkSignal, int x, int timeframe, int shift){
   checkSignal = iCustom(pairDB[x],timeframe,"Candlesticks\\Outside Candles.ex4",1,clrWhite,0,shift);
   if (checkSignal != EMPTY_VALUE){               
      double low     = iLow(pairDB[x],timeframe,shift); 
      string name    = tfName(timeframe); 
      //--- Check if Bullish Signal
      if (low > checkSignal){
         //--- Signal is Bullish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrGreen);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Engulfing Candle");
         return (true);
      }
      else{
         //--- Signal is Bearish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrRed);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Engulfing Candle");
         return (true);
      }
   }
   return(false);
}

bool checkPiercingDarkCloud(double checkSignal, int x, int timeframe, int shift){            
   checkSignal = iCustom(pairDB[x],timeframe,"Candlesticks\\Piercing-Darkclouds.ex4",1,clrWhite,0,shift);
   if (checkSignal != EMPTY_VALUE){               
      double low     = iLow(pairDB[x],timeframe,shift); 
      string name    = tfName(timeframe);
      //--- Check if Bullish Signal
      if (low > checkSignal){
         //--- Signal is Bullish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrGreen);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Piercing Pattern");
         return(true);
      }
      else{
         //--- Signal is Bearish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrRed);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Dark Cloud Cover");
         return(true);
      }
   }
   return(false);
}

bool checkHarami(double checkSignal, int x, int timeframe, int shift){
   checkSignal =  iCustom(pairDB[x],timeframe,"Candlesticks\\Inside Candles.ex4",1,clrWhite,0,0,shift);
   if (checkSignal != EMPTY_VALUE){               
      double low     = iLow(pairDB[x],timeframe,shift); 
      string name    = tfName(timeframe);
      //--- Check if Bullish Signal
      if (low > checkSignal){
         //--- Signal is Bullish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrGreen);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Harami");
         return(true);
      }
      else{
         //--- Signal is Bearish
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_BGCOLOR,clrRed);
         ObjectSetInteger(NULL,pairDB[x]+","+name,OBJPROP_COLOR,clrWhite);
         ObjectSetString(NULL,pairDB[x]+","+name,OBJPROP_TOOLTIP,"Harami"); 
         return(true);               
      }
   }
   return(false);
}

The Price Action indicators essentially follow the same template among each other, with the biggest difference being the calculations for finding the Price Action candles, so rather than posting all the code, I'll post the Properties, Input Parameters, OnInit, and OnCalculate.

#property strict
#property indicator_chart_window
#property indicator_buffers 1       // Number of buffers

extern int barsLookback=10; // Candles to look back. 0 = All Candles
input color arrowColor = clrWhite; // Arrow Color

double outsideCandle[];
int chartHeight;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){  
   if (barsLookback == 0) barsLookback = Bars-2;   
   SetIndexBuffer(0,outsideCandle); // Assigning an array to a buffer
   SetIndexStyle (0,DRAW_ARROW,EMPTY,2,arrowColor); // Line style    
   SetIndexArrow(0,159);
   chartHeight = (int)ChartGetInteger(NULL,CHART_HEIGHT_IN_PIXELS,0);
   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();
   if (counted_bars < 0) return(-1);
   if (counted_bars > 0) counted_bars--;
   barsLookback = barsLookback - counted_bars;
   scanner();
   return(rates_total);
}

The PinBar and Inside Candle indicators have a few extra input parameters. These parameters are:

//--- PinBar indicator
//--- extra Input variables
input double pMultiplier   = 3;           // Protrusion Multiplier. Default is 3
input double bMultiplier   = 3.5;         // Body Multiplier. Default is 3.5
input double hMultiplier   = 2.5;         // Head Multiplier. Default is 2.5

//--- Inside Candle indicator
//--- extra Input variables
input double range = 0; // Inside Candle Size
 
user3822: When the indicator launches, or when you switch timeframes on the chart, there's a 2 second delay.

I've done some research into this, and I read that it could be if the indicator code is not optimized or iCustom has some wrong input parameters that are causing the issue.

This calls scanner every single tick.
   int counted_bars = IndicatorCounted();
   if (counted_bars < 0) return(-1);
   if (counted_bars > 0) counted_bars--;
   barsLookback = barsLookback - counted_bars;
   scanner();
Scanner only looks at bar one. Only call it on a new bar. See How to do your lookbacks correctly.
   #define LAST 1  // Normally zero
   #define BEGIN 1 // Normally Bars - 1
   for(int iBar = BEGIN-prev_calculated; iBar >= LAST; --iBar){
         scanner();
   }
   #define REDRAW_BAR_LAST false    // Redraw Bar LAST.
   return   rates_total - REDRAW_BAR_LAST - LAST;
 
whroeder1:
This calls scanner every single tick.
Scanner only looks at bar one. Only call it on a new bar. See How to do your lookbacks correctly.
Thanks, I'll look into it and get back if I have any other questions.