Изучаем возможности создания разноцветных свечных графиков
Введение
В этой статье мы рассмотрим возможности создания кастомных индикаторов со свечными графиками, а также поговорим об их преимуществах и недостатках. В рамках статьи рассмотрим четыре варианта таких индикаторов:
1. Построение свечей одного цвета без определения направления свечей.
2. Построение разноцветных свечей, раскрашенных в соответствии с определенными правилами.
3. Построение свечей с заливкой и без, используя различные цвета для заливки свечей и для их контуров.
4. Построение разноцветных свечей с заливкой и без.
Для начала определим, зачем же надо реализовывать правила раскрашивания свечных графиков. А также посмотрим, почему так важно правильно определять правила при создании собственных индикаторов. Каждый метод имеет свои особенности, преимущества и недостатки, которые могут быть связаны, например, с взаимодействием пользователя с программой или с оптимизацией использования программой ресурсов компьютера.
Начнем с операционной модели, которая работает с тремя смещенными ценовыми линиями. Первая линия (черная) — это сама цена, вторая (синяя) — 1-периодная скользящая средняя, сдвинутая на 10 периодов вперед, а третья (красная) — 1-периодная скользящая средняя, сдвинутая на 20 периодов вперед. Построение модели на ценовом графике показано ниже — здесь я добавил две скользящие средние и изменил вид графика на линию.
Получилась не очень удобная модель, которую трудно интерпретировать, ведь тут нужно не только определять цвет линий, но и анализировать, как они соотносятся друг с другом. Это только приводит к путанице, из-за чего можем принимать неверные решения. Еще одна неоднозначная модель, которую тяжело интерпретировать — Индикатор индекса направленного движения. Все потому же, что помимо определения цветов линий надо еще анализировать их соотношения.
Вообще, чем больше у нас переменных или индикаторов, тем чаще могут возникать ошибки в интерпретации, из-за чего и качество принятых решений может быть сомнительным. Мне кажется, нужно использовать столько индикаторов и переменных, которые мы способны эффективно проанализировать и из которых можем извлечь полезную и объективную информацию.
Использование правил раскраски позволяет сделать эффективную выжимку полезной информации и дать четкий ответ, когда можно покупать, когда продавать, а когда лучше не входить в рынок. Получается, всю информацию можно отобразить в трех цветах: один показывает покупку, второй продажу, а третий используется, когда нет условий на покупку или продажу. В этой статье для отображения покупки я буду использовать зеленый, для продаж — красный, а для всех остальных случаев цвет будет желтый. Определение цветов показано в таблице:
Цвет | Направление |
---|---|
зеленый | покупка |
красный | продажа |
желтый | нейтральный |
На данный момент пока не будем думать о том, на основе каких правил раскрашиваются свечи. Для начала посмотрим, как построить свечной график в MQL5. Если вы пишете MQL5-программу для MetaTrader 5 впервые, рекомендую для начала почитать справку по MetaEditor — среде разработке для MetaTrader 5.
Построение свечного графика
Для начала я покажу, как построить простой свечной график, попутно объясню некоторые основные функции. Свечной график состоит из набора свечей. Каждая свеча формируется на основе четырех значений цены: открытия, максимума, минимума и закрытия за период формирования свечи. Чтобы определить, растущая это свеча или падающая, необходимо проверить, закрылась свеча выше или ниже цены открытия. Если закрытие выше открытия, закрасим свечу в зеленый цвет, в противоположном случае, если закрытие ниже, закрасим ее в красный.
Приступим к созданию индикатор с помощью мастера MQL Wizard.
Задаем имя индикатора и указываем правильные данные об авторских правах, т.е. имя автора и адрес веб-страницы.
В индикаторе будем использовать функцию OnCalculate, в которой содержится таймсерия из цен открытия, максимума, минимума и закрытия.
Поскольку индикатор будет отображаться в виде свечного графика, в поле "тип" выберем CANDLES и назовем метку Candles. Это имя метки будет использоваться и в интерфейсе программы, и для работы с индикаторными буферами.
Вот такой код создал Мастер MQL:
//+------------------------------------------------------------------+ //| Candles.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 4 #property indicator_plots 1 //--- plot Candle #property indicator_label1 "Candle" #property indicator_type1 DRAW_CANDLES #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double CandleBuffer1[]; double CandleBuffer2[]; double CandleBuffer3[]; double CandleBuffer4[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,CandleBuffer1,INDICATOR_DATA); SetIndexBuffer(1,CandleBuffer2,INDICATOR_DATA); SetIndexBuffer(2,CandleBuffer3,INDICATOR_DATA); SetIndexBuffer(3,CandleBuffer4,INDICATOR_DATA); //--- 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[]) { //--- //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Скомпилируем код, и индикатор Candles появится в навигаторе в терминале MetaTrader 5. Но если запустить такой индикатор на графике, он отобразится неправильно, так как мы не присваиваем значений индикаторным буферам. Поэтому присвоим значения. В нашем первом методе имеем 4 буфера: CandleBuffer1 [], CandleBuffer2 [], CandleBuffer3 [], CandleBuffer4 []. Назначение этих буферов показано в таблице ниже:
Буферы | Ценовой ряд |
---|---|
CandleBuffer1 | цены открытия |
CandleBuffer2 | цены максимума |
CandleBuffer3 | цены минимума |
CandleBuffer4 | цены закрытия |
В коде необходимо указать количество индикаторных буферов — указываем с помощью свойства индикатора indicator_buffers. Это уже сделал сам Мастер MQL, но вы можете изменить количество буферов и указать, сколько буферов нужно конкретно этому индикатору. Мы сделаем это позже.
#property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 4
Значения нашим буферам будем присваивать в функции OnCalculate с помощью цикла по всему диапазону цен. При этом, как только значение будет присвоено, его уже не нужно переназначать в случае увеличении размера серии. Это означает, что если на выходе функции у нас n свечей, а при следующем вызове свечей будет n + 1, то нам нужно будет рассчитать значения только для последней свечи. В функции OnCalcultate информацию о количестве свечей на графике получаем с помощью параметра rates_total, а количество свечей, которые были на графике на предыдущем вызове функции, получаем с помощью параметра prev_calculated.
Функция OnCalculate получилась такой:
//+------------------------------------------------------------------+ //| 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 start = prev_calculated; if(start>=rates_total) start = rates_total-1; for(int i = start; i<rates_total; i++) { CandleBuffer1[i]=open[i]; CandleBuffer2[i]=high[i]; CandleBuffer3[i]=low[i]; CandleBuffer4[i]=close[i]; } //--- return value of prev_calculated for next call return(rates_total); }
Обратите внимание, что все свечи в нашем индикаторе красного цвета — этот цвет мы определили в Мастере MQL. Этот цвет может поменять пользователь, а также его можно изменить в коде с помощью свойства indicator_color1. С принципом определения и работы с цветами в MQL5 можно ознакомиться в документации по данным типа Color.
//--- plot Candle #property indicator_label1 "Candle" #property indicator_type1 DRAW_CANDLES #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1
Построение разноцветного свечного графика
Мы познакомились с построением свечного графика без разделения по цветам и без определения направления свечей. Теперь посмотрим, как сделать свечи график разноцветными, при этом чтобы цвет устанавливался на основе определенных правил. Для начала установим правило для определения свечей вверх и вниз по цветам.
Для этого используем тип построения DRAW_CANDLES, определенный в свойствах индикатора в indicator_type1. Это свойство можно поменять на DRAW_COLOR_CANDLES, чтобы в итоге получить разноцветные свечи. Поскольку тип построения DRAW_COLOR_CANDLES должен хранить цвет каждой свечи, нам понадобится дополнительный буфер - назовем его CandleColor. Теперь количество используемых буферов выросло до 5. Кроме того, надо добавить цвет для свойства indicator_color1.
#property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 5 #property indicator_plots 1 //--- plot Candle #property indicator_label1 "Candle" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen,clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double CandleBuffer1[]; double CandleBuffer2[]; double CandleBuffer3[]; double CandleBuffer4[]; double CandleColor[];
Затем инициализируем буфер CandleColor, в котором будут храниться цвета свечей — сообщаем компилятору, что хотим использовать этот буфер для хранения цветов. Для этого используем функцию SetIndexBuffer и передаем в качестве параметра INDICATOR_COLOR_INDEX. В нашем случае у нас есть два цвета — зеленый и красный. У первого цвета индекс 0, у второго 1. Если в indicator_color1 определить n цветов, получим индексы цветов от 0 до n-1:
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,CandleBuffer1,INDICATOR_DATA); SetIndexBuffer(1,CandleBuffer2,INDICATOR_DATA); SetIndexBuffer(2,CandleBuffer3,INDICATOR_DATA); SetIndexBuffer(3,CandleBuffer4,INDICATOR_DATA); SetIndexBuffer(4,CandleColor,INDICATOR_COLOR_INDEX); //--- return(INIT_SUCCEEDED); }
Обратите внимание, что изменения можно вносить прямо в Мастере MQL, в котором и происходит инициализация и объявление буферов, а также указывается количество требуемых буферов. Именно в окне Мастера MQL нужно поменять тип построения на DRAW_COLOR_CANDLES и выбрать цвета. Это очень полезная опция, особенно когда работаете с индикатором, который должен рисовать на графике больше одного построения. Вернемся к этому позже.
Сейчас же нам нужно назначить значения буферу CandleColor. В качестве правила для раскрашивания будем использовать закрытие: если свеча закрылась выше открытия, закрашиваем зеленым, если ниже — красным. Посмотрим, как теперь выглядит функция OnCalculate:
for(int i = start; i<rates_total; i++) { CandleBuffer1[i]=open[i]; CandleBuffer2[i]=high[i]; CandleBuffer3[i]=low[i]; CandleBuffer4[i]=close[i]; //if the close price is higher than the open price we set the //green color (index 0), otherwise, the red color (index 1) CandleColor[i]=(close[i]>open[i])?0:1;
Как и ожидалось, в результате мы получаем стандартный график, на котором бычьи и медвежьи свечи отображаются разными цветами.
Давайте изменим правило раскрашивания. Вместо определения направления закрытия свечей (выше и ниже) будем использовать очень простое правило для торговли. В следующем разделе рассмотрим еще один способ определения направления свечей.
Рассмотрим операционную модель, представленную в начале статьи. Согласно правилам, если черная линия (цена закрытия) выше, чем синяя линия (со сдвигом на 10 периодов) и красная линия (со сдвигом на 20 периодов), можно совершать покупку. Если черная линия (цена закрытия) меньше синей и красной линий, то можно совершать сделку на продажу. Во всех остальных случаях необходимо ждать, пока не определится направление рынка. Эти правила показаны в таблице:
Правила торговли | Цвет свечи |
---|---|
close[0] > close[10] and close[0] > close[20] | зеленый |
close[0] < close[10] and close[0] < close[20] | красный |
close[0] > close[10] and close[0] < close[20] | желтый |
close[0] < close[10] and close[0] > close[20] | желтый |
В этом режиме нужно добавить еще один цвет в свойство indicator_color1.
#property indicator_color1 clrGreen,clrRed,clrYellow
Теперь это правило можно добавить в код и присвоить соответствующие значения. Вот что теперь имеем в функции OnCalculate:
{ //--- int start = prev_calculated; if(prev_calculated<20) start = 20; if(start>=rates_total) start = rates_total-1; for(int i = start; i<rates_total; i++) { CandleBuffer1[i]=open[i]; CandleBuffer2[i]=high[i]; CandleBuffer3[i]=low[i]; CandleBuffer4[i]=close[i]; //Close[0] > Close[10] and Close[0] > Close[20] bool buy = close[i]>close[i-10] && close[i]>close[i-20]; //Close[0] < Close[10] and Close[0] < Close[20] bool sell = close[i]<close[i-10] && close[i]<close[i-20]; CandleColor[i]=(buy)?0:(sell)?1:2; } //--- return value of prev_calculated for next call return(rates_total); }
Результат работы индикатора:
Теперь посмотрим на пользовательский интерфейс в окне параметров индикатора MetaTrader 5. Двойной клик на индикаторе в окне графика открывает окно параметров индикатора. На рисунке ниже видно, что цвета передаются в качестве параметров без указания того, какой цвет соответствует условиям на покупку, какой на продажу, а какой нейтральному состоянию. Если бы у нас было больше цветов, работать с индикатором было бы совсем неудобно. Поэтому надо объяснить пользователю, какой цвет что означает. Этим и займемся в последней главе статьи.
Построение свечного графика с заливкой и без нее
Вернемся к исходному коду, когда все свечи были одного цвета. Помните, мы использовали тип построения DRAW_CANDLES с четырьмя буферами. Чтобы использовать разные цвета для контуров свечи и заливки, надо просто определить два цвета в нашем свойстве indicator_color1. Первый цвет будет использоваться для контура, а второй — для заливки свечи. Для демонстрации результата посмотрим на черно-белые свечи.
#property indicator_type1 DRAW_CANDLES #property indicator_color1 clrBlack,clrWhite
Если определить 3 цвета в свойстве indicator_color1, уже можно будет отличать бычьи медвежьи свечи. Эта форма построения свечей заменяет первое правило раскрашивания, которое мы создали в этой статье. Разница в том, что мы продолжаем использовать 4 буфера и при этом можем определить цвета контуров. В этом случае первый цвет применяется к контурам свечи, второй будет использоваться для заливки бычьих свечей, а третий — для заливки медвежьих. На рисунке ниже показан такой график, для третьего цвета используется темно-серый, который не сливается с цветом контура.
#property indicator_type1 DRAW_CANDLES #property indicator_color1 clrBlack,clrWhite,clrDarkGray
Построение разноцветного свечного графика с вариантами заливки свечей
В завершение изучения создания разноцветных свечей в MQL5 сделаем интерфейс в окне параметров индикатора более информативным. Это промежуточный шаг для создания разноцветных свечей, некоторые из которых будут с заливкой, а другие — без. Количество необходимых буферов будет одинаковым в обоих случаях, но их больше, чем количество буферов в вариантах, рассмотренных ранее. Это потому, что мы не будем использовать построения для всех цветов, вместо этого используем построение для каждого цвета. В нашей модели три разных построения: для покупки, для продажи и для неопределенных условий, как было предложено в начале статьи. То есть для реализации такой модель нам понадобятся 12 буферов. Кроме того, для определения цвета будем использовать те же правила на основе скользящих со смещением.
Снова воспользуемся Мастером MQL, это позволит пропустить шаги по определению и инициализации 12 буферов. Вместо построения типа Candle будем использовать построения Buy, Sell и Neutral.
Нам не нужно, чтобы все элементы отображались одновременно. Индикатор должен выбрать один из трех вариантов отображения на основе определенных нами правил, остальные должны быть в это время скрыты. Для этого буферы скрытых свечей должны быть заполнены пустым значением. Первым шагом определим значения, для которых построение должно быть пропущено. Для этого используем функцию PlotIndexSetDouble, как показано ниже.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,BuyBuffer1,INDICATOR_DATA); SetIndexBuffer(1,BuyBuffer2,INDICATOR_DATA); SetIndexBuffer(2,BuyBuffer3,INDICATOR_DATA); SetIndexBuffer(3,BuyBuffer4,INDICATOR_DATA); SetIndexBuffer(4,SellBuffer1,INDICATOR_DATA); SetIndexBuffer(5,SellBuffer2,INDICATOR_DATA); SetIndexBuffer(6,SellBuffer3,INDICATOR_DATA); SetIndexBuffer(7,SellBuffer4,INDICATOR_DATA); SetIndexBuffer(8,NeutralBuffer1,INDICATOR_DATA); SetIndexBuffer(9,NeutralBuffer2,INDICATOR_DATA); SetIndexBuffer(10,NeutralBuffer3,INDICATOR_DATA); SetIndexBuffer(11,NeutralBuffer4,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0); //--- return(INIT_SUCCEEDED); }
В нашем случае используем значения 0.0, чтобы определить пустые значения в наших буферах. Значения 0, 1 и 2, которые передаются первым параметром в функции PlotIndexSetDouble, это индексы наших построений, которые должны быть отображены на ценовом графике. Это тот же индекс, что используется при объявлении свойств наших построений.
Все, что нам нужно сделать, это реализовать определенные ранее правила в функции OnCalculate нашего индикатора. Поскольку в момент времени может отобразиться только одно построение, мы можем определить другие построения как невидимые (скрытые), присвоив значение 0.0 всем свечам при каждом вызове функции OnCalculate. Затем присваиваем значения цен открытия, максимума, минимума и закрытия свечам, которые нужно построить на графике в соответствии с правилами. Вот что у нас получилось:
{ //--- int start = prev_calculated; if(prev_calculated<20) start = 20; if(start>=rates_total) start = rates_total-1; for(int i = start; i<rates_total; i++) { //initializing the candles data BuyBuffer1[i]=0.0; BuyBuffer2[i]=0.0; BuyBuffer3[i]=0.0; BuyBuffer4[i]=0.0; SellBuffer1[i]=0.0; SellBuffer2[i]=0.0; SellBuffer3[i]=0.0; SellBuffer4[i]=0.0; NeutralBuffer1[i]=0.0; NeutralBuffer2[i]=0.0; NeutralBuffer3[i]=0.0; NeutralBuffer4[i]=0.0; //Close[0] > Close[10] e Close[0] > Close[20] bool buy= close[i]>close[i-10] && close[i]>close[i-20]; //Close[0] < Close[10] e Close[0] < Close[20] bool sell= close[i]<close[i-10] && close[i]<close[i-20]; //Setting the values to the candles according to the trading rules if(buy) { BuyBuffer1[i]=open[i]; BuyBuffer2[i]=high[i]; BuyBuffer3[i]=low[i]; BuyBuffer4[i]=close[i]; } else if(sell) { SellBuffer1[i]=open[i]; SellBuffer2[i]=high[i]; SellBuffer3[i]=low[i]; SellBuffer4[i]=close[i]; } else { NeutralBuffer1[i]=open[i]; NeutralBuffer2[i]=high[i]; NeutralBuffer3[i]=low[i]; NeutralBuffer4[i]=close[i]; } } //--- return value of prev_calculated for next call return(rates_total); }
Визуально результат получился таким же, как при использовании типа построения DRAW_COLOR_CANDLES. Большое преимущество нового метода в том, что мы получаем более информативный пользовательский интерфейс, несмотря на значительное увеличение количества необходимых буферов. Это преимущество и дальше можно улучшить, добавив раскрашивание не только для отображения информации согласно выбранным правилам, но и для различения бычьих и медвежьих свечей. Для этого можно поработать с цветами контура и заливкой. Для каждого построения контур и заливка свечей, направленных вниз, будет одного цвета, а для заливки свечей, направленных вверх, будем использовать белый цвет на фоне ценового графика с белым фоном, создавая иллюзию незаполненных свечей. Таблица ниже показывает использование цветов по новой схеме.
Правила торговли | Контур | Положительная заливка | Отрицательная заливка |
---|---|---|---|
покупка | зеленый | белый | зеленый |
продажа | красный | белый | красный |
нейтральный | желтый | белый | желтый |
Ниже показаны изменения в коде:
#property indicator_color1 clrGreen,clrWhite,clrGreen
#property indicator_color2 clrRed,clrWhite,clrRed
#property indicator_color3 clrYellow,clrWhite,clrYellow
Итак, мы подошли к цели этой статьи — демонстрации того, как создавать правила раскраски на основе определенных выбранных торговых правил для создания пользовательского свечного графика. Окончательный результат работы показан на рисунке ниже:
Заключение
Мы увидели, что можем создавать свечные графики, используя два типа построения — DRAW_CANDLES и DRAW_COLOR_CANDLES. Мы научились раскрашивать свечной график на основе выбранных правил торговли, а также использовать разные цвета для контуров и заливки свечей, который позволяет раскрашивать свечи и отображать различие между бычьими и медвежьими свечами. Важно отметить, что в зависимости от целей разрабатываемого индикатора можно не использовать разные цвета для определения свечей, направленных вверх и вниз. Кроме того, если приходится использовать слишком много цветов, например 10, последний рассмотренный метод будет не очень удобным, потому что количество используемых буферов будет очень большим, что может увеличить использование ресурсов пользователей.
В этом случае есть два варианта, которые можно использовать вместо объяснения назначения каждого цвета в окне параметров индикатора. Можно использовать тип построения DRAW_COLOR_CANDLES или DRAW_CANDLES и создать иллюзию незаполненных свечей, нарисовав только контуры для свечей, направленных вниз, а заливку оставив прозрачной — так заливка будет совпадать с фоном графика, и мы получим различие между бычьими и медвежьими свечами, наложенное на построение DRAW_COLOR_CANDLES на основе выбранных правил.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/7815
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования