How to change buffer color of indicator in OBJ_CHART

 

When creating an embedded chart...

bool EmbeddedChart::Create() {
   ResetLastError();
   
   if(!ObjectCreate(_chartID,_name,OBJ_CHART,0,0,0)) {
      printf( "[%s ERROR]: failed to create the embedded chart object! Error code = %i", __FUNCTION__, GetLastError() );
      _embeddedChartID = -1;
      return false;
   }
      
   _embeddedChartID =  ObjectGetInteger(_chartID, _name, OBJPROP_CHART_ID);
   
   return true;
}

Then adding an indicator to it, in this case a simple MA

   _embeddedChartMaHandle = iMA(ChartSymbol(_embeddedChartID), PERIOD_H8, 20, 0, MODE_SMA, PRICE_CLOSE);

   ResetLastError();
   
   if( !ChartIndicatorAdd(_embeddedChartID, 0, _embeddedChartMaHandle) ) { 
      printf("Couldn't Add MA to embedded chart | Error = %d", GetLastError() );
   }

It attaches fine, but it is colored red.

How can we programmically change the buffer draw color?

Embedded chart object with ma

Documentation on MQL5: Constants, Enumerations and Structures / Indicator Constants / Drawing Styles
Documentation on MQL5: Constants, Enumerations and Structures / Indicator Constants / Drawing Styles
  • www.mql5.com
When creating a custom indicator, you can specify one of 18 types of graphical plotting (as displayed in the main chart window or a chart subwindow), whose values are specified in the ENUM_DRAW_TYPE enumeration. Depending on the drawing style, you may need one to four value buffers (marked as INDICATOR_DATA). If a style admits dynamic...
 

You could use a modified or custom indicator that has a color value as input parameter, and then you can do a iCustom call to that indicator specifying the color in the input parmeters.

For example:

//+------------------------------------------------------------------+
//|                                        Custom Moving Average.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
//#property indicator_color1  Red > We made this property a input parameter.
//--- input parameters
input int            InpMAPeriod = 13;         // Period
input int            InpMAShift  = 0;          // Shift
input ENUM_MA_METHOD InpMAMethod = MODE_SMMA;  // Method
input color          InpColor    = clrGold;    // Color
//--- indicator buffers
double               ExtLineBuffer[];
//+------------------------------------------------------------------+
//| simple moving average                                            |
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])
  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)// first calculation
     {
      limit=InpMAPeriod+begin;
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
         firstValue+=price[i];
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
//---
  }
//+------------------------------------------------------------------+
//|  exponential moving average                                      |
//+------------------------------------------------------------------+
void CalculateEMA(int rates_total,int prev_calculated,int begin,const double &price[])
  {
   int    i,limit;
   double SmoothFactor=2.0/(1.0+InpMAPeriod);
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      limit=InpMAPeriod+begin;
      ExtLineBuffer[begin]=price[begin];
      for(i=begin+1;i<limit;i++)
         ExtLineBuffer[i]=price[i]*SmoothFactor+ExtLineBuffer[i-1]*(1.0-SmoothFactor);
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)
      ExtLineBuffer[i]=price[i]*SmoothFactor+ExtLineBuffer[i-1]*(1.0-SmoothFactor);
//---
  }
//+------------------------------------------------------------------+
//|  linear weighted moving average                                  |
//+------------------------------------------------------------------+
void CalculateLWMA(int rates_total,int prev_calculated,int begin,const double &price[])
  {
   int        i,limit;
   static int weightsum;
   double     sum;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      weightsum=0;
      limit=InpMAPeriod+begin;
      //--- set empty value for first limit bars
      for(i=0;i<limit;i++) ExtLineBuffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
        {
         int k=i-begin+1;
         weightsum+=k;
         firstValue+=k*price[i];
        }
      firstValue/=(double)weightsum;
      ExtLineBuffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)
     {
      sum=0;
      for(int j=0;j<InpMAPeriod;j++) sum+=(InpMAPeriod-j)*price[i-j];
      ExtLineBuffer[i]=sum/weightsum;
     }
