Colour-changing lines and histograms in MQL5 indicators
Convert Pine plot(color=cond ? green : red) into DRAW_COLOR_LINE and DRAW_COLOR_HISTOGRAM with a colour index buffer.
The Pine Script original
In Pine you pass a colour expression to plot and it changes per bar:
Pine Script
//@version=5
indicator("Colored MA", overlay=true)
ma = ta.ema(close, 20)
plot(ma, color = ma > ma[1] ? color.green : color.red, linewidth=2)How MQL5 colours a plot
A colour plot needs two buffers: the values (INDICATOR_DATA) and a colour index (INDICATOR_COLOR_INDEX). The colour index buffer holds 0, 1, 2... pointing into the colour list declared with indicator_color1. Both buffers must be double arrays and the counts in indicator_buffers and indicator_plots must match.
MQL5
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 1
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 clrLimeGreen, clrRed
#property indicator_width1 2
double MaBuf[], ClrBuf[];
int hMa;
int OnInit(){
SetIndexBuffer(0, MaBuf, INDICATOR_DATA);
SetIndexBuffer(1, ClrBuf, INDICATOR_COLOR_INDEX);
ArraySetAsSeries(MaBuf, true); ArraySetAsSeries(ClrBuf, true);
hMa = iMA(_Symbol, _Period, 20, 0, MODE_EMA, PRICE_CLOSE);
return hMa == INVALID_HANDLE ? INIT_FAILED : INIT_SUCCEEDED;
}
void OnDeinit(const int r){ IndicatorRelease(hMa); }
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]){
if(BarsCalculated(hMa) < rates_total) return 0;
int toCopy = (prev_calculated == 0) ? rates_total : rates_total - prev_calculated + 1;
if(CopyBuffer(hMa, 0, 0, toCopy, MaBuf) != toCopy) return 0;
int limit = MathMin(toCopy, rates_total - 1) - 1;
for(int i = limit; i >= 0; i--)
ClrBuf[i] = (MaBuf[i] > MaBuf[i + 1]) ? 0 : 1;
return rates_total;
}Histograms and several plots
DRAW_COLOR_HISTOGRAM works the same way (value buffer plus colour index). With several plots, buffers are assigned in order: plot 1 takes buffers 0 and 1, plot 2 starts at buffer 2. Getting this order wrong is the most common reason a converted indicator shows an empty window or the wrong line.
Calculation-only arrays that are not drawn should be registered with INDICATOR_CALCULATIONS after all drawn buffers, and still counted in indicator_buffers.