тел.: 8 800 200 86 47|+7 (812) 336 61 11Заказать звонок
Admiral Markets UK Admiral Markets UK Choose your country

Разноцветные индикаторные линии

Цикл "В помощь трейдеру"

Скачать Stochastic_color.mq4

Как известно, индикаторы играют немаловажную роль в жизни трейдеров. Качество представления информации особенно остро ощущается трейдером, когда этап первого знакомство с рынком уже завершён и начинается осмысленная торговля. В этот период трейдер уже достаточно хорошо представляет что и для чего ему нужно. Если трейдер торгует вручную, основывая свои торговые решения на показаниях какого-то индикатора, то нередко возникает идея его усовершенствования с целью повышения эффективности использования информации.

Наиболее популярной задачей в подобных случаях является изменение цвета индикаторных линий при изменении тенденции движения рыночной цены. Изменение цвета линий обычно требуется выполнить либо при их пересечении, либо при изменении знака наклона линии. Для самостоятельного решения подобных задач требуется знание некоторых подробностей технологии построения индикаторов для MetaTrader 4, а также начальный опыт программирования. Здесь мы рассмотрим пример, который позволит показать основные особенности выполнения этой работы.

 

Задача.

Внести необходимые изменения в код стандартного индикатора Stochastic.

При пересечении основной линией индикатора сигнальной линии сверху вниз цвет основной линии должен изменяться на красный. При пересечении снизу вверх - на синий. При пересечении линий в любом направлении необходимо один раз выдать звуковое оповещение.

 

Обычный индикатор Stochastic выводится в подокно. При стандартных настройках индикатор отображает две тонкие сплошные линии - основную зелёную и сигнальную красную. В соответствии с замыслом разработчиков индикатора, торговое решение принимается в момент, кода линии пересекаются. Считается, что если пересечение линий происходит за пределами коридора 30-70%, то вероятность успешного завершения операции достаточно высока. Если зелёная пересекает красную сверху вниз, то открывают ордер Buy, если же снизу вверх, то Sell.

Рис. 1. Стандартный индикатор Stochastic в подокне финансового инструмента.

Основу предложенного решения составляет код стандартного индикатора Stochastic, выполненный разработчиками торговой платформы MetaTrader 4. Настроечные параметры, локальные и глобальные переменные, а также сам алгоритм расчётов не изменены. В индикатор добавлен новый блок 8-10, в котором содержится основной код, реализующий решение рассматриваемой задачи.

 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
// Stochastic_color.mq4
// Индикатор запрограммирован по тех.заданию заказчика.
// Сергей Ковалёв, Днепропетровск, sk@autograf.dp.ua, ICQ 64015987, http://autograf.dp.ua
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 0 жж
#property copyright "Convert pvt, http://autograf.dp.ua"
#property link "Sergey Kovalyov, sk@autograf.dp.ua"
#property indicator_separate_window // Индикатор отображается в подокне
#property indicator_buffers 6 // Количество буферов
#property indicator_color1 Lime // Цвет основной линии
#property indicator_color2 DeepSkyBlue // Цвет поднимающейся линии
#property indicator_color3 Tomato // Цвет опускающейся линии
#property indicator_color4 Silver // Цвет сигнальной линии
#property indicator_maximum 100 // Верхнее ограничение шкалы индика
#property indicator_minimum 0 // Нижнее ограничение шкалы индикат
extern int KPeriod=5; // Внешние параметры Stochastic
extern int DPeriod=3; // Внешние параметры Stochastic
extern int Slowing=3; // Внешние параметры Stochastic
double Main[]; // Массив данных основной линии
double Line_B[]; // Массив данных поднимающейся лини
double Line_S[]; // Массив данных опускающейся линии
double Signal[]; // Массив данных сигнальной линии
double HighesBuffer[]; // Рабочий массив для вычислений
double LowesBuffer[]; // Рабочий массив для вычислений
int draw_begin1=0; // Открытие глобальных переменных
int draw_begin2=0; // Открытие глобальных переменных
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 1 жж
int init()
{
string short_name; // Короткое имя
IndicatorBuffers(6); // Распределение памяти для 6 буферов
SetIndexBuffer(0, Main); // Соответствие буфера и назв. массива
SetIndexBuffer(1, Line_B); // Соответствие буфера и назв. массива
SetIndexBuffer(2, Line_S); // Соответствие буфера и назв. массива
SetIndexBuffer(3, Signal); // Соответствие буфера и назв. массива
SetIndexBuffer(4, HighesBuffer);
SetIndexBuffer(5, LowesBuffer);
SetIndexStyle(0,DRAW_LINE); // Настройка стиля основной линии
SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2); // Настройка стиля поднимающейся линии
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2); // Настройка стиля опускающейся линии
SetIndexStyle(3,DRAW_LINE,STYLE_DOT); // Настройка стиля сигнальной линии
short_name="Sto("+KPeriod+","+DPeriod+","+Slowing+")";// Значение строки коротк. имени
IndicatorShortName(short_name); // Установка короткого имени индикат
SetIndexLabel(0,short_name); // Установка имени основной линии
SetIndexLabel(3,"Signal"); // Установка имени сигнальной линии
draw_begin1=KPeriod+Slowing; // Вычисление порядкового номера ..
draw_begin2=draw_begin1+DPeriod; // .. бара от начала данных
SetIndexDrawBegin(0,draw_begin1); // Установка порядкового номера ..
SetIndexDrawBegin(3,draw_begin2); // .. бара от начала данных
SetIndexDrawBegin(1,draw_begin1); // Для синей линии оранич. как основн
SetIndexDrawBegin(2,draw_begin1); // Для красн линии оранич. как основн
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 2 жж
int start()
{
int i,k; // Основной код функции start (2-8) ..
int counted_bars=IndicatorCounted(); // .. составлен на основе стандартного
double price; // .. индикатора Stochastic ..
if(Bars<=draw_begin2) // .. (не комментируется)
return;
//---- initial zero ---------------------------------------------------------------- 3 --
if(counted_bars<1)
{
for(i=1;i<=draw_begin1;i++) Main[Bars-i]=0;
for(i=1;i<=draw_begin2;i++) Signal[Bars-i]=0;
}
//---- minimums counting ----------------------------------------------------------- 4 --
i=Bars-KPeriod;
if(counted_bars>KPeriod) i=Bars-counted_bars-1;
while(i>=0)
{
double min=1000000;
k=i+KPeriod-1;
while(k>=i)
{
price=Low[k];
if(min>price) min=price;
k--;
}
LowesBuffer[i]=min;
i--;
}
//---- maximums counting ----------------------------------------------------------- 5 --
i=Bars-KPeriod;
if(counted_bars>KPeriod) i=Bars-counted_bars-1;
while(i>=0)
{
double max=-1000000;
k=i+KPeriod-1;
while(k>=i)
{
price=High[k];
if(max<price) max=price;
k--;
}
HighesBuffer[i]=max;
i--;
}
//---- %K line --------------------------------------------------------------------- 6 --
i=Bars-draw_begin1;
if(counted_bars>draw_begin1) i=Bars-counted_bars-1;
while(i>=0)
{
double sumlow=0.0;
double sumhigh=0.0;
for(k=(i+Slowing-1);k>=i;k--)
{
sumlow+=Close[k]-LowesBuffer[k];
sumhigh+=HighesBuffer[k]-LowesBuffer[k];
}
if(sumhigh==0.0) Main[i]=100.0;
else Main[i]=sumlow/sumhigh*100;
i--;
}
//---- last counted bar will be recounted ------------------------------------------ 7 --
if(counted_bars>0) counted_bars--;
int limit=Bars-counted_bars;
//---- signal line is simple movimg average
for(i=0; i<limit; i++)
Signal[i]=iMAOnArray(Main,Bars,DPeriod,0,MODE_SMA,i);
//================================================================================== 8 ==
bool Sound = false; // Флаг разрешения звукового сигнал
if (Fun_New_Bar() == 1) // Если это новый бар ..
Sound = true; // .. разрешаем звук
//---------------------------------------------------------------------------------- 9 --
counted_bars = IndicatorCounted(); // Количество просчитанных баров
i=Bars-counted_bars-1; // Индекс первого непосчитанного
while(i>=0) // Цикл по непосчитанным барам
{
if (Main[i]>Signal[i]) // Если основная выше сигнальной
{
Line_B[i] = Main[i]; // Значение синей определяется, ..
Line_S[i] = EMPTY_VALUE; // .. а красной - пустое
if (Main[i+1]<=Signal[i+1]) // Если при этом предыдущее значен
{ // .. основной линии ниже сигнальн
Line_B[i+1]= Main[i+1]; // Значение синей определяется
if (i==0 && Sound == true) // Если на 0 баре звука не было
PlaySound("alert.wav"); // Воспроизводим звуковой сигнал
}
}
if (Main[i]<Signal[i]) // Если основная ниже сигнальной
{
Line_S[i] = Main[i]; // Значение красной определяется,..
Line_B[i] = EMPTY_VALUE; // .. а синей - пустое
if (Main[i+1]>=Signal[i+1]) // Если при этом предыдущее значен
{ // .. основной линии выше сигнальн
Line_S[i+1]= Main[i+1]; // Значение красной определяется
if (i==0 && Sound == true) // Если на 0 баре звука не было
PlaySound("alert.wav"); // Воспроизводим звуковой сигнал
}
}
i--; // Расчёт индекса следующего бара
}
//================================================================================= 10 ==
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 11 жж
int Fun_New_Bar() // Ф-ия обнаружения нового бара
{
static datetime New_Time=0; // Время текущего бара
if (New_Time == 0) // Если это самое первое вычисление
{
New_Time = Time[0]; // Теперь время такое
return(0); // Возвращаем 0. Нового бара нет
}
if (New_Time != Time[0]) // Время другое, т.е.есть новый бар
{
New_Time = Time[0]; // Теперь будем помнить такое время
return(1); // Возвращаем 1. Поймался новый бар
}
else
return(0); // Возвращаем 0. Нового бара нет
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж Конец модуля жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 12 жж
 

 

 

В стандартном индикаторе Stochastic используются всего 4 глобальных массива, два из которых содержат данные для отображения линий, а два других используются для промежуточных расчётов. Решение рассматриваемой задачи предполагает увеличение количества массивов. Кроме указанных, требуются ещё два массива. Такая необходимость вызвана тем, что линия переменного цвета фактически состоит из двух независимых линий. Каждую из этих линий также нужно вывести в подокно индикатора. Для этого следует использовать ещё два буфера.

Вообще говоря, в программе используется массив Main, данные которого составляют значения основной линии. В другом варианте решения можно было бы добавить всего один массив, например, для красной линии, а для отображения синей использовать имеющийся массив Main. Однако, наша идея состоит в том, чтобы по возможности не вносить изменения в исходный код индикатора. Эта идея вполне осуществима, т.к. стандартом языка MQL 4 предусматривается максимально 8 буферов для индикаторных массивов. Мы же будем использовать всего 6 из них.

Таким образом, все данные в массиве Main будут сохранены в том виде, в котором они присутствуют в расчётах стандартного индикатора. При необходимости можно "обесцветить" красную и синюю линии, при этом линия Main станет видна. Таким способом можно восстановить на экране исходный вид индикатора. 

Цвет для новых линий задан в головной части программы - блоке 0-1. Два новых индикаторных массива названы, соответственно, Line_B[] и Line_S[]. Другие данные в этой части оставлены без изменений. В блоке 1-2 всем индикаторным массивам поставлены в соответствие номера буферов, заданы стили линий. Другие строки кода в этом блоке также не измены.

Алгоритм вычисления значений для массивов Line_B[] и Line_S[] реализован в блоке 8-10. Значение переменной counted_bars в процессе предыдущих вычислений изменялось по смыслу соответствующих расчётов. Наши расчёты предполагают необходимость заново вычислить это значение, исходя из общего количества баров.

Вычисления значений элементов массивов Line_B[] и Line_S[] выполняются в цикле while по всем барам, начиная от самого старого к текущему. Собственно, расчёт значений основной линии наша программа унаследовала от стандартного индикатора. Красная и синяя линии чередуются, но образуемая ими общая траектория полностью совпадает с исходной основной линией.

Совокупность всех одноцветных отрезков синего цвета с пустыми промежутками между ними представляет цельную линию, данные для построения которой содержатся в массиве Line_B[], а красной - в массиве Line_S[]. Расчёт значений красной и синей линий сводится к определению точек начала и конца каждого отдельного участка.

 В данном решении задачи принято, что участок между двумя барами, на котором происходит пересечение основной и сигнальной линий, отображается цветом новой тенденции. В процессе развития бара цвет этого участка может меняться. С момента образования нового бара вычисления на этом участке больше не выполняются, поэтому исторический цвет остаётся таким, каким он был вычислен на последнем тике бара (по цене закрытия).

Пустые промежутки линий появляются, если одно из значений элементарного участка (между барами) содержит пустое значение (EMPTY_VALUE). При пересечении сигнальной линии основной линией снизу вверх начало синей тенденции отображается на последнем баре, предшествующем факту пересечения. Расчёты, соответствующие этому случаю, представлены ниже:

 
      if (Main[i]>Signal[i])                          // Если основная выше сигнальной
{
Line_B[i] = Main[i]; // Значение синей определяется, ..
Line_S[i] = EMPTY_VALUE; // .. а красной - пустое
if (Main[i+1]<=Signal[i+1]) // Если при этом предыдущее значен
{ // .. основной линии ниже сигнальн
Line_B[i+1]= Main[i+1]; // Значение синей определяется
. . .
}
}
 

Аналогичные расчёты выполняются при пересечении сверху вниз (начало и продолжение красной тенденции). Рисунок, который выводится в окно индикатора, выглядит как одна цельная линия, изменяющая свой цвет:

Рис. 2. Пользовательский индикатор Stochastic_color в подокне финансового инструмента.

Принятый метод построения разноцветной линии в окне индикатора имеет одну особенность: пустой промежуток между двумя соседними барами с помощью этого метода отобразить невозможно. Поэтому некоторые участки отображаются неправильно:

Рис. 3. Неправильный цвет на участке 1-2. Отображается красный. Должен быть синий.

Для правильного понимания этого затруднения рассмотрим простой пример. Пусть имеются бары, пронумерованные слева направо 0, 1, 2, 3. Пусть данные индикаторной линии на этих барах будут одинаковыми и составляют 75. Требуется составить последовательность значимых и пустых значений так, чтобы видны были участки 0-1 и 1-2, а участок 1-2 не отображался. Для отображения "заполненного" участка 0-1 требуется, чтобы значение 2 было пустым (EMPTY_VALUE), а значения 0 и 1 составляли 0.75 . А для отображения участка 2-3 требуется, чтобы пустым было значение 1. Таким образом, это - взаимоисключающие условия, не позволяющие получить решение для отображение одного элементарного пустого промежутка. В случае, если пустой отрезок составляет более одного элементарного участка (например, между двумя, тремя барами и более), то это легко выполнимо.

Указанный недостаток касается только отображения, но не касается данных в исходном массиве Main[]. Поэтому, вызывая этот индикатор для расчётов из эксперта через iCustom, следует принимать к расчётам данные не из массивов Line_B[] и Line_S[], а из массива Main[].

Может сложиться впечатление, что при возникновении методического затруднения (в этом примере) неправильные вычисления выполняются "зеркально" и при вычислении значений для синей линии. Но это не так. Затруднения возникают только в случае необходимости отображения элементарного пустого участка. В данном случае для синей линии ситуация не такая. На Рис. 4 хорошо видно, что справа и слева от "проблемного" участка пустые промежутки занимают более одного элементарного участка (2 слева и 5 справа). Отдельно нужно заметить, что если на одном участке отображаются две линии, то видимой будет та, индекс которой больше.

Рис. 4. Изображение получено путём обесцвечивания красной линии в окне настроек индикатора.

Звуковое оповещение выводится в случае, когда имеет место начало новой тенденции (один раз в начале нового бара). Для этой цели в программе содержится простой код:

 
            if (i==0 && Sound == true)                // Если на 0 баре звука не было 
PlaySound("alert.wav"); // Воспроизводим звуковой сигнал
 

 

 

Значение флага Sound определяется в блоке 8-9. Определение факта образования нового бара вычисляется в функции Fun_New_Bar(). Нужно подчеркнуть также, что расцветка линий и звуковое сопровождение - две разные, не связанные между собой подзадачи. Необходимость выдавать звуковой сигнал рассчитывается на основании данных массива Main[], не содержащего пустых значений. Поэтому звуковые сигналы будут появляться вовремя, в соответствии с фактом образования новой тенденции и независимо от методических затруднений при отображении.

Рис. 5. Индикаторы Stochastic и Stochastic_color в подокне финансового инструмента.

Успешность принятой стратегии, конечно же, никак не связана с расцветкой или озвучиванием того или иного индикатора. Вместе с тем, использование "дружественных" прикладных программ, в том числе, индикаторов, оптимизированных по виду и цвету позволяет создать комфортную обстановку во время торговли, понизить нервную нагрузку, легче сосредоточиться на выполнении главной задачи. "Усиление" индикатора звуком также весьма полезно. Звуковые оповещения позволяют трейдеру не присутствовать постоянно возле компьютера, а подходить лишь в случае необходимости принимать торговые решения.

 

 Сергей Ковалёв
Июнь 20099
http://autograf.dp.ua/
Специально для компании Admiral Markets
 

4.125
 
 
X
Loading