Indicator buffers get unwanted values :( - page 2

To add comments, please log in or register
Pasi Hakamaki
24250
Pasi Hakamaki  
RaptorUK:

Hope you don't mind,  I have taken the opportunity to learn a little about mql5 using your code . . .  I have learned that a lot of things are different compared to mql4 and that not having a Book, as there is for mql4, is a pain in the behind.

This is where I got to,  it seems to be OK in terms of changing timeframes and it will update the bar to the right of the currently forming bar when a new bar is formed.  It does not update the currently forming bar, not sure if you wanted it to or not. 

 

 

Not at all RaptorUK :) I am learning from your code too :) Very nice code and it is working perfectly. It is still a little bit weird that we must clear the values as it is not stated anywhere in the references, at least I have not come a cross anything like that...

Br, Candles

EDIT: I will take my word back see bold part of code below taken from references. The buffers are indeed initialized with 0.0 prior to filling them with values:

//+------------------------------------------------------------------+
//|                                           DRAW_COLOR_CANDLES.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
 
#property description "An indicator to demonstrate DRAW_COLOR_CANDLES."
#property description "It draws candlesticks of a selected symbol in a separate window"
#property description " "
#property description "The color and width of candlesticks, as well as the symbol are changed"
#property description "randomly every N ticks"
 
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
//--- plot ColorCandles
#property indicator_label1  "ColorCandles"
#property indicator_type1   DRAW_COLOR_CANDLES
//--- Define 8 colors for coloring candlesticks (they are stored in the special array)
#property indicator_color1  clrRed,clrBlue,clrGreen,clrYellow,clrMagenta,clrCyan,clrLime,clrOrange
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
 
//--- input parameters
input int      N=5;              // The number of ticks to change the type
input int      bars=500;         // The number of candlesticks to show
input bool     messages=false;   // Show messages in the "Expert Advisors" log
//--- Indicator buffers
double         ColorCandlesBuffer1[];
double         ColorCandlesBuffer2[];
double         ColorCandlesBuffer3[];
double         ColorCandlesBuffer4[];
double         ColorCandlesColors[];
int            candles_colors;
//--- Symbol name
string symbol;
//--- An array for storing colors contains 14 elements
color colors[]=
  {
   clrRed,clrBlue,clrGreen,clrChocolate,clrMagenta,clrDodgerBlue,clrGoldenrod,
   clrIndigo,clrLightBlue,clrAliceBlue,clrMoccasin,clrMagenta,clrCyan,clrMediumPurple
  };
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- If bars is very small - complete the work ahead of time
   if(bars<50)
     {
      Comment("Please specify a larger number of bars! The operation of the indicator has been terminated");
      return(-1);
     }
//--- indicator buffers mapping
   SetIndexBuffer(0,ColorCandlesBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,ColorCandlesBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ColorCandlesBuffer3,INDICATOR_DATA);
   SetIndexBuffer(3,ColorCandlesBuffer4,INDICATOR_DATA);
   SetIndexBuffer(4,ColorCandlesColors,INDICATOR_COLOR_INDEX);
//--- An empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- The name of the symbol, for which the bars are drawn
   symbol=_Symbol;
//--- Set the display of the symbol
   PlotIndexSetString(0,PLOT_LABEL,symbol+" Open;"+symbol+" High;"+symbol+" Low;"+symbol+" Close");
   IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_COLOR_CANDLES("+symbol+")");
//---- The number of colors to color candlesticks
   candles_colors=8;     //  see. a comment to the #property indicator_color1 property
//--- 
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
   static int ticks=INT_MAX-100;
//--- Count ticks to change the style and color
   ticks++;
//--- If a sufficient number of ticks has been accumulated
   if(ticks>=N)
     {
      //--- Select a new symbol from the Market watch window
      symbol=GetRandomSymbolName();
      //--- Change the form
      ChangeLineAppearance();
      //--- Change the colors used to draw the candlesticks
      ChangeColors(colors,candles_colors);
 
      int tries=0;
      //--- Make 5 attempts to fill in the buffers of plot1 with the prices from symbol
      while(!CopyFromSymbolToBuffers(symbol,rates_total,0,
            ColorCandlesBuffer1,ColorCandlesBuffer2,ColorCandlesBuffer3,
            ColorCandlesBuffer4,ColorCandlesColors,candles_colors)
            && tries<5)
        {
         //--- A counter of calls of the CopyFromSymbolToBuffers() function
         tries++;
        }
      //--- Reset the counter of ticks to zero
      ticks=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Fills in the specified candlestick                                    |
//+------------------------------------------------------------------+
bool CopyFromSymbolToBuffers(string name,
                             int total,
                             int plot_index,
                             double &buff1[],
                             double &buff2[],
                             double &buff3[],
                             double &buff4[],
                             double &col_buffer[],
                             int    cndl_colors
                             )
  {
//--- In the rates[] array, we will copy Open, High, Low and Close
   MqlRates rates[];
//--- The counter of attempts
   int attempts=0;
//--- How much has been copied
   int copied=0;
//--- Make 25 attempts to get a timeseries on the desired symbol
   while(attempts<25 && (copied=CopyRates(name,_Period,0,bars,rates))<0)
     {
      Sleep(100);
      attempts++;
      if(messages) PrintFormat("%s CopyRates(%s) attempts=%d",__FUNCTION__,name,attempts);
     }
//--- If failed to copy a sufficient number of bars
   if(copied!=bars)
     {
      //--- Form a message string
      string comm=StringFormat("For the symbol %s, managed to receive only %d bars of %d requested ones",
                               name,
                               copied,
                               bars
                               );
      //--- Show a message in a comment in the main chart window
      Comment(comm);
      //--- Show the message
      if(messages) Print(comm);
      return(false);
     }
   else
     {
      //--- Set the display of the symbol 
      PlotIndexSetString(plot_index,PLOT_LABEL,name+" Open;"+name+" High;"+name+" Low;"+name+" Close");
      IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_COLOR_CANDLES("+symbol+")");
     }
//--- !!!!!!!Initialize buffers with empty values!!!!!
   ArrayInitialize(buff1,0.0);
   ArrayInitialize(buff2,0.0);
   ArrayInitialize(buff3,0.0);
   ArrayInitialize(buff4,0.0);
//--- On each tick copy prices to buffers
   for(int i=0;i<copied;i++)
     {
      //--- Calculate the appropriate index for the buffers
      int buffer_index=total-copied+i;
      //--- Write the prices to the buffers
      buff1[buffer_index]=rates[i].open;
      buff2[buffer_index]=rates[i].high;
      buff3[buffer_index]=rates[i].low;
      buff4[buffer_index]=rates[i].close;
      //--- Set the candlestick color
      int color_index=i%cndl_colors;
      col_buffer[buffer_index]=color_index;
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| Randomly returns a symbol from the Market Watch              |
//+------------------------------------------------------------------+
string GetRandomSymbolName()
  {
//--- The number of symbols shown in the Market watch window
   int symbols=SymbolsTotal(true);
//--- The position of a symbol in the list - a random number from 0 to symbols
   int number=MathRand()%symbols;
//--- Return the name of a symbol at the specified position
   return SymbolName(number,true);
  }
//+------------------------------------------------------------------+
//|  Changes the color of the candlestick segments
//+------------------------------------------------------------------+
void  ChangeColors(color  &cols[],int plot_colors)
  {
//--- The number of colors
   int size=ArraySize(cols);
//--- 
   string comm=ChartGetString(0,CHART_COMMENT)+"\r\n\r\n";
 
//--- For each color index define a new color randomly
   for(int plot_color_ind=0;plot_color_ind<plot_colors;plot_color_ind++)
     {
      //--- Get a random value
      int number=MathRand();
      //--- Get an index in the col[] array as a remainder of the integer devision
      int i=number%size;
      //--- Set the color for each index as the property PLOT_LINE_COLOR
      PlotIndexSetInteger(0,                    //  The number of a graphical style
                          PLOT_LINE_COLOR,      //  Property identifier
                          plot_color_ind,       //  The index of the color, where we write the color
                          cols[i]);             //  A new color
      //--- Write the colors
      comm=comm+StringFormat("CandleColorIndex[%d]=%s \r\n",plot_color_ind,ColorToString(cols[i],true));
      ChartSetString(0,CHART_COMMENT,comm);
     }
//---
  }
//+------------------------------------------------------------------+
//| Changes the appearance of candlesticks                                |
//+------------------------------------------------------------------+
void ChangeLineAppearance()
  {
//--- A string for the formation of information about the candlestick properties
   string comm="";
//--- Write the symbol name
   comm="\r\n"+symbol+comm;
//--- Show the information on the chart using a comment
   Comment(comm);
  }
Pasi Hakamaki
24250
Pasi Hakamaki  

... And thus the below code also works flawlessly.... I think:

EDIT: Code not working after new bar is completed.

//+------------------------------------------------------------------+
//|                                                COLOR_CANDLES.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots 1
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_label1 "Open;High;Low;Close"
#property indicator_width1 3

bool init=false;
double o[],h[],l[],c[],clr[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,o,INDICATOR_DATA);
   SetIndexBuffer(1,h,INDICATOR_DATA);
   SetIndexBuffer(2,l,INDICATOR_DATA);
   SetIndexBuffer(3,c,INDICATOR_DATA);
   SetIndexBuffer(4,clr,INDICATOR_COLOR_INDEX);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);

   PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,1);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Blue);

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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 FirstBar=0;
//---
   if(prev_calculated==0) FirstBar=0;
   if(prev_calculated!=0) FirstBar=prev_calculated-1;

   if(init==false)
     {
      //--- Initialize buffers with empty values
      ArrayInitialize(o,0.0);
      ArrayInitialize(h,0.0);
      ArrayInitialize(l,0.0);
      ArrayInitialize(c,0.0);
      init=true;
     }
