![Индикатор "Канат" Эрика Наймана](https://c.mql5.com/i/articles/overlay.png)
Индикатор "Канат" Эрика Наймана
Содержание
- Введение
- Глава 1. Описание принципов построения и расчетов индикатора «Канат» с примерами по коду
- Глава 2. Практическое применение индикатора «Канат» и построение эксперта по данному индикатору
- Глава 3. Оптимизация входных параметров эксперта по индикатору «Канат»
- Заключение
Введение
Данная статья и индикатор построены по книге Эрика Л. Наймана (Малая энциклопедия трейдера — К . ВИРА-Р Альфа Капитал, 1999. —236 с.). В ней рассматриваются основы технического и фундаментального анализа финансовых рынков, среди которых был выбран данный метод, названный автором «индикатор "Канат"». Очень кратко об индикаторе можно сказать, что он основан на отношении скорости изменения цены за выбранный период к количеству этих изменений.
В книге автор дает представление своего анализа в таблицах и графиках, на основе которых была написана данная статья. Автор выполняет анализ рынка на основе взаимодействия быков и медведей, в качестве объектов анализа используется скорость изменения цены, количество сделок, масса изменения. Скорость измеряется количеством сделок, а масса определяется разницей двух соседних котировок (текущей и предыдущей). Котировкой в книге считается последняя известная цена (в главе 1 о ней будет рассказано более подробно на примере расчетов).
Целью анализа рынка автором является расчет силы и определение направления тренда, где одновременно на рынок воздействуют силы быков и медведей. Рассчитывая величину этой силы, можно судить о том, кто в данный момент действует сильнее. Автор выделяет это действие как перетягивание каната между двумя противодействующими силами, схематично изображая это в книге через величину «канат», рассчитанную на суммарной силе быков и медведей:
Автор описывает два подхода к анализу рынка и расчетам на основе статического и динамического методов. Расчет величины «канат» в книге проводится по следующим этапам:
1. Оценка и расчет «силы» быков и медведей, нахождение направления.
Формулы силы быков (по книге):
Сб = СПИi, где:
- Сб — сила быков;
- СПИi -—сумма положительных изменений за анализируемый период времени.
Формула силы медведей (по книге):
См = СОИi, где:
- См — сила медведей;
- СОИi — сумма отрицательных изменений за анализируемый период времени.
Далее сравниваются между собой величины Сб и См, чья величина больше, те на рынке в доминирующем положении.
Если взять значение силы и сравнить на двух соседних барах рассматриваемого периода графика, то получим динамическую оценку. В первоисточнике это анализируется как:
Если Сб > См и (Сб1 - СбО) > (См1 - СмО), то это говорит об общей нарастающей силе быков (здесь индексом 1 отмечено текущее значение величины силы, а индексом 0 — предыдущее значение).
Если Сб > См и (Сб1 - СбО) < (См1 - СмО), то это говорит об общей, но падающей силе быков.
Если Сб < См и (Сб1 - СбО) > (См1 - СмО), то это говорит об общей, но падающей силе медведей.
Если Сб < См и (Сб1 - СбО) < (См1 - СмО), то это говорит об общей нарастающей силе медведей.
Как видно, кроме статической величины силы, дополнительно рассматривается динамика изменения данной величины на соседних расчетных точках.
2. Оценка «подвижности» (количество изменений) быков и медведей, расчет и сравнение. Расчет подвижности быков и медведей в первоисточнике:
Пб = КПИi, где:
- Пб — подвижность быков;
- КПИi — количество положительных изменений за анализируемый период времени.
Пм = КОИi, где:
- Пм — подвижность медведей;
- КОИi — количество отрицательных изменений за анализируемый период времени.
Сравнив расчетную величину подвижности с предыдущей соседней, получим динамическую оценку. Оценка динамики делается путем сравнения статической величины с динамической величиной, так же как на примере сравнения из предыдущего этапа анализа.
3. Оценка «мастерства» быков и медведей, расчет и сравнение. В первоисточнике расчет мастерства быков и медведей выглядит как:
Мастерство быков и медведей в проведении своей политики на рынке проявляется в следующих формулах:
Мб = СПИ1/КПИ1;
Мм = COИ1 / КОИ1.
Так рассчитывается статическая величина, динамическая рассчитывается на примере из первого этапа.
4. Итоговая оценка быков и медведей. Рассчитав все значения предыдущих трех этапов и сделав сравнение данных, можно сделать вывод о направлении и характере тренда. Итоговая оценка делается на сравнении всех трех показателей. В книге итоговая оценка представляется как:
Если Сб > См, Пб > Пм и Мб > Мм (при соблюдении динамических соотношений, которые были приведены выше), то быки гораздо предпочтительней в своем движении, нежели медведи и стоит рассматривать только варианты покупки. Для динамической оценки рынка к статическим данным следует добавить динамическую величину двух «соседних расчетных точек линии каната».
На основе данных этапов анализа можно выделить три основные расчетные величины построения индикатора:
- сила — сумма изменений за анализируемый период времени;
- подвижность — количество изменений за анализируемый период времени;
- мастерство = сила / подвижность.
Динамическая часть была проанализирована автором как наиболее чувствительная и наиболее подвижная. В данной статье и в коде был выбран только статический метод расчетов. Таким образом, сравнивая между собой три расчетные части — «сила», «подвижность» и «мастерство», автор делает вывод о силе и направлении тренда, рассчитывает статические и динамические данные и приводит разные методы к их использованию. Далее мы подробно рассмотрим построение самого индикатора «Канат» по методу Эрика Л. Наймана.
Глава 1. Описание принципов построения и расчетов индикатора «Канат» с примерами по коду
Для построения индикатора был выбран линейный и гистограммный метод. Линейный представляет собой сумму расчетных величин быков и медведей. Гистограммный метод отображает расчеты отдельно для быков и медведей.
Теперь рассмотрим код индикатора, в котором дается комментарий каждого шага. Начнем с объявления переменных и характеристик отображения индикатора через #property. Ниже в коде дается описание цветовых характеристик индикатора, что сделано для удобства анализа данных.
//+------------------------------------------------------------------+ //| RopebyEricNaiman.mq5 | //| Copyright 2015, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property description "RopebyEricNaiman by Im_hungry (https://login.mql5.com/en/users/Im_hungry)" #property description "RopebyEricNaiman - shows the direction of the desire of the market action and the power of this desire." #property version "1.00" #property strict //--- подключение функции расчета МА из файла MovingAverages.mqh #include <MovingAverages.mqh> //--- #property indicator_separate_window // задает отрисовку в отдельном окне #property indicator_buffers 12 // установка 12 индикаторных буферов индикатора #property indicator_plots 5 // установка 5 индикаторных буферов, которые будут отрисовываться индикатором //--- гистограмма быков #property indicator_label1 "BULL" #property indicator_type1 DRAW_COLOR_HISTOGRAM // 0 - clrDarkGreen - цветовой индекс "только покупка", покупка с высокой категорией подтверждения // 1 - clrMediumSeaGreen - цветовой индекс "возможна покупка", покупка со средней категорией подтверждения // 2 - clrLightGreen - цветовой индекс "возможна покупка", покупка с низкой категорией подтверждения // 3 - clrGray - цветовой индекс "покупка запрещена" #property indicator_color1 clrDarkGreen,clrMediumSeaGreen,clrLightGreen,clrGray #property indicator_style1 STYLE_SOLID #property indicator_width1 2 //--- гистограмма медведей #property indicator_label2 "BEAR" #property indicator_type2 DRAW_COLOR_HISTOGRAM // 0 - clrDarkRed - цветовой индекс "только продажа", продажа с высокой категорией подтверждения // 1 - clrIndianRed - цветовой индекс "возможна продажа", продажа со средней категорией подтверждения // 2 - clrLightPink - цветовой индекс "возможна продажа", продажа с низкой категорией подтверждения // 3 - clrGray - цветовой индекс "продажа запрещена" #property indicator_color2 clrDarkRed,clrIndianRed,clrLightPink,clrGray #property indicator_style2 STYLE_SOLID #property indicator_width2 2 //--- ГЛАВНАЯ линия индикатора #property indicator_label3 "main line" #property indicator_type3 DRAW_COLOR_LINE // 0 - clrDarkGreen - цветовой индекс "только покупка", покупка с высокой категорией подтверждения // 1 - clrDarkRed - цветовой индекс "только продажа", продажа с высокой категорией подтверждения // 2 - clrGray - цветовой индекс "нет строгого подтверждения" #property indicator_color3 clrDarkGreen,clrDarkRed,clrGray #property indicator_style3 STYLE_SOLID #property indicator_width3 2 //--- отрисовка индикатора быстрой МА по данным ГЛАВНОЙ (main line) линии индикатора #property indicator_label4 "ma fast" #property indicator_type4 DRAW_LINE #property indicator_color4 clrAqua #property indicator_style4 STYLE_SOLID #property indicator_width4 1 //--- отрисовка индикатора медленной МА по данным ГЛАВНОЙ (main line) линии индикатора #property indicator_label5 "ma slow" #property indicator_type5 DRAW_LINE #property indicator_color5 clrYellow #property indicator_style5 STYLE_SOLID #property indicator_width5 1
Сам автор не дает описание цветовых характеристик, и осуществляет анализ тренда при полном/частичном совпадении трех показателей:
- Сила быков > силы медведей — бычий тренд, обратный знак говорит о преобладании медвежьего рынка.
- Подвижность быков > подвижность медведей — бычий тренд.
- Мастерство быков > мастерство медведей — бычий тренд.
Сравнивая между собой эти показатели, можно говорить о силе тренда. Чем больше показателей указывают на тренд, тем он сильнее. Выше при инициализации переменных дается описание цветового отображения гистограммы по трем основным расчетным величинам. Сравнение трех расчетных величин берется в любом сочетании.
0 — clrDarkGreen, цветовой индекс «только покупка», покупка с высокой категорией подтверждения.
1 — clrMediumSeaGreen, цветовой индекс «возможна покупка», покупка со средней категорией подтверждения.
2 — clrLightGreen, цветовой индекс «возможна покупка», покупка с низкой категорией подтверждения.
3 — clrGray, цветовой индекс «покупка запрещена».
Для главной линии индикатора сделано цветовое отображение только при совпадении всех трех расчетных величин в соответствии с оригинальным описанием из книги:
"Если Сб > См, Пб > Пм и Мб > Мм (при соблюдении динамических соотношений, которые были приведены выше), то быки гораздо предпочтительней в своем движении, нежели медведи и стоит рассматривать только варианты покупки. Если Сб < См, Пб < Пм и Мб < Мм (при соблюдении динамических соотношений), то медведи гораздо предпочтительней, чем быки. Желательна только продажа." |
Объявляем внешние переменные индикатора. Здесь нужно отметить, что для удобства работы с индикатором сделана возможность отображать линию и/или гистограмму с помощью входных переменных draw_line и draw_histogram. Для универсальности расчетов была добавлена возможность выбора цен для расчетов индикатора параметром _price. Настройки индикатора МА сделаны также отключаемой опцией.
//--- input parameters input string section_1="___ main settings"; //--- включает отрисовку гистограммы быков и медведей input bool draw_histogram=true; //--- включает отрисовку главной линии индикатора input bool draw_line=true; //--- период индикатора input int _period=76; //--- цена, используемая для расчетов input ENUM_APPLIED_PRICE _price=PRICE_CLOSE; //--- ограничение в расчетах по барам вглубь истории от текущего бара input int max_bars=0; //--- кратное отклонение линии и МА от гистограммы для лучшей наглядности индикатора. Все значения главной линии и МА умножаются на line_deviation input double line_deviation=3.0; //--- input string section_2="___ MA fast"; //--- включение отрисовки быстрой МА input bool draw_MA_fast=false; //--- период расчета быстрой МА по индикатору input int period_MA_fast=25; //--- метод расчета быстрой скользящей средней input ENUM_MA_METHOD method_MA_fast=MODE_SMA; //--- input string section_3="___ MA slow"; //--- включение отрисовки медленной МА input bool draw_MA_slow=false; //--- период расчета медленной МА по индикатору input int period_MA_slow=143; //--- метод расчета медленной скользящей средней input ENUM_MA_METHOD method_MA_slow=MODE_SMA; //---- buffers ...
В книге приведен ряд вариантов по работе с величиной «канат». Среди них были выбраны следующие:
- Пересечение индикатора с нулевой линией.
- Торги только при совпадении всех трех расчетных величин: сила, подвижность, мастерство. Реализовано в качестве цветов главной линии.
- Пересечение индикатора с МА.
- По пересечению двух МА.
Индикатор МА (загружаемый через библиотеку MovingAverages.mqh) строится по значениям главной линии индикатора, находящейся в буферном массиве Buffer_calcLINE. Этот массив был добавлен для удобства доступа к данным перед передачей их в библиотеку функций по расчету МА.
В функции OnInit инициализируем основные данные для расчетов и построения индикатора. Обнуление переменных prev_rates_total и _tm_prev является важной частью для расчетов при случаях смены периода графика и других причин перезапуска индикатора. Значение _tm_prev отвечает за время последнего расчетного бара, с которого начнется расчет при следующем появлении бара. Параметр prev_rates_total сохраняет предыдущее значение rates_total (на предыдущем тике). Сравнивая его с текущим rates_total (количество баров или размер массива price[]), можно судить, что был пересчет данных, не все бары были загружены, делается перерасчет для предотвращения случаев догрузки пробелов в истории и, как следствие, неверное отображение данных на графике.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- сообщение в лог о первом запуске индикатора Print(__FUNCTION__+"\\ Initialization | _period: ",_period); //--- количество знаков после запятой текущего символа _digits=(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS); //--- точность отображения значений индикатора IndicatorSetInteger(INDICATOR_DIGITS,_digits); //--- установка имени индикатора, с отображением в окне индикатора IndicatorSetString(INDICATOR_SHORTNAME,"RopebyEricNaiman"); //--- INDICATOR_DATA - хранит данные для отрисовки //--- INDICATOR_COLOR_INDEX - хранит индексы цветов //--- INDICATOR_CALCULATIONS - хранит данные для промежуточных расчетов не предназначенных для отрисовки SetIndexBuffer(0,Buffer_main_bull,INDICATOR_DATA); // буфер данных гистограммы быков SetIndexBuffer(1,Buffer_color_bull,INDICATOR_COLOR_INDEX); // буфер данных цветов быков SetIndexBuffer(2,Buffer_main_bear,INDICATOR_DATA); // буфер данных гистограммы медведей SetIndexBuffer(3,Buffer_color_bear,INDICATOR_COLOR_INDEX); // буфер данных цветов медведей SetIndexBuffer(4,Buffer_mainline,INDICATOR_DATA); // буфер данных главной линии индикатора SetIndexBuffer(5,Buffer_mainline_color,INDICATOR_COLOR_INDEX); // буфер данных цветов главной линии индикатора SetIndexBuffer(6,Buffer_MAfast,INDICATOR_DATA); // буфер данных быстрой МА SetIndexBuffer(7,Buffer_MAslow,INDICATOR_DATA); // буфер данных медленной МА SetIndexBuffer(8,Buffer_calc,INDICATOR_CALCULATIONS); // буфер данных ценовых расчетов SetIndexBuffer(9,Buffer_calc_bull,INDICATOR_CALCULATIONS); // буфер расчетных данных быков SetIndexBuffer(10,Buffer_calc_bear,INDICATOR_CALCULATIONS); // буфер расчетных данных медведей SetIndexBuffer(11,Buffer_calcLINE,INDICATOR_CALCULATIONS); // буфер расчетных данных для МА //--- обнуление времени последнего рассчитанного бара и prev_rates_total (rates_total на предыдущем вызове // rates_total = размер массива price[]) _tm_prev=0; prev_rates_total=0; //--- return(INIT_SUCCEEDED); }
Далее идут все расчеты в функции OnCalculate для отображения данных на графике. Учитывая расчетную часть таблицы из книги на стр. 147, положительным изменением считается положительный результат разницы двух цен, цена считается ценой закрытия бара (при использовании цены _price=PRICE_CLOSE). Такая разница говорит или о бычьем настроении рынка (положительное изменение) или о медвежьем (отрицательное изменение). Далее такая разница будет считаться как «бар», состоящий из цены открытия, равной цене закрытия предыдущего бара от расчетного, и цены закрытия расчетного бара (i), определяемый функцией:
for(int i=1; i<bars_calc && !IsStopped(); i++) { ...
Для расчета трех основных показателей требуется взять массив цен в соответствии с настройкой _price и рассчитать с помощью оператора for значение по переменной _period. Подсчитать за этот период положительные изменения цен для быков и отрицательные для медведей, подсчитать количество таких изменений и найти их отношение, разделив сумму на количество:
- if(total_bull>0) Buffer_calc_bull[i]=sum_bull/total_bull; — для быков.
- if(total_bear>0) Buffer_calc_bear[i]=sum_bear/total_bear; — для медведей.
Ниже представлен расчет (вживую по графику) на примере гистограммы быков, медведей и главной линии с периодом _period=5:
Таким образом, в результате суммирования показаний быков и медведей на каждом баре получается величина «канат», используемая в дальнейшем для расчетов. В индикаторе это учтено и представлено в виде линии с тремя цветами, отображаемыми через индикаторный цветовой буфер Buffer_mainline_color[]. Ниже приведены расчеты в OnCalculate().
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, // размер массива price[] 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(time,true); //--- установка индексации массива как в таймсерии, самый младший индекс 0 имеет самое последнее известное расчетное значение в истории ArraySetAsSeries(open,true); ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(close,true); ArraySetAsSeries(Buffer_main_bull,true); ArraySetAsSeries(Buffer_color_bull,true); ArraySetAsSeries(Buffer_main_bear,true); ArraySetAsSeries(Buffer_color_bear,true); ArraySetAsSeries(Buffer_mainline,true); ArraySetAsSeries(Buffer_mainline_color,true); ArraySetAsSeries(Buffer_MAfast,true); ArraySetAsSeries(Buffer_MAslow,true); ArraySetAsSeries(Buffer_calc,true); ArraySetAsSeries(Buffer_calc_bull,true); ArraySetAsSeries(Buffer_calc_bear,true); ArraySetAsSeries(Buffer_calcLINE,true); //--- int copy=0; bars_calc=0; //--- расчет индикаторных данных //--- при prev_calculated = 0 рассчитываем все данные заново по всем барам, =0 равенство нулю может быть после разрыва в истории, при длительном разрыве связи с интернетом, к примеру if(prev_calculated==0) _tm_prev=0; //--- если предыдущий размер больше текущего, значит, был сбой и нужен пересчет всех данных if(prev_rates_total>rates_total) _tm_prev=0; if(_tm_prev<time[0]) // расчет при появлении нового бара { if(_tm_prev>0) // если индикатор уже имеет ранее расчетные данные { copy=TakeShift_byTime(Symbol(),PERIOD_CURRENT,_tm_prev); // получение смещение бара текущего символа по времени последнего расчетного бара if(copy<=0) // если смещение не найдено, расчеты отклоняются и повтор на следующем тике { return 0; } bars_calc=copy+1; // установка смещения бара для начала расчетов от текущего незакрытого бара индикатора //--- обнуление первого текущего незакрытого бара, т.е. данные по нему не рассчитываются Buffer_main_bull[0]=0.0; Buffer_color_bull[0]=5; // установка индекса цвета в номер 5 соответствует пустому цвету, поэтому цвет не отрисовывается Buffer_main_bear[0]=0.0; Buffer_color_bear[0]=5; // установка индекса цвета в номер 5 соответствует пустому цвету, поэтому цвет не отрисовывается Buffer_mainline[0]=0.0; Buffer_mainline_color[0]=5; // установка индекса цвета в номер 5 соответствует пустому цвету, поэтому цвет не отрисовывается Buffer_MAfast[0]=0.0; Buffer_MAslow[0]=0.0; Buffer_calc[0]=0.0; Buffer_calc_bull[0]=0.0; Buffer_calc_bear[0]=0.0; Buffer_calcLINE[0]=0.0; } else // если индикатор установлен в первый раз и значения не рассчитаны { bars_calc=Bars(Symbol(),PERIOD_CURRENT)-1; // смещение бара для начала расчетов устанавливается как общее количество баров -1 //--- обнуление всех данных по всем барам с целью предотвращения ошибок отрисовки for(int i=0; i<Bars(Symbol(),PERIOD_CURRENT) && !IsStopped(); i++) { Buffer_main_bull[i]=0.0; Buffer_main_bear[i]=0.0; Buffer_mainline[i]=0.0; Buffer_MAfast[i]=0.0; Buffer_MAslow[i]=0.0; Buffer_calc[i]=0.0; Buffer_calc_bull[i]=0.0; Buffer_calc_bear[i]=0.0; Buffer_calcLINE[i]=0.0; } } //--- если количество баров для расчетов индикатора меньше нуля, то прервать расчет if(bars_calc<0) return 0; //--- ограничение количества баров для расчетов по значению max_bars if(bars_calc>max_bars && max_bars!=0) bars_calc=max_bars; for(int i=1; i<bars_calc && !IsStopped(); i++) { //--- вычисление разницы котировок двух баров в соответствии с настройкой _price switch(_price) { case PRICE_CLOSE: Buffer_calc[i]=close[i]-close[i+1]; break; case PRICE_OPEN: Buffer_calc[i]=open[i]-open[i+1]; break; case PRICE_HIGH: Buffer_calc[i]=high[i]-high[i+1]; break; case PRICE_LOW: Buffer_calc[i]=low[i]-low[i+1]; break; case PRICE_MEDIAN: Buffer_calc[i]=((high[i]+low[i])/2)-((high[i+1]+low[i+1])/2); break; case PRICE_TYPICAL: Buffer_calc[i]=((high[i]+low[i]+close[i])/3)-((high[i+1]+low[i+1]+close[i+1])/3); break; case PRICE_WEIGHTED: Buffer_calc[i]=((high[i]+low[i]+close[i]+close[i])/4)-((high[i+1]+low[i+1]+close[i+1]+close[i+1])/4); break; default: return 0; } } //--- запуск перебора нерассчитанных баров до тех пор, пока не закончится цикл или не появится команда IsStopped=true на завершение программы (как в случае с удалением индикатора с графика) for(int i=1; i<=bars_calc && !IsStopped(); i++) { //--- обнуление данных sum_bull=0.0; // переменная суммы положительных изменений (для быков) за анализируемый период времени total_bull=0; // переменная количества положительных изменений за анализируемый период времени sum_bear=0.0; // переменная суммы отрицательных изменений (для медведей) за анализируемый период времени total_bear=0; // переменная количества отрицательных изменений за анализируемый период времени Buffer_main_bull[i]=0.0; Buffer_color_bull[i]=5; Buffer_main_bear[i]=0.0; Buffer_color_bear[i]=5; Buffer_mainline[i]=0.0; Buffer_mainline_color[0]=5; Buffer_calc_bull[i]=0.0; Buffer_calc_bear[i]=0.0; Buffer_calcLINE[i]=0.0; //--- прекратить расчет для бара, если он выходит за пределы имеющихся данных в соответствии с анализируемым периодом if(i>=(rates_total-_period)) continue; //--- перебор данных за анализируемый период (_period) от текущего бара вглубь истории for(int i2=i; i2<i+_period; i2++) { //--- расчет для быков if(Buffer_calc[i2]>0) { sum_bull+=Buffer_calc[i2]; // суммирование цен положительных баров ("сумма положительных изменений за анализируемый период времени") total_bull++; // подсчет количества положительных баров ("количество положительных изменений за анализируемый период времени") } //--- расчет для медведей if(Buffer_calc[i2]<0) { sum_bear+=Buffer_calc[i2]; // суммирование цен отрицательных баров ("сумма отрицательных изменений за анализируемый период времени") total_bear++; // подсчет количества отрицательных баров ("количество отрицательных изменений за анализируемый период времени") } } //--- расчет "мастерства быков", деление величины бара в пунктах на количество таких баров if(total_bull>0) Buffer_calc_bull[i]=sum_bull/total_bull; //--- расчет "мастерства медведей" if(total_bear>0) Buffer_calc_bear[i]=sum_bear/total_bear; //--- отрисовка гистограммы с заполнением цветов по категориям подтверждения сигнала if(draw_histogram) { //--- отрисовка гистограммы быков, деление величины бара в пунктах на количество таких баров if(total_bull>0) Buffer_main_bull[i]=sum_bull/total_bull; //--- отрисовка гистограммы медведей, деление величины бара в пунктах на количество таких баров if(total_bear>0) Buffer_main_bear[i]=sum_bear/total_bear; //--- 0 цвет гистограммы clrDarkGreen - цветовой индекс "только покупка", покупка с высокой категорией подтверждения //--- категория подтверждения - все три показателя указывают на бычью тенденцию //--- подвижность быков > подвижность медведей и сила быков > сила медведей и мастерство быков > мастерство медведей //--- подвижность - количество баров //--- сила - суммирование величины бара в пунктах //--- мастерство - средняя расчетная величина всех сумм баров за указанный период сила/подвижность if(total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) Buffer_color_bull[i]=0; else { //--- 1 цвет гистограммы clrMediumSeaGreen - цветовой индекс "возможна покупка", покупка со средней категорией подтверждения //--- категория подтверждения - при двух бычьих показателях и одном медвежьем, в любом сочетании if((total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i]))) Buffer_color_bull[i]=1; else { //--- 2 цвет гистограммы clrLightGreen - цветовой индекс "возможна покупка", покупка с низкой категорией подтверждения //--- категория подтверждения - при одном бычьем показателе и двух медвежьих, в любом сочетании if((total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || (total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i]))) Buffer_color_bull[i]=2; else { //--- 3 цвет гистограммы clrGray - цветовой индекс "покупка запрещена" //--- категория подтверждения - при отсутствующем бычьем показателе Buffer_color_bull[i]=3; } } } //--- 0 цвет гистограммы clrDarkRed - цветовой индекс "только продажа", продажа с высокой категорией подтверждения //--- категория подтверждения - все три показателя указывают на медвежью тенденцию if(total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) Buffer_color_bear[i]=0; else { //--- 1 цвет гистограммы clrIndianRed - цветовой индекс "возможна продажа", продажа со средней категорией подтверждения //--- категория подтверждения - при двух медвежьих показателях и одном бычьем, в любом сочетании if((total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i]))) Buffer_color_bear[i]=1; else { //--- 2 цвет гистограммы clrLightPink - цветовой индекс "возможна продажа", продажа с низкой категорией подтверждения //--- категория подтверждения - при одном медвежьем показателе и двух бычьих, в любом сочетании if((total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || (total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i]))) Buffer_color_bear[i]=2; else { //--- 3 цвет гистограммы clrGray - цветовой индекс "продажа запрещена" //--- категория подтверждения - при отсутствующем медвежьем показателе Buffer_color_bear[i]=3; } } } } //--- расчетное значение главной линии, суммирование мастерства медведей и быков Buffer_calcLINE[i]=(Buffer_calc_bull[i]+Buffer_calc_bear[i])*line_deviation; //--- отрисовка линии с заполнением цветов по категориям подтверждения сигнала // 0 - clrDarkGreen - цветовой индекс "только покупка", покупка с высокой категорией подтверждения // 1 - clrDarkRed - цветовой индекс "только продажа", продажа с высокой категорией подтверждения // 2 - clrGray - цветовой индекс "нет строгого подтверждения" if(draw_line) { //--- отрисовка значения главной линии, суммирование мастерства медведей и быков Buffer_mainline[i]=(Buffer_calc_bull[i]+Buffer_calc_bear[i])*line_deviation; //--- установка неопределенного цвета линии (2 - clrGray) Buffer_mainline_color[i]=2; //--- установка бычьего цвета линии (0 - clrDarkGreen) при совпадении всех трех бычьих показателях (bull>bear) if(total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_calc_bull[i])>MathAbs(Buffer_calc_bear[i])) Buffer_mainline_color[i]=0; //--- установка медвежьего цвета линии (1 - clrDarkRed) при совпадении всех трех медвежьих показателях (bear>bull) if(total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_calc_bull[i])<MathAbs(Buffer_calc_bear[i])) Buffer_mainline_color[i]=1; } } //--- расчет и отрисовка МА if(draw_MA_fast || draw_MA_slow) { //--- отключение индексации как в таймсериях для передачи в библиотеку MovingAverages.mqh (изменяем индексацию таким образом, что в конце массива - текущий бар истории) ArraySetAsSeries(Buffer_calcLINE,false); ArraySetAsSeries(Buffer_MAfast,false); ArraySetAsSeries(Buffer_MAslow,false); //--- перебор всех нерассчитанных баров. Перебор = Все бары (rates_total) - смещение бара от последнего известного расчетного времени _tm_prev (bars_calc) for(int i=rates_total-bars_calc; i<rates_total && !IsStopped(); i++) { //--- ограничение расчетов по заданному в параметрах max_bars, расчет только для заданного max_bars количества как разница количества всех баров (rates_total) минус установленное (max_bars) if(max_bars>0?(i<(rates_total-max_bars)):false) { //--- если текущий индекс i выходит за пределы разрешенного значения, то переходим к разрешенному индексу i=rates_total-max_bars; continue; } //--- обнуление массива в случае неполучения данных по МА Buffer_MAfast[i]=0.0; Buffer_MAslow[i]=0.0; //--- выбор метода расчета быстрой МА по параметру method_MA_fast if(draw_MA_fast) { switch(method_MA_fast) { case MODE_SMA: // Простое усреднение Buffer_MAfast[i]=SimpleMA(i,period_MA_fast,Buffer_calcLINE); // получение данных рассчитанной SimpleMA индекса i из библиотеки Include\\MovingAverages.mqh по буферу данных Buffer_calcLINE и периодом period_MA_fast break; case MODE_EMA: // Экспоненциальное усреднение Buffer_MAfast[i]=ExponentialMA(i,period_MA_fast,Buffer_MAfast[i-1],Buffer_calcLINE); break; case MODE_SMMA: // Сглаженное усреднение Buffer_MAfast[i]=SmoothedMA(i+period_MA_fast,period_MA_fast,Buffer_MAfast[i-1],Buffer_calcLINE); break; case MODE_LWMA: // Линейно-взвешенное усреднение Buffer_MAfast[i]=LinearWeightedMA(i+period_MA_fast,period_MA_fast,Buffer_calcLINE); break; default: return 0; } } //--- выбор метода расчета медленной МА по параметру method_MA_slow if(draw_MA_slow) { switch(method_MA_slow) { case MODE_SMA: // Простое усреднение Buffer_MAslow[i]=SimpleMA(i,period_MA_slow,Buffer_calcLINE); break; case MODE_EMA: // Экспоненциальное усреднение Buffer_MAslow[i]=ExponentialMA(i,period_MA_slow,Buffer_MAslow[i-1],Buffer_calcLINE); break; case MODE_SMMA: // Сглаженное усреднение Buffer_MAslow[i]=SmoothedMA(i,period_MA_slow,Buffer_MAslow[i-1],Buffer_calcLINE); break; case MODE_LWMA: // Линейно-взвешенное усреднение Buffer_MAslow[i]=LinearWeightedMA(i,period_MA_slow,Buffer_calcLINE); break; default: return 0; } } } //--- включение индексации как в таймсерии для отрисовки ArraySetAsSeries(Buffer_calcLINE,true); ArraySetAsSeries(Buffer_MAfast,true); ArraySetAsSeries(Buffer_MAslow,true); //--- обнуление данных МА для текущего бара, т.к. не рассчитываются Buffer_MAfast[0]=EMPTY_VALUE; Buffer_MAslow[0]=EMPTY_VALUE; Buffer_calcLINE[0]=EMPTY_VALUE; } //--- запоминаем время последнего расчетного бара _tm_prev=time[0]; } //--- return value of prev_calculated for next call prev_rates_total=rates_total; return(rates_total); }
Для удобства просмотра при включенном отображении линий и гистограммы сделано увеличение значений главной линии (значение главной линии * line_deviation), чтобы выйти за пределы гистограммы. Добавлено ограничение по количеству рассчитываемых баров (max_bars) для ускорения расчетов на малых периодах, таких как М1. Последний блок кода TakeShift_byTime используется для получения смещения бара по времени с целью определения количества баров, требуемых для расчетов в bars_calc.
Глава 2. Практическое применение индикатора «Канат» и построение эксперта
В данной главе рассмотрим написание эксперта EARopebyEricNaiman по индикатору «Канат» (название исходного кода индикатора — RopebyEricNaiman). Индикатор можно использовать как в отдельной стратегии на примере эксперта EARopebyEricNaiman, так и в качестве фильтра для определения направления тренда. В книге автором рассматривается несколько подходов к использованию данных, рассчитанных индикатором. Среди них в эксперте были выбраны следующие:
- Пересечение главной линии с 0 (main line cross zero). Пересечение вверх — покупка, пересечение вниз — продажа.
- Открытие при смене цвета главной линии (main line color) с серого на зеленый (покупка) или с серого на красный (продажа).
- Открытие при пересечении главной линии с быстрой МА (main line cross MAfast). Главная линия пересекает MA снизу вверх — покупка, сверху вниз — продажа.
Открытие по пересечению двух МА (two MA cross). Быстрая МА пересекает медленную МА снизу вверх — покупка, сверху вниз — продажа.
Помимо основных настроек, в эксперте сделана возможность отдельно настраивать 4 типа закрытия, соответствующие сигналам на открытие, но в обратном направлении по сравнению с типом открытой позиции:
//--- настройки закрытия позиции input string section_5="___ Close settings"; //--- закрытие по пересечении главной линии с нулевой / при BUY закрытие при пересечении сверху вниз input bool close1=true; // Close main line cross zero //--- закрытие при смене цвета на противоположный открытой позиции / при BUY закрытие при смене на красный input bool close2=false; // Close main line color //--- закрытие при пересечении главной с линией МА / при BUY закрытие при пересечении главной линии сверху вниз МА input bool close3=false; // Close main line cross MAfast //--- закрытие при пересечении двух МА / при BUY закрытие при пересечении быстрой МА сверху вниз медленной МА input bool close4=true; // Close two MA cross
Таким образом, открытие происходит по одному из выбранных методов в переменной trade_mode, а закрытие — по Stop Loss/Take Profit/«по одному из перечисленных выше». Весь исходный код эксперта и индикатора можно скачать и посмотреть в прикрепленных ниже файлах. В статье рассмотрим только основную расчетную часть сигналов на открытие и закрытие позиции.
- В блоке OnInit() выполняется инициализация основных переменных и самого индикатора RopebyEricNaiman.
- В блоке OnTick() содержится управляющий блок на открытие и закрытие позиции.
- В блоке расчета сигнала на открытие Check_Indi_Open() производится загрузка данных индикатора и поиск сигнала:
//+------------------------------------------------------------------+ //| Check_Indi_Open | //+------------------------------------------------------------------+ int Check_Indi_Open() { //--- объявление массивов для получения индикаторных данных int copy=0; double _arr_ind_1[]; double mafast[]; double mainline[]; double maslow[]; //--- с помощью функции switch выбирается метод открытия по параметру внешней переменной trade_mode switch((int)trade_mode) { case 0: //--- сравнение главной линии индикатора на двух последних барах, не включая текущий copy=Copy_indi_Buffer(RbEN_handle,4,1,2,_arr_ind_1,"RbEN"); if(copy!=2) return 4; if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]>0 && _arr_ind_1[1]<=0) { return 0; } if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]<0 && _arr_ind_1[1]>=0) { return 1; } break; case 1: //--- получение цветового индекса индикатора из индикаторного буфера №5 на двух последних барах, не включая текущий copy=Copy_indi_Buffer(RbEN_handle,5,1,2,_arr_ind_1,"RbEN"); if(copy!=2) return 5; if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]==0 && _arr_ind_1[1]!=0) { return 0; } if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]==1 && _arr_ind_1[1]!=1) { return 1; } break; case 2: //--- получение и сравнение значений mafast (МА по главной линии индикатора) и mainline (главная линия индикатора) на двух последних барах, не включая текущий copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN"); if(copy!=2) return 6; copy=Copy_indi_Buffer(RbEN_handle,4,1,2,mainline,"RbEN"); if(copy!=2) return 7; if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && mainline[0]>mafast[0] && mainline[1]<=mafast[1]) { return 0; } if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && mainline[0]<mafast[0] && mainline[1]>=mafast[1]) { return 1; } break; case 3: //--- получение и сравнение значений mafast (быстрой МА по главной линии индикатора) и maslow (медленной МА по главной линии индикатора) на двух последних барах, не включая текущий copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN"); if(copy!=2) return 8; copy=Copy_indi_Buffer(RbEN_handle,7,1,2,maslow,"RbEN"); if(copy!=2) return 9; if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE && maslow[0]<mafast[0] && maslow[1]>=mafast[1]) { return 0; } if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE && maslow[0]>mafast[0] && maslow[1]<=mafast[1]) { return 1; } break; default: return 3; } //--- return 2; }
В блоке Check_Indi_Close() выполняется перебор в соответствии с входными настройками всех 4-х методов закрытия открытой позиции:
//+------------------------------------------------------------------+ //| Check_Indi_Close | //+------------------------------------------------------------------+ int Check_Indi_Close() { //--- объявление массивов для получения индикаторных данных int copy=0; double _arr_ind_1[]; double mafast[]; double mainline[]; double maslow[]; _str_close=""; //--- получение и сравнение с нулевой линией главной линии на двух последних барах, не включая текущий if(close1) { copy=Copy_indi_Buffer(RbEN_handle,4,1,2,_arr_ind_1,"RbEN"); if(copy!=2) return 4; _str_close="Close main line cross zero"; if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]>0 && _arr_ind_1[1]<=0) { return 0; } if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]<0 && _arr_ind_1[1]>=0) { return 1; } } //--- получение цветового индекса индикатора из индикаторного буфера №5 на двух последних барах, не включая текущий if(close2) { copy=Copy_indi_Buffer(RbEN_handle,5,1,2,_arr_ind_1,"RbEN"); if(copy!=2) return 5; _str_close="Close main line color"; if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]==0 && _arr_ind_1[1]!=0) { return 0; } if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && _arr_ind_1[0]==1 && _arr_ind_1[1]!=1) { return 1; } } //--- получение и сравнение значений mafast (МА по главной линии индикатора) и mainline (главная линия индикатора) на двух последних барах, не включая текущий if(close3) { copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN"); if(copy!=2) return 6; copy=Copy_indi_Buffer(RbEN_handle,4,1,2,mainline,"RbEN"); if(copy!=2) return 7; _str_close="Close main line cross MAfast"; if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && mainline[0]>mafast[0] && mainline[1]<=mafast[1]) { return 0; } if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && mainline[0]<mafast[0] && mainline[1]>=mafast[1]) { return 1; } } //--- получение и сравнение значений mafast (быстрая МА по главной линии индикатора) и maslow (медленная МА по главной линии индикатора) на двух последних барах, не включая текущий if(close4) { copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN"); if(copy!=2) return 8; copy=Copy_indi_Buffer(RbEN_handle,7,1,2,maslow,"RbEN"); if(copy!=2) return 9; _str_close="Close two MA cross"; if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE && maslow[0]<mafast[0] && maslow[1]>=mafast[1]) { return 0; } if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE && maslow[0]>mafast[0] && maslow[1]<=mafast[1]) { return 1; } } //--- return 2; }
- Блок Copy_indi_Buffer() сделан для получения данных индикатора через функцию CopyBuffer().
- Блок TakeLastOpenTime() служит для получения времени последней открытой позиции для сравнения (в OnTick) с временем открытия бара, чтобы предотвратить многократное открытие позиции на одном баре.
- OpenPosition() — функция на открытие позиции.
- Copy_Time() копирует время указанного бара.
- CloseAllPosition() закрывает все позиции.
После написания эксперта переходим к оптимизации входных параметров в следующей главе.
Глава 3. Оптимизация входных параметров эксперта по индикатору «Канат»
Перед запуском эксперта следует произвести оптимизацию основных входных параметров. В качестве примера выбран символ EURUSD H1 2005-2015 года (генетический алгоритм оптимизации). Для каждого из четырех типов открытия сделана отдельная оптимизация.
1. trade_mode = Close main line cross zero (пересечение главной линии с 0: пересечение вверх — покупка, пересечение вниз — продажа).
Оптимизационные параметры:
Значение Старт Шаг Стоп Шаги StopLoss 0 50 10000 201 TakeProfit 0 50 10000 201 _period 1 1 200 200 close1 false true 2 Всего проходов 16160400
Результаты оптимизации и лучшего теста можно посмотреть в приложенном архиве optimization.zip в папке "EURUSD H1 2005-2015\test1 - main line cross zero\".
2. trade_mode = Close main line color (открытие при смене цвета главной линии с серого на зеленый (покупка) или с серого на красный (продажа)).
Оптимизационные параметры:
Значение Старт Шаг Стоп Шаги StopLoss 0 50 10000 201 TakeProfit 0 50 10000 201 _period 1 1 200 200 close2 false true 2 Всего проходов 16160400
Результаты оптимизации и лучшего теста можно посмотреть в приложенном архиве optimization.zip в папке "EURUSD H1 2005-2015\test2 - main line color\".
3. trade_mode = main line cross MAfast (открытие при пересечении главной линии с быстрой МА: главная линия пересекает MA снизу вверх — покупка, сверху вниз — продажа).
Оптимизационные параметры:
Значение Старт Шаг Стоп Шаги StopLoss 0 50 10000 201 TakeProfit 0 50 10000 201 _period 1 1 200 200 period_MA_fast 1 1 300 300 close3 false true 2 Всего проходов 4848120000 Результаты оптимизации и лучшего теста можно посмотреть в приложенном архиве optimization.zip в папке "EURUSD H1 2005-2015\test3 - main line cross MAfast\".
4. trade_mode = two MA cross (открытие по пересечению двух МА: быстрая МА пересекает медленную МА снизу вверх — покупка, сверху вниз — продажа).
Оптимизационные параметры:
Значение Старт Шаг Стоп Шаги StopLoss 0 50 10000 201 TakeProfit 0 50 10000 201 _period 1 1 200 200 period_MA_fast 1 1 300 300 period_MA_slow 1 1 400 400 close4 false true 2 Всего проходов 1939248000000 Результаты оптимизации и лучшего теста можно посмотреть в приложенном архиве optimization.zip в папке "EURUSD H1 2005-2015\test4 - two MA cross\".
Заключение
Результаты оптимизации говорят о жизнеспособности данной стратегии, при том что эксперт построен на чистой логике работы индикатора без применения каких-либо дополнительных функций по управлению капиталом. Говоря о чистой логике, имеется ввиду отмеченная автором стратегия определения тренда, основанная на статической оценке движения быков и медведей в указанном диапазоне времени. С помощью данного индикатора можно выделить опорные ключевые точки входа в рынок, таким образом, индикатор применим и как фильтр в своей стратегии, и как базовый сигнал по открытию сделок.
В прикрепленных ниже файлах вы сможете найти исходный код индикатора и эксперта, по которому можете сделать собственные разработки в области программирования и трейдинга. Данная стратегия была реализована и показана в малых ее направлениях использования (базовые сигналы на вход/выход) и уже на начальных этапах показала рабочий потенциал.
![Andrey Nikolaev Andrey Nikolaev](https://c.mql5.com/avatar/avatar_na2.png)
![Модуль торговых сигналов по системе Билла Вильямса](https://c.mql5.com/2/20/MQL5_wizard_ru.png)
![Защита от ложных срабатываний торгового робота](https://c.mql5.com/2/21/avatar.png)
![Изучаем класс CCanvas. Сглаживание и тени](https://c.mql5.com/2/21/CCanvas_class_Standard_library_MetaTrader5.png)
![Еще раз о картах Кохонена](https://c.mql5.com/2/20/jursbu_z7z.png)
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования