
Эффективные алгоритмы усреднения с минимальным лагом и их использование в индикаторах и экспертах
Введение
В механических торговых системах, построенных на базе индикаторов, в основе которых лежат какие-либо алгоритмы усреднения, их создатели редко когда используют больше одного какого-нибудь алгоритма усреднения. Во многих случаях, если алгоритм эксперта построен на основе обычных мувингов и индикаторов, входящих в стандартный набор индикаторов терминала MetaTrader 4, дело ограничивается четырьмя стандартными алгоритмами: простым, экспоненциальным, сглаженным и линейно-взвешенным усреднениями. Такой подход сильно ограничивает возможности эксперта.
Одна и та же торговая система с использованием различных алгоритмов усреднения может показывать весьма внушительные отличия торговых показателей. Причём никогда нельзя сказать заранее, какие из имеющихся в наличии алгоритмов усреднения обеспечат максимальную прибыльность торговой системы. Так что гораздо разумнее будет строить код с возможностью использования в нём абсолютно различных алгоритмов усреднения, выбор которых можно осуществлять посредством изменения значений внешних переменных эксперта. В конечном итоге при таком подходе дело сводится к замене индикаторов, которые использует эксперт, на самостоятельно написанные с более гибкой настройкой выбора алгоритмов усреднения. Таким образом, данный подход можно разделить на три этапа:
1. Пишется рабочий код эксперта на основе стандартных мувингов и индикаторов, входящих в комплект технических индикаторов клиентского терминала MetaTrader 4.
2. Пишутся пользовательские индикаторы по описаниям стандартных индикаторов с возможностью использования более гибкой замены алгоритмов сглаживания.
3. Делается замена обращений к техническим индикаторам на обращения к этим пользовательским индикаторам с вытаскиванием внешних переменных этих индикаторов во внешние переменные эксперта.
В данной статье я бы хотел коснуться темы написания более универсальных индикаторов с возможностью (если можно так выразиться) горячей замены алгоритмов усреднения, которые используется в этих индикаторах. Статья является продолжением статьи "Эффективные алгоритмы усреднения с минимальным лагом и их использование в индикаторах", так что прежде, чем приступить к её изучению, читателю следует внимательно ознакомиться и с предыдущей статьeй этого цикла.
Универсальная функция усреднения
В своей предыдущей статье я ознакомил читателей с пятью функциями усреднения. Для большей полноты комплекта к этим функциям следовало бы добавить ещё и MASeries() с классическими алгоритмами усреднения, что я сейчас и сделаю:
double MASeries ( int number, int MA_Method, int MaxBar, int limit, int period, double series, int bar, int& reset )
Функция в плане её использования абсолютно аналогична предыдущим пяти функциям, так что в каких-либо подробных комментариях не нуждается. Программный код этой функции представлен файлом MASeries.mqh.
Теперь на базе этих шести функций можно построить универсальную функцию усреднения, которую я назвал SmoothXSeries() и разместил в файле SmoothXSeries.mqh. Как и предыдущие функции эта функция объявляется директивой #include < >:
#include <SmoothXSeries.mqh>
В плане внешних переменных эта функция аналогична функции JJMASeries(), но появляется новая переменная идентификатора алгоритма усреднения SmoothMode:
double SmoothXSeries ( int number,int SmoothMode, int din, int MaxBar, int limit, int Phase, int Length, double Series, int bar, int& reset )
Варьированием значения этого параметра SmoothMode от нуля до восьми и достигают выбора требуемого алгоритма усреднения:
// 0 : JJMA // 1 : JurX // 2 : ParMA // 3 : LRMA // 4 : T3 // 5 : SMA // 6 : EMA // 7 : SSMA // 8 : LWMA
Вполне естественно, что переменные din и Phase оказываются задействованными только для тех алгоритмов усреднения, для которых они были определены первоначально. Прежде, чем использовать эту функцию в коде индикатора, следует произвести инициализацию переменных этой функции и распределить память для них. Для этого в блоке инициализации индикатора необходимо сделать обращение к функции SmoothXSeriesResize(). В качестве значения её внешней переменной Size следует сделать количество обращений к функции SmoothXSeries() в коде индикатора
//Десять обращений к функции SmoothXSeriesResize() в коде индикатора SmoothXSeriesResize(10);
Теперь, имея универсальный алгоритм усреднения SmoothXSeries(), можно приступать к построению кода индикаторов.
Универсальный мувинг
Любой мувинг(от англ. moving - скользящая) получается сглаживанием какой-нибудь ценовой таймсерии. В своей предыдущей статье я познакомил читателей с функцией PriceSeries() для выбора значений ценового ряда таймсерии. Вся задача построения мувинга сводится к обработке этих значений ценового ряда функцией SmoothXSeries() и передача их в индикаторный буфер. Вот вариант реализации кода:
/* Для работы индикатора следует положить файлы SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+X================================================================X+ //| X1MA.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в основном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвет индикатора #property indicator_color1 Red //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА +-------------------------------------------------+ extern int Smooth_Mode = 0; // Выбор алгоритма сглаживания 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length = 11; // глубина сглаживания extern int Phase = 100; // параметр, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Shift = 0; // cдвиг индикатора вдоль оси времени extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- +------------------------------------------------------------------------------+ //---- буферы double XMA[]; //---- переменные bool INIT; int StartBar; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Объявление функции SmoothXSeries //----+ Объявление функции SmoothXSeriesResize //----+ Объявление функции SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Объявление функции PriceSeries //----+ Объявление функции PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| X1MA initialization function | //+X================================================================X+ int init() { //----+ //---- установка стиля изображения индикатора SetIndexStyle(0, DRAW_LINE); //---- определение буфера для подсчёта SetIndexBuffer(0, XMA); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0, 0.0); //---- установка алертов на недопустимые значения внешних переменных JJMASeriesAlert (0, "Length", Length); JJMASeriesAlert (1, "Phase", Phase); PriceSeriesAlert(Input_Price_Customs); //----+ Изменение размеров буферных переменных функции //SmoothXSeries, number = 1(Одно обращение к функции SmoothXSeries) if (SmoothXSeriesResize(1) != 1) { INIT = false; return(0); } //---- инициализация переменных if (Smooth_Mode > 0 && Smooth_Mode < 9) StartBar = Length; else StartBar = 30; //---- установка номера бара, //начиная с которого будет отрисовываться индикатор SetIndexDrawBegin(0, StartBar); //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //---- завершение инициализации INIT = true; return(0); //----+ } //+X================================================================X+ //| X1MA iteration function | //+X================================================================X+ int start() { //----+ //---- Получение количества всех баров int Bars_ = Bars - 1; //---- проверка завершения инициализации и //проверка количества баров на достаточность для расчёта if (!INIT || Bars_ <= StartBar) return(-1); //---- Введение переменных с плавающей точкой double Price, xma; //---- Введение целых переменных и получение //количества уже посчитанных баров int reset, MaxBar, limit, bar, counted_bars = IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars < 0) return(-1); //---- последний посчитанный бар должен быть пересчитан if (counted_bars > 0) counted_bars--; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт новых баров limit = Bars_ - counted_bars; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт всех баров MaxBar = Bars_; //----+ основной цикл расчёта индикатора for(bar = limit; bar >= 0; bar--) { //---- Получение исходного значения ценового ряда Price = PriceSeries(Input_Price_Customs, bar); //---- X1MA сглаживание исходного значения ценового ряда, //---- Обращение к функции SmoothXSeries за номером 0, //параметры Phase и Length не меняются на каждом баре (din = 0) xma = SmoothXSeries(0, Smooth_Mode, 0, MaxBar, limit, Phase, Length, Price, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); XMA[bar] = xma; //---- } //---- завершение вычислений значений индикатора return(0); //----+ } //+X--------------------+ <<< The End >>> +--------------------X+В этом индикаторе выбор алгоритма усреднения осуществляется посредством изменения значения переменной Smooth_Mode.
Универсальный мувинг с использованием двойного усреднения
Эффективность работы с таким мувингом можно значительно улучшить, если произвести дополнительное сглаживание полученного индикатора всё той же функцией SmoothXSeries()
/* Для работы индикатора следует положить файлы SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+X================================================================X+ //| X2MA.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в основном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвет индикатора #property indicator_color1 Lime //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА +-------------------------------------------------+ extern int Smooth_Mode1 = 0; // Выбор алгоритма 1 сглаживания 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length1 = 9; // глубина сглаживания extern int Phase1 = 100; // параметр, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Smooth_Mode2 = 0; // Выбор алгоритма 2 сглаживания 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length2 = 5; // глубина сглаживания extern int Phase2 = 100; // параметр, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Shift = 0; // cдвиг индикатора вдоль оси времени extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- +------------------------------------------------------------------------------+ //---- буферы double X2MA[]; //---- переменные bool INIT; int StartBar, StartBar1, StartBar2; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Объявление функции SmoothXSeries //----+ Объявление функции SmoothXSeriesResize //----+ Объявление функции SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Объявление функции PriceSeries //----+ Объявление функции PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| X2MA initialization function | //+X================================================================X+ int init() { //----+ //---- установка стиля изображения индикатора SetIndexStyle(0, DRAW_LINE); //---- определение буфера для подсчёта SetIndexBuffer(0, X2MA); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0, 0.0); //---- установка алертов на недопустимые значения внешних переменных JJMASeriesAlert (0, "Length1", Length1); JJMASeriesAlert (1, "Phase1", Phase1); JJMASeriesAlert (0, "Length2", Length2); JJMASeriesAlert (1, "Phase2", Phase2); PriceSeriesAlert(Input_Price_Customs); //----+ Изменение размеров буферных переменных функции //SmoothXSeries, number = 2(Два обращения к функции SmoothXSeries) if (SmoothXSeriesResize(2) != 2) { INIT = false; return(0); } //---- инициализация переменных if (Smooth_Mode1 > 0 && Smooth_Mode1 < 9) StartBar1 = Length1; else StartBar1 = 30; if (Smooth_Mode2 > 0 && Smooth_Mode2 < 9) StartBar2 = Length2; else StartBar2 = 30; StartBar = StartBar1 + StartBar2; //---- установка номера бара, //начиная с которого будет отрисовываться индикатор SetIndexDrawBegin(0, StartBar); //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //---- завершение инициализации INIT = true; return(0); //----+ } //+X================================================================X+ //| X2MA iteration function | //+X================================================================X+ int start() { //----+ //---- Получение номера последнего бара int Bars_ = Bars - 1; //---- проверка завершения инициализации и //проверка количества баров на достаточность для расчёта if (!INIT || Bars_ <= StartBar) return(-1); //---- Введение переменных с плавающей точкой double Price, x1ma, x2ma; //---- Введение целых переменных и получение //количества уже посчитанных баров int reset, MaxBar1, MaxBar2, limit, bar, counted_bars = IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars < 0) return(-1); //---- последний подсчитанный бар должен быть пересчитан if (counted_bars > 0) counted_bars--; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт новых баров limit = Bars_ - counted_bars; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт всех баров MaxBar1 = Bars_; MaxBar2 = MaxBar1 - StartBar1; //----+ основной цикл расчёта индикатора for(bar = limit; bar >= 0; bar--) { //---- Получение исходного значения ценового ряда Price = PriceSeries(Input_Price_Customs, bar); //---- X1MA сглаживание исходного значения ценового ряда, //---- Обращение к функции SmoothXSeries за номером 0, //параметры Phase и Length не меняются на каждом баре (din = 0) x1ma = SmoothXSeries(0, Smooth_Mode1, 0, MaxBar1, limit, Phase1, Length1, Price, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); //---- X2MA сглаживание полученного индикатора, //---- Обращение к функции SmoothXSeries за номером 1, //параметры Phase и Length не меняются на каждом баре (din = 0) x2ma = SmoothXSeries(1, Smooth_Mode2, 0, MaxBar2, limit, Phase2, Length2, x1ma, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); //---- X2MA[bar] = x2ma; //---- } //----+ завершение вычислений значений индикатора return(0); //----+ } //+X--------------------+ <<< The End >>> +--------------------X+Конечно, итоговый индикатор будет иметь некоторую задержку, по сравнению с оригиналом, но количество ложных сигналов, получаемых таким мувингом, будет существенно ниже, что с лихвой эту задержку скомпенсирует.
Получившийся индикатор можно значительно улучшить, если превратить непрерывный ряд значений, который он может принимать, в квантованный (дискретный). Это делается с помощью достаточно простого алгоритма:
//----+ нормализация полученного значения x2ma double Norma = Step * Point; //---- x2ma /= Norma; x2ma = NormalizeDouble(x2ma, 0); x2ma *= Norma;Переменная Step представляет собой целый внешний параметр индикатора, который определяет шаг дискретизации значений полученного мувинга в пунктах. Приводить весь код этого индикатора в тексте статьи нецелесообразно, читатель может самостоятельно ознакомиться с ним, используя прикреплённый к статье индикатор X2DigMa.mq4.
Практические рекомендации по оптимизации экспертов, использующих индикатор X2DigMa.mq4
Данный мувинг имеет достаточно большое количество внешних переменных, и поэтому любого эксперта, сделанного на основе этого индикатора, можно весьма недурно подогнать под какой угодно рынок. Однако формальная подгонка параметров эксперта - это далеко не самый оптимальный способ его программирования для дальнейшей работы. Следовало бы немного поподробнее остановиться на нюансах работы с внешними переменными такого мувинга в эксперте. Итак, допустим мы имеем эксперта, в котором все внешние переменные мувинга X2DigMA.mq4 сделаны внешними переменными эксперта.
extern int Smooth_Mode1 = 0; extern int Length1 = 9; extern int Phase1 = 100; extern int Smooth_Mode2 = 0; extern int Length2 = 5; extern int Phase2 = 100; extern int Step = 10; extern int Input_Price_Customs = 0;Переменная Smooth_Mode1 принимает значение от нуля и до восьми, но оптимизировать значение этой переменной в тестере стратегий с использованием генетического алгоритма не стоит! Гораздо лучше будет сделать восемь независимых оптимизаций для каждого значения этой переменной. Значение аналогичной переменной для повторного сглаживания Smooth_Mode2 лучше зафиксировать равным нулю. В таком случае в качестве повторного сглаживания будет использоваться алгоритм JMA усреднения, который имеет самый минимальный лаг и в качестве дополнительного усреднения во многих ситуациях даёт самые лучшие результаты.
Параметры Phase1 и Phase2, которые используются только в JMA и T3 усреднениях, лучше тоже зафиксировать на значении равном ста(100). Параметр Length2 может принимать какие угодно значения, но во многих ситуациях и в абсолютно разных экспертах самыми оптимальными зачастую оказываются одни и те же значения из ряда 3, 5, 7, 9, 11. Перебора этих значений параметра Length2, как правило, более чем достаточно. Параметр Step сильно зависит от рынка, на котором работает эксперт и периода графика, но зачастую стабилизируется на одних и тех же значениях. Лучшими значениями параметра Input_Price_Customs оказываются ноль и девять. В итоге для досконального исследования остаётся всего один параметр Length1, значения которого могут быть какими угодно.
Универсальная MACD диаграмма
С помощью предложенной мной функции SmoothXSeries() можно построить любой индикатор классического, технического анализа, например диаграмму MACD, представляющую собой график двух индикаторов. Первый представляет диаграмму разности двух мувингов, а второй - скользящее среднее этой разности.
/* Для работы индикатора следует положить файлы SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+X================================================================X+ //| XMACD.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в отдельном окне #property indicator_separate_window //---- количество индикаторных буферов #property indicator_buffers 2 //---- цвета индикатора #property indicator_color1 Blue #property indicator_color2 Magenta //---- толщина линии диаграммы #property indicator_width1 2 //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int MACD_Mode = 0; // Выбор алгоритма сглаживания для MACD 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int MACD_Phase = 100; extern int FastXMA = 12; extern int SlowXMA = 26; extern int Signal_Mode = 0; // Выбор алгоритма сглаживания для сигнальной линии //0 - JJMA, 1 - JurX, 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Signal_Phase = 100; extern int SignalXMA = 9; extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- индикаторные буферы double XMacdBuffer[]; double XSignalBuffer[]; //---- переменные bool INIT; int StartBar, StartBar1, StartBar2; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Объявление функции SmoothXSeries //----+ Объявление функции SmoothXSeriesResize //----+ Объявление функции SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Объявление функции PriceSeries //----+ Объявление функции PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| XMACD indicator initialization function | //+X================================================================X+ int init() { //----+ //---- установка стиля изображения индикатора SetIndexStyle(0, DRAW_HISTOGRAM); SetIndexStyle(1, DRAW_LINE); //---- Установка формата точности (количество знаков //после десятичной точки) для визуализации значений индикатора IndicatorDigits(Digits + 1); //---- определение буферов для подсчёта SetIndexBuffer(0, XMacdBuffer); SetIndexBuffer(1, XSignalBuffer); //---- имена для окон данных и лэйбы для субъокон IndicatorShortName(StringConcatenate ("XMACD(", FastXMA, ",", SlowXMA, ",", SignalXMA, ")")); SetIndexLabel(0, "XMACD"); SetIndexLabel(1, "XSignal"); //---- установка алертов на недопустимые значения внешних переменных JJMASeriesAlert (0, "FastXMA", FastXMA); JJMASeriesAlert (0, "SlowXMA", SlowXMA); JJMASeriesAlert (0, "SignalXMA", SignalXMA); //---- JJMASeriesAlert (1, "MACD_Phase", MACD_Phase); JJMASeriesAlert (1, "Signal_Phase", Signal_Phase); PriceSeriesAlert(Input_Price_Customs); //---- Изменение размеров буферных переменных функции //SmoothXSeries, number = 3(Три обращения к функции SmoothXSeries) if (SmoothXSeriesResize(3) != 3) { INIT = false; return(0); } //---- инициализация переменных if (MACD_Mode > 0 && MACD_Mode < 9) StartBar1 = MathMax( FastXMA, SlowXMA); else StartBar1 = 30; //---- if (Signal_Mode > 0 && Signal_Mode < 9) StartBar2 = SignalXMA; else StartBar2 = 30; //---- StartBar = StartBar1 + StartBar2; //---- SetIndexDrawBegin(0, StartBar1); SetIndexDrawBegin(1, StartBar); //---- завершение инициализации INIT = true; return(0); //----+ } //+X================================================================X+ //| XMACD indicator iteration function | //+X================================================================X+ int start() { //----+ //---- Получение номера последнего бара int Bars_ = Bars - 1; //---- проверка завершения инициализации и //проверка количества баров на достаточность для расчёта if (!INIT || Bars_ <= StartBar) return(-1); //---- Введение переменных с плавающей точкой double Price, FastXMA_, SlowXMA_, XMACD, SignalXMA_; //---- Введение целых переменных и получение //количества уже посчитанных баров int reset, MaxBar1, MaxBar2, limit, bar, counted_bars = IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars < 0) return(-1); //---- последний подсчитанный бар должен быть пересчитан if (counted_bars > 0) counted_bars--; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт новых баров limit = Bars_ - counted_bars; //---- определение номера самого старого бара, //начиная с которого будет произедён пересчёт всех баров MaxBar1 = Bars_; MaxBar2 = MaxBar1 - StartBar1; //----+ основной цикл расчёта индикатора for(bar = limit; bar >= 0; bar--) { //---- Получение исходного значения ценового ряда Price = PriceSeries(Input_Price_Customs, bar); //---- FastXMA сглаживание исходного значения ценового ряда, //---- Обращение к функции SmoothXSeries за номером 0, //параметры Phase и Length не меняются на каждом баре (din = 0) FastXMA_ = SmoothXSeries(0, MACD_Mode, 0, MaxBar1, limit, MACD_Phase, FastXMA, Price, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); //---- SlowXMA сглаживание исходного значения ценового ряда, //---- Обращение к функции SmoothXSeries за номером 1, //параметры Phase и Length не меняются на каждом баре (din = 0) SlowXMA_ = SmoothXSeries(1, MACD_Mode, 0, MaxBar1, limit, MACD_Phase, SlowXMA, Price, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); //---- if(bar < MaxBar2) XMACD = FastXMA_ - SlowXMA_; //---- SignalXMA сглаживание полученной диаграммы XMACD, //---- Обращение к функции SmoothXSeries за номером 2, //параметры Phase и Length не меняются на каждом баре (din = 0) SignalXMA_ = SmoothXSeries(2, Signal_Mode, 0, MaxBar2, limit, Signal_Phase, SignalXMA, XMACD, bar, reset); //---- проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); //---- XMacdBuffer[bar] = XMACD; XSignalBuffer[bar] = SignalXMA_; } return(0); //----+ } //+X----------------------+ <<< The End >>> +-----------------------X+Логика работы с таким индикатором в эксперте во многом аналогична тому, что я писал выше, но только в данной ситуации значение переменной Signal_Mode гораздо логичнее будет подвергнуть генетической оптимизации.
Заключение
С помощью обращения к функции SmoothXSeries() можно построить практически любой индикатор технического анализа, возможности которого зачастую оказываются выше, чем у его классического аналога. Конечно, всё это требует определённого опыта в написании индикаторов, но результат всё-таки стоит затраченного труда.




- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Вот вариант функции, которая делает то, что вам надо:
Эта функция принимает буфер с вашим ценовым рядом InputIndBuffer[] и отдаёт сглаженный ценовой ряд в другой индикаторный буфер OutputIndBuffer[]. Вот вариант обращения к функции:
Николай,
Спасибо Вам огромное за потраченное время. У меня, конечно, нет потребности в подобной функции, но ее изучение натолкнуло меня на изыскания другого рода. Как бы там ни было - главное результат. А результат есть. Я был не прав. Ваша библиотека замечательно работает. Проблемы были в моих ошибках. Извините что отнял у Вас время. И спасибо Вам за Ваши труды. Удачи в чемпионате!
Столкнулся сегодня с проблемой компилирования индикаторов, описанной несколькими постами ниже. Она возникает из-за системы безопасности Windows7, ограничивающей права пользователей. Поэтому компиляцию индикаторов и экспертов, которые ссылаются на другие файлы необходимо проводить из учетной записи Администратор. Для ее разблокировки необходимо вести в командной строке следующее:
net user Администратор /active:yes
Далее «Пуск» - «Сменить пользователя» - «Администратор» и компилируем уже без ошибок.