//---
   for(int i=FirstBar;i<rates_total-1;i++)
     {
      if(init==true)
        {
         o[i]=0.0; h[i]=0.0; l[i]=0.0; c[i]=0.0;
        }
      if(close[i]>open[i])
        {
         o[i]=open[i];
         h[i]=high[i];
         l[i]=low[i];
         c[i]=close[i];
         clr[i]=0;
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


But being the obsessive person I am  I would still like to know why indicator buffer arrays can initially have so weird values like in the below pic although it is probably irrelevant:




Simon Gniadkowski
17730
Simon Gniadkowski  
Candles:

... And thus the below code also works flawlessly.... I think:


But being the obsessive person I am  I would still like to know why indicator buffer arrays can initially have so weird values like in the below pic although it is probably irrelevant:

An array is just a bunch of memory locations that hold the values in the array. When the memory is allocated for the array is it cleared/zeroed ?  I don't know if it is or isn't,  maybe it isn't,  so that could explain the strange values.
Pasi Hakamaki
24250
Pasi Hakamaki  
RaptorUK:
An array is just a bunch of memory locations that hold the values in the array. When the memory is allocated for the array is it cleared/zeroed ?  I don't know if it is or isn't,  maybe it isn't,  so that could explain the strange values.
Yeah, that its what I think as well. Maybe it is just the number of the memory cell or something...
Simon Gniadkowski
17730
Simon Gniadkowski  
Candles:

... And thus the below code also works flawlessly.... I think:

You may still get issues with the currently forming bar,  I think.  The four arrays you are using are dynamic arrays,  they are not defined with a pre-set size and are not resized using ArrayResize(),  they grow as needed and new memory is allocated when needed. Using ArrayInitialise() will,  I assume,  initialise the array elements that exist at the time . . .  what about new elements that get added as new bars are added to the chart ?

This code also sets the Array values to 0.0

      if(init==true)
        {
         o[i]=0.0; h[i]=0.0; l[i]=0.0; c[i]=0.0;
        }

but what it doesn't do, because of the limit of the for loop,  is clear the array values for the currently forming bar.  That position is rates_total-1  the for loop exits when i == rates_total-1  this was why I added

o[i] = 0.0; h[i] = 0.0; l[i] = 0.0; c[i] = 0.0;  // clear values for currently forming bar

 immediately after the loop.

Pasi Hakamaki
24250
Pasi Hakamaki  
RaptorUK:

You may still get issues with the currently forming bar,  I think.  The four arrays you are using are dynamic arrays,  they are not defined with a pre-set size and are not resized using ArrayResize(),  they grow as needed and new memory is allocated when needed. Using ArrayInitialise() will,  I assume,  initialise the array elements that exist at the time . . .  what about new elements that get added as new bars are added to the chart ?

This code also sets the Array values to 0.0

but what it doesn't do, because of the limit of the for loop,  is clear the array values for the currently forming bar.  That position is rates_total-1  the for loop exits when i == rates_total-1  this was why I added

 immediately after the loop.

I believe you are right. I tested my previous code on the M1 chart and indeed problems occur when new bar is completed and refresh clicked. The underlined part is very well put I get it now :) ArrayInitialize() no good as the arrays grow in time and thus initialization is performed only for the array of the current size.
12
To add comments, please log in or register