//---
  }
//+------------------------------------------------------------------+
//|  smoothed moving average                                         |
//+------------------------------------------------------------------+
void CalculateSmoothedMA(int rates_total,int prev_calculated,int begin,const double &price[])
  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
     {
      limit=InpMAPeriod+begin;
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)
         firstValue+=price[i];
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)
      ExtLineBuffer[i]=(ExtLineBuffer[i-1]*(InpMAPeriod-1)+price[i])/InpMAPeriod;
//---
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtLineBuffer,INDICATOR_DATA);
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpMAPeriod);
//---- line shifts when drawing
   PlotIndexSetInteger(0,PLOT_SHIFT,InpMAShift);
//--- name for DataWindow
   string short_name="unknown ma";
   switch(InpMAMethod)
     {
      case MODE_EMA :  short_name="EMA";  break;
      case MODE_LWMA : short_name="LWMA"; break;
      case MODE_SMA :  short_name="SMA";  break;
      case MODE_SMMA : short_name="SMMA"; break;
     }
   IndicatorSetString(INDICATOR_SHORTNAME,short_name+"("+string(InpMAPeriod)+")");
//---- sets drawing line empty value--
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- Set the color as the PLOT_LINE_COLOR property
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,InpColor);   
//---- initialization done
  }
//+------------------------------------------------------------------+
//|  Moving Average                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//--- check for bars count
   if(rates_total<InpMAPeriod-1+begin)
      return(0);// not enough bars for calculation
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
      ArrayInitialize(ExtLineBuffer,0);
//--- sets first bar from what index will be draw
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpMAPeriod-1+begin);

//--- calculation
   switch(InpMAMethod)
     {
      case MODE_EMA:  CalculateEMA(rates_total,prev_calculated,begin,price);        break;
      case MODE_LWMA: CalculateLWMA(rates_total,prev_calculated,begin,price);       break;
      case MODE_SMMA: CalculateSmoothedMA(rates_total,prev_calculated,begin,price); break;
      case MODE_SMA:  CalculateSimpleMA(rates_total,prev_calculated,begin,price);   break;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Then you can use a iCustom call like so:

int _embeddedChartMaHandle = iCustom(Symbol(),PERIOD_CURRENT,"iMAC.ex5",13,0,MODE_SMMA,clrLime);

ResetLastError();
   
   if( !ChartIndicatorAdd(_embeddedChartID, 0, _embeddedChartMaHandle) ) { 
      printf("Couldn't Add MA to embedded chart | Error = %d", GetLastError() );
   }

So you can set the color as a color parameter in the call.


Step on New Rails: Custom Indicators in MQL5
Step on New Rails: Custom Indicators in MQL5
  • www.mql5.com
Finally we've got an opportunity to try the new trade terminal - MetaTrader 5 . No doubt, it is noteworthy and has many new features as compared to its predecessor. The important advantages of this platform among others are: Essentially modified language allowing now to use the object-oriented programming, still allowing to use the rich...
 

Thanks for this, your code works.

However I have my own moving average pack, which is multibuffered and uses OnTimer() internally to make sure nothing happens until all data is calculated before drawing... (which I though was std way for MT5).

If I try to attach it via iCustom, nothing draws on the embedded chart, and there are no errors on...

_embeddedChartMaHandle = iCustom(ChartSymbol(_chartID), _embeddedChartTf, "::res\\MovingAveragePack.ex5", 20, MA_SIMPLE, AUTO, false);

or

if( !ChartIndicatorAdd(_embeddedChartID, 0, _embeddedChartMaHandle) ) { 
      printf("Couldn't Add MA to embedded chart | Error = %d", GetLastError() );
   }


So I wonder if there is a limitation to what you can add to embedded charts. Your example uses this signature...

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

Where as mine uses...

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[]
) 


I wouldn't have thought this would be a problem. Maybe the chart object can only handle single buffer indicators?

Reason: