
Построение излучений индикаторов в MQL5
Введение
Наверняка, многих трейдеров и разработчиков торговых стратегий (ТС) интересовали подобные вопросы:
- Как зарождаются сильные движения на рынке?
- Как определить правильное направление предстоящих изменений?
- Как занять выгодную позицию для торговли?
- Как с максимальной выгодой закрыть позиции?
Поиск ответов на эти вопросы в результате привёл меня к созданию нового направления исследования рынка: построение и анализ излучений от индикаторов. Чтобы было понятнее о чём идёт речь, предлагаю посмотреть на следующие рисунки.
Рис. 1 Излучение индикатора DCMV
Рис. 2 Излучение индикатора, построенного на конвертах iМА
Здесь изображены излучения от разных индикаторов, но принцип построения у них одинаков. С каждым тиком, на графике появляются всё новые и новые точки с различным цветом и формой. Они образуют многочисленные скопления в виде туманностей, облаков, дорожек, линий, дуг и т.п. Эти характерные области точек помогают обнаружить невидимые пружины и силы, которые влияют на движение рыночных цен. Рассмотрение и анализ излучений индикаторов похожи чем-то даже на хиромантию.
Излучение и его свойства
Излучение - это множество точек, расположенных в местах пересечений характерных линий индикатора.
Свойства излучений пока не все открыты и не достаточно изучены - они ждут ещё своих исследователей. А вот некоторые, уже известные, свойства можно перечислить:
- однотипные точки стремятся объединиться в скопления;
- излучение распространяется из настоящего времени в будущее или прошлое;
- плотные скопления точек способны притянуть к себе или, наоборот, оттолкнуть от себя цену.
Построение излучения от индикаторов
Рассмотрим принцип построения излучения на примере. Для этого возьмём два индикатора: iBands и iMA. Затем будем искать пересечения линий этих индикаторов и там рисовать соответствующие точки. Для этого нам потребуются графические объекты, алгоритм реализован в эксперте, хотя можно и в индикаторе.
Итак, исходные индикаторы изображаются на графике примерно так.
Рис. 3 Индикаторы iBands (зелёный) и iMA (красный)
Далее нам нужен эксперт, в котором и будем последовательно реализовывать наш замысел - создания излучения. Для этого лучше всего воспользоваться мастером MQL5 и создать шаблон советника.
Рис. 4 Создание шаблона советника с помощью мастера
//+------------------------------------------------------------------+ //| Излучение Bands && MA.mq5 | //| Copyright DC2008 | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "DC2008" #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
Первым делом, нам нужны вспомогательные построения. Необходимо продолжить характерные линии индикаторов лучами (рис. 5). Это поможет контролировать правильность расчёта и визуализации точек излучения. В дальнейшем, мы эти линии удалим с графика.
Рис. 5 Вспомогательные построения. Продолжение линий индикаторов лучами
Итак, добавим в код эксперта графические объекты: горизонтальные и трендовые (индикаторные) линии.
input bool H_line=true; // разрешаем строить горизонтальные линии input bool I_line=true; // разрешаем строить индикаторные линии //--- string name; //---- indicator buffers double MA[]; // массив для индикатора iMA double BBH[]; // массив для индикатора iBands - UPPER_BAND double BBL[]; // массив для индикатора iBands - LOWER_BAND double BBM[]; // массив для индикатора iBands - BASE_LINE datetime T[]; // массив координат времени //---- handles for indicators int MAHandle; // указатель на индикатор iMA int BBHandle; // указатель на индикатор iBands //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- MAHandle=iMA(Symbol(),0,21,0,MODE_EMA,PRICE_CLOSE); BBHandle=iBands(Symbol(),0,144,0,2,PRICE_CLOSE); //--- if(H_line) // Горизонтальные линии для индикатора iBands { //--- iBands - UPPER_BAND name="Hi"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Red); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); //--- iBands - LOWER_BAND name="Lo"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Blue); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); //--- iBands - BASE_LINE name="MIDI"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,DarkOrange); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); } //--- if(I_line) // Индикаторные линии { //--- iMA name="MA"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Red); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,2); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - UPPER_BAND name="BH"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - LOWER_BAND name="BL"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - BASE_LINE name="BM"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); } return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- заполнение массивов координат текущими значениями CopyBuffer(MAHandle,0,0,2,MA); ArraySetAsSeries(MA,true); CopyBuffer(BBHandle,0,0,2,BBM); ArraySetAsSeries(BBM,true); CopyBuffer(BBHandle,1,0,2,BBH); ArraySetAsSeries(BBH,true); CopyBuffer(BBHandle,2,0,2,BBL); ArraySetAsSeries(BBL,true); CopyTime(Symbol(),0,0,10,T); ArraySetAsSeries(T,true); //--- Горизонтальные линии для индикатора iBands (корректировка) if(H_line) { name="Hi"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBH[0]); name="Lo"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBL[0]); name="MIDI"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBM[0]); } //--- Индикаторные линии (корректировка) if(I_line) { name="MA"; //--- iMA ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,MA[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,MA[0]); name="BH"; //--- iBands - UPPER_BAND ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBH[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBH[0]); name="BL"; //--- iBands - LOWER_BAND ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBL[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBL[0]); name="BM"; //--- iBands - BASE_LINE ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBM[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBM[0]); } } //+------------------------------------------------------------------+Поскольку построение излучения происходит и в прошлое, и в будущее, то свойства трендовых линий должны быть следующими:
- луч продолжается вправо = 1;
- луч продолжается влево = 1.
В результате, график с дополнительными линиями будет выглядеть приблизительно так, как на рис. 6.
Подготовительный этап завершён, теперь переходим непосредственно к излучению. Первую серию точек будем строить в узлах пересечения индикаторных линий:
- прямой "MA" (iMA) и прямой "BH" (iBands = UPPER_BAND);
- прямой "MA" (iMA) и прямой "BL" (iBands = LOWER_BAND);
- прямой "MA" (iMA) и прямой "BM" (iBands = BASE_BAND).
Рис. 6 Вспомогательные построения. Продолжения индикаторов прямыми линиями
И вот мы подошли к тому моменту, когда осталось только вычислить координаты пересечения этих линий и нарисовать в них соответствующие точки излучения. Для этого создадим следующую функцию:
void Draw_Point( string P_name, // имя объекта OBJ_ARROW double P_y1, // Y-координата 1 прямой на [1] баре double P_y0, // Y-координата 1 прямой на [0] баре double P_yy1, // Y-координата 2 прямой на [1] баре double P_yy0, // Y-координата 2 прямой на [0] баре char P_code1, // код символа точки справа от [0] бара char P_code2, // код символа точки слева от [0] бара color P_color1, // цвет точки точки справа от [0] бара color P_color2 // цвет точки точки слева от [0] бара ) { double P,X; datetime P_time; if(MathAbs((P_yy0-P_yy1)-(P_y0-P_y1))>0) { P=P_y1+(P_y0-P_y1)*(P_y1-P_yy1)/((P_yy0-P_yy1)-(P_y0-P_y1)); X=(P_y1-P_yy1)/((P_yy0-P_yy1)-(P_y0-P_y1)); if(X>draw_period) { P_time=T[0]+(int)(X*PeriodSeconds()); ObjectCreate(0,P_name,OBJ_ARROW,0,0,0); ObjectSetDouble(0,P_name,OBJPROP_PRICE,P); ObjectSetInteger(0,P_name,OBJPROP_TIME,P_time); ObjectSetInteger(0,P_name,OBJPROP_WIDTH,0); ObjectSetInteger(0,P_name,OBJPROP_ARROWCODE,P_code1); ObjectSetInteger(0,P_name,OBJPROP_COLOR,P_color1); if(X<0) { ObjectSetInteger(0,P_name,OBJPROP_ARROWCODE,P_code2); ObjectSetInteger(0,P_name,OBJPROP_COLOR,P_color2); } } } }
а в функцию OnTick() советника включим вот этот фрагмент:
//+------------------------------------------------------------------+ int GTC=GetTickCount(); //+------------------------------------------------------------------+ name="H"+(string)GTC; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],170,178,Red,Red); name="L"+(string)GTC; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],170,178,Blue,Blue); name="M"+(string)GTC; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],170,178,Green,Green); //--- ChartRedraw(0);
Запускаем эксперт и смотрим на результат (рис. 7).
Хорошо, но ведь кроме пересечения линий индикаторов между собой есть и другие варианты пересечений, которые мы не учли. Так, индикатор iBands состоит из трёх линий, которые также пересекаются между собой и могут дополнить общую картину.
Рис. 7 Излучение от индикаторов iMA и iBands (3 пересечения)
Давайте попробуем добавить ещё одну серию точек к полученному излучению:
- прямой "BH" (iBands = UPPER_BAND) и прямой "BL" (iBands = LOWER_BAND);
- прямой "BH" (iBands = UPPER_BAND) и прямой "BM" (iBands = BASE_BAND);
- прямой "BL" (iBands = LOWER_BAND) и прямой "BM" (iBands = BASE_BAND).
В результате этих пересечений, мы получили бы 3 точки, но они все будут иметь одинаковые координаты. Поэтому, достаточно оставить только одно пересечение, в котором участвует прямая "BH" и прямая "BL".
Добавим в код эксперта вот эти строчки и посмотрим на окончательный результат (рис. 8).
name="B"+(string)GTC; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],170,178,Magenta,Magenta);
Рис. 8 Излучение от индикаторов iMA и iBands (4 пересечения)
Итак, вроде получили излучение, но остаётся ощущение, что мы что-то очень важное пропустили. А что?
У внимательного читателя давно уже возник вопрос: а почему, собственно говоря, в индикаторах использованы именно такие входные параметры? А что будет, если их изменить? И вообще, какова их роль в излучениях?
Всё правильно. Полученное нами излучение соответствует только одной частоте, обусловленной входными параметрами индикаторов. А чтобы получить наиболее полный многочастотный спектр, необходимо построить аналогичные излучения и для других частот. Выбор таких частот остаётся за вами. В качестве примера, приведу свой вариант возможного спектра излучения:
//---- handles for indicators int MAHandle[5]; // массив указателей на индикатор iMA int BBHandle[7]; // массив указателей на индикатор iBands //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- MAHandle[0]=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); MAHandle[1]=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE); MAHandle[2]=iMA(NULL,0,55,0,MODE_EMA,PRICE_CLOSE); MAHandle[3]=iMA(NULL,0,89,0,MODE_EMA,PRICE_CLOSE); MAHandle[4]=iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE); //--- BBHandle[0]=iBands(NULL,0,55,0,2,PRICE_CLOSE); BBHandle[1]=iBands(NULL,0,89,0,2,PRICE_CLOSE); BBHandle[2]=iBands(NULL,0,144,0,2,PRICE_CLOSE); BBHandle[3]=iBands(NULL,0,233,0,2,PRICE_CLOSE); BBHandle[4]=iBands(NULL,0,377,0,2,PRICE_CLOSE); BBHandle[5]=iBands(NULL,0,610,0,2,PRICE_CLOSE); BBHandle[6]=iBands(NULL,0,987,0,2,PRICE_CLOSE); //--- return(0); }
а по перебору всех возможных комбинаций, добавим в советник следующий код
//+------------------------------------------------------------------+ CopyTime(NULL,0,0,10,T); ArraySetAsSeries(T,true); int GTC=GetTickCount(); //+------------------------------------------------------------------+ int iMax=ArraySize(BBHandle)-1; int jMax=ArraySize(MAHandle)-1; for(int i=0; i<iMax; i++) { for(int j=0; j<jMax; j++) { //--- заполнение массивов координат текущими значениями CopyBuffer(MAHandle[j],0,0,2,MA); ArraySetAsSeries(MA,true); CopyBuffer(BBHandle[i],0,0,2,BBM); ArraySetAsSeries(BBM,true); CopyBuffer(BBHandle[i],1,0,2,BBH); ArraySetAsSeries(BBH,true); CopyBuffer(BBHandle[i],2,0,2,BBL); ArraySetAsSeries(BBL,true); name="H"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],250,158,Aqua,Aqua); name="L"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],250,158,Blue,Blue); name="M"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],250,158,Green,Green); name="B"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],250,158,Magenta,Magenta); } } //--- ChartRedraw(0);
Чем больше частот участвует в спектре излучения, тем более полную картину получим на графике, но не стоит и злоупотреблять этим - иначе никаких ресурсов компьютера не хватит, а на графике образуется хаос. Определить достаточное для анализа количество частот можно экспериментально. А для лучшего восприятия графики, надо уделить особое внимание стилю рисования.
Рис. 9 Многочастотный спектр излучения
О стилях отображения излучений
MQL5 предоставляет разработчикам большой выбор цветовой гаммы и кодов символов для изображения излучений. Но мне бы хотелось поделиться своими соображениями на этот счёт:
- У каждого человека своё восприятие графических образов, поэтому придётся потратить какое-то время на настройку изображения излучений под себя.
- "Каша" на графике (рис. 9) мешает распознаванию образов и каких-либо закономерностей, поэтому он служит примером - "как НЕ надо делать".
- Цвета старайтесь подбирать так, чтобы они находились по соседству в спектре радуги.
- Коды символов (точек) в прошлом (слева от [0] бара) и будущем (справа от [0] бара) должны обязательно отличаться.
- Гармоничное сочетание цветовой гаммы и формы точек способно превратить излучение в шедевры на ваших мониторах, которые будут не только помогать в торговле, но и радовать глаз.
В качестве примера, приведу свой вариант стиля отображения излучения (см. рис. 10-17):
name="H"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],250,158,Aqua,Aqua); name="L"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],250,158,Blue,Blue); name="M"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],250,158,Magenta,Magenta); name="B"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],250,158,DarkOrchid,DarkOrchid);
Галерея излучения iMA и iBands
В этом разделе размещены рисунки с исследуемым излучением.Рис. 10
Рис. 11
Рис. 12
Рис. 13
Рис. 14
Рис. 15
Рис. 16
Рис. 17
Анализ излучения
По анализу излучений можно написать не одну книгу. Поэтому, в рамках данной статьи, ограничусь только наиболее важным моментом: лучше всего понаблюдать за излучением в реальном времени - многие эффекты и закономерности обнаружатся сами собой.
Особенно обратите внимание на коррекции цен - излучение исследуемых индикаторов как будто знает куда цена "откатится". Кроме того, можно заметить области поддержки, сопротивления и равновесия цены.
Заключение
- Излучения индикаторов могут заинтересовать трейдеров и разработчиков торговых стратегий, которые ищут новые методы исследования и анализа рынка.
- Статья является ознакомительной и готовых решений не содержит. Однако приведённая технология получения излучений подробно рассмотрена и может быть применена для других индикаторов или их комбинаций.
- К моменту опубликования статьи у меня накопилось больше вопросов, чем ответов. Вот некоторые из них: как оптимизировать алгоритм построения излучений; как влияют спектрально-частотные характеристики на информативность излучения; как использовать излучения в автотрейдинге?





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Хорошая статья. Автору спасибо
Ну всё, брокерам-кухням осталось жить недолго, скоро алгоритм рынков будет раскрыт)
у меня показивает совмем другое что то..
Совсем не похоже и вдобавок машину сильно грузит(смотрел на реальных котировках EURUSD M1).