Can't Plot Arrows

 

Hello, this code should plot some arrows but it doesn't. It only prints the correct values in the journal, please can you help me?

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue


// Inputs
input int max_bars    = 1000;
input int       iPeriods  = 34;

// Buffers
double DynR[];
double DynS[];

int daily = 1440;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,DynR,INDICATOR_DATA);
   SetIndexBuffer(1,DynS,INDICATOR_DATA);
   
   PlotIndexSetInteger(0,PLOT_ARROW,119);
   PlotIndexSetInteger(1,PLOT_ARROW,119);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ObDeleteObjectsByPrefix(string Prefix)
  {
   int L = StringLen(Prefix);
   int i = 0;
   while(i < ObjectsTotal(i))
     {
      string ObjName = ObjectName(i,0);
      if(StringSubstr(ObjName, 0, L) != Prefix)
        {
         i++;
        }
      ObjectDelete(0,ObjName);
     }
  }

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| 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[])
  {
//---
   datetime today=__DATE__;

   int counted_bars= int(prev_calculated);
   if(counted_bars < 0)
      return(-1);
//----
   int limit=iBars(_Symbol,_Period)-counted_bars;

   DynR[0] = iClose(_Symbol,_Period,0);
   DynS[0] = iClose(_Symbol,_Period,0);


   double nHH, nLL;

 int processBars=MathMin(limit, max_bars);
   int i = processBars-3;

   while (i >= 0)
      
     {
      Print(i);
 
        nHH = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH,iPeriods ,i));;
        nLL = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods, i));
        DynR[i] =   nHH;
        DynS[i] =   nLL;
        Print("DynR= ", DynR[i]);
        
         if((DynR[i] != iHigh(_Symbol,_Period,0)) && (DynR[i] < DynR[i+1]) && (DynR[i+1] != 0))
            DynR[i] = DynR[i+1];

         if((DynS[i] != iLow(_Symbol,_Period,0)) && (DynS[i] > DynS[i+1]) && (DynS[i+1] != 0))
            DynS[i] = DynS[i+1];
         //--- return value of prev_calculated for next call
        
         i--;

        }

     ChartRedraw();
     return(rates_total);
}

//+------------------------------------------------------------------+
 
Leandro Norcini:

Hello, this code should plot some arrows but it doesn't. It only prints the correct values in the journal, please can you help me?

the iHigh , iClose etc index (i) is from right to left , while as is , your buffers are from left to right

try filling them with value j

j=rates_total-i-1;
 
Lorentzos Roussos #:

the iHigh , iClose etc index (i) is from right to left , while as is , your buffers are from left to right

try filling them with value j

Thank you Lorentzos,

it makes sense and I tried but without success. Do you think that using CreateObject would work better? I'm sorry I'm still a newbie. Thank you much.

 
Leandro Norcini #:

Thank you Lorentzos,

it makes sense and I tried but without success. Do you think that using CreateObject would work better? I'm sorry I'm still a newbie. Thank you much.

try this 

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_color1 Red
#property indicator_color2 Blue


// Inputs
input int max_bars    = 1000;
input int       iPeriods  = 34;

// Buffers
double DynR[];
double DynS[];

int daily = 1440;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,DynR,INDICATOR_DATA);
   SetIndexBuffer(1,DynS,INDICATOR_DATA);
   
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ObDeleteObjectsByPrefix(string Prefix)
  {
   int L = StringLen(Prefix);
   int i = 0;
   while(i < ObjectsTotal(i))
     {
      string ObjName = ObjectName(i,0);
      if(StringSubstr(ObjName, 0, L) != Prefix)
        {
         i++;
        }
      ObjectDelete(0,ObjName);
     }
  }

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| 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 j=prev_calculated;j<rates_total;j++){    
      int i=(rates_total-1)-j;
        DynR[j] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH,iPeriods ,i));
        DynS[j] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods, i));      
        i--;
   }
return(rates_total);
}

Also you have to set the plot draw type as arrow first , and , then pass the arrow codes

https://www.mql5.com/en/docs/customind/plotindexsetinteger

Documentation on MQL5: Custom Indicators / PlotIndexSetInteger
Documentation on MQL5: Custom Indicators / PlotIndexSetInteger
  • www.mql5.com
PlotIndexSetInteger - Custom Indicators - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

this for loop could work as well

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 lastBar = rates_total-1;
     
   for(int i=rates_total-1;i>prev_calculated;i--){  
   
        DynR[i] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH,iPeriods,(lastBar - i)));
        DynS[i] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods,(lastBar - i))); 
   }
   
   return(rates_total);
}
 

You miss properties for the arrow buffers

#property indicator_label1  "Up"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrGold
#property indicator_width1  1

#property indicator_label2  "Down"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrGold
#property indicator_width2  1

