Думаю этот пример "DRAW_COLOR_LINE Lite.mq5" поможет понять как работают цветные буферы:
//| DRAW_COLOR_LINE Lite.mq5 |
//| Copyright 2016, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "An indicator to demonstrate DRAW_COLOR_LINE"
#property description "It draws a line on Close price in colored pieces of 20 bars each"
#property description "The width, style and color of the line parts are changed randomly"
#property description "every N ticks"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 1
//--- plot ColorLine
#property indicator_label1 "ColorLine"
#property indicator_type1 DRAW_COLOR_LINE
//--- Define 5 colors for coloring each bar (they are stored in the special array)
#property indicator_color1 clrBlue,clrRed // (Up to 64 colors can be specified)
#property indicator_style1 STYLE_SOLID
#property indicator_width1 3
//--- A buffer for plotting
double ColorLineBuffer[];
//--- A buffer for storing the line color on each bar
double ColorLineColors[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Binding an array and an indicator buffer
SetIndexBuffer(0,ColorLineBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ColorLineColors,INDICATOR_COLOR_INDEX);
//---
ArraySetAsSeries(ColorLineBuffer,true);
ArraySetAsSeries(ColorLineColors,true);
//---
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[])
{
ArraySetAsSeries(close,true);
if(prev_calculated==0)
{
for(int i=0;i<rates_total;i++)
ColorLineBuffer[i]=close[i];
}
//--- Block for calculating indicator values
for(int i=0;i<10;i++)
{
//--- Write the indicator value into the buffer
ColorLineBuffer[i]=close[i];
//--- For this bar, the line will have the color with the index color_index
if(ColorLineBuffer[i]>ColorLineBuffer[i+1])
ColorLineColors[i]=0;
else
ColorLineColors[i]=1;
}
//--- Return the prev_calculated value for the next call of the function
return(rates_total);
}
//+------------------------------------------------------------------+
Цикл
взят просто так, просто захотелось мне на каждом тике перезаписывать последние 10 баров :)
Vladimir Karputov:
Спасибо за помощь.
В том скрипте не хватало
Исправил. Сейчас вроде правильно работает и пошустрее, чем единственный подобный индикатор под МТ5.
https://www.mql5.com/en/code/1299
В этом индикаторе бывает такое, что рисуется 5 боксов по 100 пипс = 500 пипс, хотя цена прошла не больше 150.
Мой вроде правильней считает, тренды более плавные.Тем не менее, было бы неплохо, если бы кто выложил в кодобазу или проверил корректность написаного.
Интерес вызвала эта тема
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Классический теханализ больше не работает. А что работает, может квантовый?
Sergey Pavlov, 2009.11.12 19:39
Если Вы говорите о том как построить цифровой фильтр или провести спектральный или квантовый анализ. То на мой взгляд, Вы ищете какое-то супер-сложное решение. Скорее всего что и найдёте (чуствуется у вас крепкая хватка). Но о том, что вы говорили, уменя самое смутное представление. Цифровой приёмник (дешифратор) или анализатор, как хотите называйте, у меня занимает 10 строк внутри советника. Ну как в таком коротком коде можно вместить всю высшую математику?
===
Можно я Вам подскажу? Выкиньте из головы цену и время, а оставьте только сигналы ТС и результаты сделок по этим сигналам. Вы же программисты. Выключите аналоговое, а включите своё цифровое мышление. Битовые операции наверняка знаете.
===
Может найдёте подсказку в прикреплённом файле. Примерно так я получаю конечный результат.
Не совсем понятно, как можно получить вторую цветную линию в одном индикаторе. Для примера, пытаюсь продублировать ценовые серии High и Low.
Для начала беру одну цветную линию серии High. Тут все нормально.
#property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 1 double bufHigh[]; double highColor[]; //------------------------------------------------------------------ void OnInit() { SetIndexBuffer(0,bufHigh); PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_COLOR_LINE); PlotIndexSetString(0, PLOT_LABEL, "High"); SetIndexBuffer(1, highColor, INDICATOR_COLOR_INDEX); PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2); PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrDeepSkyBlue); //Нулевой индекс -> Синий PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrTomato); //Первый индекс -> Оранжевый } //------------------------------------------------------------------ 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 limit = rates_total - prev_calculated; // как правило, выдает 0-й или 1-й индекс свечи для расчета for(int i = limit-1; i >= 0; --i) { bufHigh[i] = high[i]; highColor[i] = (i%2 == 0) ? 0 : 1; } return rates_total; }
Но вот с добавлением второй линии по серии Low возникли проблемы с отрисовкой.
Добавил второй буфер bufLow[] и для него отдельный буфер для цвета. Ниже в коде таким образом прописал в секцию OnInit(). В «Окне данных» значения есть, а отрисовки не видно.
Помогите прояснить ситуацию.
#property indicator_chart_window #property indicator_buffers 4 #property indicator_plots 4 double bufHigh[]; double highColor[]; double bufLow[]; double lowColor[]; //------------------------------------------------------------------ void OnInit() { SetIndexBuffer(0,bufHigh); PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_COLOR_LINE); PlotIndexSetString(0, PLOT_LABEL, "High"); SetIndexBuffer(1, highColor, INDICATOR_COLOR_INDEX); PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2); PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrDeepSkyBlue); //Нулевой индекс -> Синий PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrTomato); //Первый индекс -> Оранжевый // ---- добавление Low линии SetIndexBuffer(2,bufLow); PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_COLOR_LINE); PlotIndexSetString(2, PLOT_LABEL, "Low"); SetIndexBuffer(3, lowColor, INDICATOR_COLOR_INDEX); PlotIndexSetInteger(2,PLOT_COLOR_INDEXES,2); PlotIndexSetInteger(2,PLOT_LINE_COLOR,0,clrBlue); PlotIndexSetInteger(2,PLOT_LINE_COLOR,1,clrGold); } //------------------------------------------------------------------ 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 limit = rates_total - prev_calculated; for(int i = limit-1; i >= 0; --i) { bufHigh[i] = high[i]; highColor[i] = (i%2 == 0) ? 0 : 1; // на четных индексах цвет из индекса 0, на нечетных - из индекса 1 bufLow[i] = low[i]; lowColor[i] = (i%2 == 0) ? 0 : 1; // на четных индексах цвет из индекса 0, на нечетных - из индекса 1 } return rates_total; }
Создавайте заготовку через MQL Wizard - и не будет ошибок:
//+------------------------------------------------------------------+ //| HighLowColor.mq5 | //| Copyright © 2021, Vladimir Karputov | //| https://www.mql5.com/en/users/barabashkakvn | //+------------------------------------------------------------------+ #property copyright "Copyright © 2021, Vladimir Karputov" #property link "https://www.mql5.com/en/users/barabashkakvn" #property version "1.00" #property indicator_chart_window #property indicator_buffers 4 #property indicator_plots 2 //--- plot High #property indicator_label1 "High" #property indicator_type1 DRAW_COLOR_LINE #property indicator_color1 clrDeepSkyBlue,clrTomato #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- plot Low #property indicator_label2 "Low" #property indicator_type2 DRAW_COLOR_LINE #property indicator_color2 clrBlue,clrGold #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- input parameters input int Input1=9; //--- indicator buffers double HighBuffer[]; double HighColors[]; double LowBuffer[]; double LowColors[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,HighBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighColors,INDICATOR_COLOR_INDEX); SetIndexBuffer(2,LowBuffer,INDICATOR_DATA); SetIndexBuffer(3,LowColors,INDICATOR_COLOR_INDEX); //--- 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 limit=prev_calculated-1; if(prev_calculated==0) limit=0; for(int i=limit; i<rates_total; i++) { int result=i%2; HighBuffer[i]=high[i]; HighColors[i]=(result==0)?0:1; LowBuffer[i]=low[i]; LowColors[i]=(result==0)?0:1; } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Результат:
Мне на данный момент представленное Вами решение подходит, спасибо большое. Однако, я попробовал поочередно переносить некоторые из свойств property в функции PlotIndex... В справке все-таки написано, что можно и так и так задавать:
Получается для второй линии перестает работать вывод названия в окно данных PLOT_LABEL, и отрисовки PLOT_DRAW_TYPE, PLOT_COLOR_INDEXES не отображаются.
Сегодня увидел в примерах с помощью этих функций можно много динамических изменений делать в процессе работы индикатора. А получается с линией больше, чем одна, наверное, не получится.
Возможно, это недоработка и нужны поправки от разработчиков.
Vasiliy Pushkaryov #:
Возможно, это недоработка и нужны поправки от разработчиков.
Нет, просто вы немного недоразобрались.
У индикаторов есть буферы (buffers) и графики (plots). В простых случаях нумерация для них совпадает, в вашем нет.
У вас 4 буфера и 2 графика, соответственно для второго графика для функций PlotIndexSet* индекс будет 1 а не 2, потому что индексация у них последовательная.
Нет, просто вы немного недоразобрались.
У индикаторов есть буферы (buffers) и графики (plots). В простых случаях нумерация для них совпадает, в вашем нет.
У вас 4 буфера и 2 графика, соответственно для второго графика для функций PlotIndexSet* индекс будет 1 а не 2, потому что индексация у них последовательная.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Пытаюсь создать вменяемый индикатор Ренко, насколько он только может быть вменяемым на минутных барах.
Вроде более-менее похоже на правду, но с цветами запутался.
Может кто подскажет, почему цвет присваивается не по индексу буфера, а на опр. его участке?
Мой индикатор нижний.
Хочется так
#property indicator_buffers 2
#property indicator_plots 1
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 clrBlue, clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
input int InpBoxSize = 100;
input int InpDepth = 0;
double iRenkoValues[];
double iRenkoColors[];
double iRenko[];
int iMaxBars = 0;
int OnInit()
{
SetIndexBuffer(0, iRenko, INDICATOR_DATA);
SetIndexBuffer(1, iRenkoColors, INDICATOR_COLOR_INDEX);
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 2);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, clrBlue); // PROBLEM MAY BE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, clrRed);
IndicatorSetInteger(INDICATOR_DIGITS, Digits());
IndicatorSetString(INDICATOR_SHORTNAME, "Renko");
iMaxBars = InpDepth ? InpDepth : TerminalInfoInteger(TERMINAL_MAXBARS);
ArrayResize(iRenkoValues, iMaxBars);
ArraySetAsSeries(iRenko, true);
ArraySetAsSeries(iRenkoValues, true);
ArrayFill(iRenkoValues, 0, iMaxBars, 0);
ArrayInitialize(iRenkoValues, 0);
return 0;
}
int OnCalculate(const int bars, const int counted, const int begin, const double &price[])
{
string symbol = Symbol();
MqlRates rates[];
int stop = 0;
int index = 0;
int downloads = CopyRates(symbol, PERIOD_M1, 0, iMaxBars, rates);
int direction = rates[downloads - 1].close > rates[downloads - 2].open ? 1 : -1;
double residualUp = 0;
double residualDown = 0;
double size = InpBoxSize * Point();
double point = direction > 0 ? rates[downloads - 1].high : rates[downloads - 1].low;
for (int k = downloads - 2; k > 0; k--)
{
direction = rates[k].close > rates[k - 1].open ? 1 : -1;
double distance = MathAbs(rates[k].high - rates[k].low);
int intervals = (int) MathFloor(distance / Point() / InpBoxSize);
for (int n = 0; n < intervals; n++)
{
if (index + n >= iMaxBars)
{
stop = 1;
break;
}
iRenkoValues[index] = point;
point -= direction * size;
index += 1;
}
if (stop == 1 || index >= iMaxBars)
{
break;
}
double residual = intervals < 1 ? distance : MathMod(distance, InpBoxSize);
if (direction > 0)
{
residualUp += residual;
}
if (direction < 0)
{
residualDown += residual;
}
if (MathAbs(residual) > size)
{
residualDown = residualDown ? residualDown - size : 0;
residualUp = residualUp ? residualUp - size : 0;
iRenkoValues[index] = point;
point -= direction * size;
index++;
}
}
int pos = 0;
int count = MathMin(ArraySize(iRenko), ArraySize(iRenkoValues));
for (int k = 0; k < count - InpBoxSize - 1; k++)
{
iRenko[pos] = iRenkoValues[k];
iRenkoColors[pos] = iRenkoValues[k + 1] > iRenkoValues[k] ? 0 : 1; // PROBLEM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
pos++;
}
return bars;
}