I wouldn't advise using ObjectCreate because then you won't be able to make an iCustom implementation for your indicator as there will be objects instead of buffers.

I'm not sure what kind of criteria you wanted with the arrows, but I would use two separate buffers for the arrows, so 4 buffers in total and two buffers for plotting the arrows

double DynR[];
double DynS[];
double arr_buf_up[];
double arr_buf_down[];

Example:

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 2
#property indicator_color1 clrGold
#property indicator_color2 clrGold

#property indicator_label1  "Up"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrGold
#property indicator_width1  1

#property indicator_label2  "Down"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrGold
#property indicator_width2  1

// Inputs
input int max_bars    = 1000;
input int  iPeriods  = 34;

// Buffers
double DynR[];
double DynS[];
double arr_buf_up[];
double arr_buf_down[];

int daily = 1440;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, arr_buf_up, INDICATOR_DATA);
   SetIndexBuffer(1, arr_buf_down, INDICATOR_DATA);  
   SetIndexBuffer(2,DynR,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,DynS,INDICATOR_CALCULATIONS);
   
   PlotIndexSetInteger(0,PLOT_ARROW,238);
   PlotIndexSetInteger(1,PLOT_ARROW,236);     
   PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,20);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-20);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ObDeleteObjectsByPrefix(string Prefix)
  {
   int L = StringLen(Prefix);
   int i = 0;
   while(i < ObjectsTotal(i))
     {
      string ObjName = ObjectName(i,0);
      if(StringSubstr(ObjName, 0, L) != Prefix)
        {
         i++;
        }
      ObjectDelete(0,ObjName);
     }
  }

//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| 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 lastBar = rates_total-1;
   

   for(int i=rates_total-1;i>rates_total-max_bars;i--){  
   
        arr_buf_up[i] = 0; 
        arr_buf_down[i] = 0;
        
        DynR[i] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH,iPeriods,(lastBar - i)));
        DynS[i] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods,(lastBar - i))); 
     
        if((i+1)<rates_total-1 && DynR[i] > DynR[i-1] && DynR[i] == DynR[i+1]){

            arr_buf_down[i] = high[i]; 
        }
      
        
        if((i+1)<rates_total-1 && DynS[i] < DynS[i-1] && DynS[i] == DynS[i+1]){
   
            arr_buf_up[i] = low[i];
        }

   }
   
   return(rates_total);
}
 
Gamuchirai Zororo Ndawana #:
Why are arrows notoriously tricky to work with?
It all depends on what logic you apply to them. iHighest and iLowest makes me think lines not arrows as more logic is needed to stop the arrow painting on every bar. I only use arrows if there's a signal that would only occur at irregular conditions.
Take a look here where I have two very stable scripts using arrows, the first version uses ObjectCreate, the second version uses arrow buffers

 

Here's a better code with optimization, I made as an example with your script, arrows to appear consistently at the breakouts and pullbacks (signaling at highest and lowest)


Files:
 
Lorentzos Roussos #:

try this 

Also you have to set the plot draw type as arrow first , and , then pass the arrow codes

https://www.mql5.com/en/docs/customind/plotindexsetinteger

Thank you so much, it perfectly works now.
 
I updated the code with the original logic:

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_color1 Red
#property indicator_color2 Blue

// Inputs
input int max_bars    = 1000;
input int       iPeriods  = 34;

// Buffers
double DynR[];
double DynS[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,DynR,INDICATOR_DATA);
   SetIndexBuffer(1,DynS,INDICATOR_DATA);
   
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ARROW);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_ARROW);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.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[])
  {
   for(int j=prev_calculated;j<rates_total;j++){    
      int i=(rates_total-1)-j;
        DynR[j] = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH,iPeriods ,i));
        DynS[j] = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, iPeriods, i));     
        
        if ((DynR[j] != high[j]) && (DynR[j] < DynR[j-1]) &&  ( DynR[j-1] != 0 ))     
           DynR[j] = DynR[j-1]; 

        if (( DynS[j] != low[j]) && (DynS[j] > DynS[j-1] ) && ( DynS[j-1] != 0 )) 
           DynS[j] = DynS[j-1];  
        i--;              
   }
return(rates_total);
}
 
Conor Mcnamara #:

You miss properties for the arrow buffers

I wouldn't advise using ObjectCreate because then you won't be able to make an iCustom implementation for your indicator as there will be objects instead of buffers.

I'm not sure what kind of criteria you wanted with the arrows, but I would use two separate buffers for the arrows, so 4 buffers in total and two buffers for plotting the arrows

Example:

Thank you, yes I was totally lost on buffers. Now I'm getting it a bit more but I have to go deeper.
I was suspecting something like that on ObjectCreate, thanks for explaining.