
Эффективные алгоритмы усреднения с минимальным лагом и их использование в индикаторах
Введение
Я думаю, что нет никакой необходимости объяснять значительную
роль алгоритмов сглаживания для технического анализа и торговых
систем. Достаточно взглянуть на код почти любого индикатора,
чтобы обнаружить в нём в явном или неявном виде какой-нибудь
алгоритм усреднения. Если присмотреться более внимательно,
то обнаружится, что в большинстве торгово-аналитических платформ
и клиентских терминалов применяются самые простые, хотя далеко
не самые эффективные, алгоритмы усреднения и большинство индикаторов
построены на базе этих алгоритмов. На настоящий момент разработаны гораздо более эффективные алгоритмы сглаживания, но попытка их применения в индикаторах в виду их значительной сложности обычно приводит к тому, что терпения программиста хватает в лучшем случае на один - два индикатора, которые далеко не всегда работают корректно. После этого обычно улетучивается всякое желание работать в этом направлении дальше. Самое же основное преимущество простых средних в том, что они всегда имеются в наличии в виде простых пользовательских функций, которые можно применить, где угодно и когда угодно.
Предмет статьи
В данной статье автор хотел бы предложить трейдерам, знакомым с языком MQL4, достаточно эффективные алгоритмы усреднения с минимальным лагом, которые представлены в виде достаточно простых пользовательских функций. Использовать данные функции не многим сложнее, чем технические индикаторы. Функции написаны уже достаточно давно и качество их работы проверялось достаточно долго, но каких-либо нарушений в работе, сбоев и некорректных вычислений обнаружено не было. Итак, мы рассмотрим следующие алгоритмы:
- JJMASeries () - алгоритм адаптивного JMA сглаживания;
- JLiteSeries() - алгоритм JMA сглаживания без алгоритма адаптации;
- JurXSeries () - алгоритм ультралинейного сглаживания, взятый из индикатора JRSX;
- ParMASeries() - алгоритм сглаживания на основе параболической аппроксимации;
- LRMASeries () - алгоритм сглаживания на основе линейной регрессии;
- T3Series () - алгоритм сглаживания на основе алгоритма Тильсона.
Реализация функций сглаживания
Функции представлены в виде файлов: JJMASeries.mqh, JLiteSeries.mqh, JurXSeries. mqh, ParMASeries.mqh, LRMASeries.mqh, T3Series.mqh.
Сами обращения к этим функциям абсолютно одинаковы, отличие
состоит только в отсутствии у отдельных функций некоторых внешних
переменных. Обычно такие функции строят для обработки пользовательских
и индикаторных массивов, которые выступают в качестве внешних
переменных, но, на мой взгляд, это не всегда удобно и гораздо
лучше было выполнить такие функции для обработки обычных переменных,
а не массивов. В таком случае можно за один цикл вычислений сделать
неограниченное число сглаживаний с помощью этих алгоритмов!
Я думаю, что будет абсолютно излишним в статье представлять
сам код функций. Он будет интересен только для тех, кто сам собирается
делать аналогичные функции на основе каких-нибудь других алгоритмов.
Нас же будет интересовать только алгоритм обращения к этим
функциям в тексте индикатора, то есть практическое применение
этих функций.
Своё знакомство начнём с функции JJMASeries():
double JJMASeries(int number, int din, int MaxBar, int limit, int Phase, int Length, double series, int bar, int& reset)
Файл JJMASeries.mqh содержит четыре функции: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert() и JMA_ErrDescr(). Помимо функций файл содержит переменные, которые объявлены как глобальные.
Функция JJMASeries() предназначена для использования алгоритма JMA при написании любых индикаторов теханализа и экспертов, для замены расчёта классического усреднения на этот алгоритм. Функция не работает, если параметр limit принимает значение, равное нулю! Все индикаторы, сделанные мною для JJMASeries, выполнены с учётом этого ограничения. Файл следует положить в папку MetaTrader\experts\include\ . Следует учесть, что если значение переменной bar больше, чем значение переменной MaxBar, то функция JJMASeries() возвращает на этом баре значение равное нулю! И, следовательно, такое значение не может присутствовать в знаменателе какой-либо дроби в расчёте индикатора! На последующих тридцати барах функция JJMASeries() тоже возвращает ноль!
Эта версия функции JJMASeries() поддерживает экспертов при её использовании
в пользовательских индикаторах, к которым обращается эксперт.
Кроме того, эта версия функции JJMASeries() поддерживает экспертов
при её использовании в коде индикатора, который полностью помещён
в код эксперта с сохранением всех операторов цикла и переменных!
При написании индикаторов и экспертов с использованием функции
JJMASeries не рекомендуется переменным давать имена, начинающиеся
с nJMA... или dJMA... Функция JJMASeries() может быть использована во внутреннем
коде других пользовательских функций, но при этом следует учитывать
тот факт, что в каждом обращении к такой пользовательской функции
у каждого обращения к JJMASeries() должен быть свой уникальный номер
(number). Данная версия функции JJMASeries() предназначена для обработки
переменных, связанных с массивами таймсерий текущего графика!
Если применить эту функцию к обработке переменных, вычисленных
на основе массивов таймсерий с других графиков, то в расчёте
будет присутствовать ошибка!
Входные параметры:
- number - порядковый номер обращения к функции JJMASeries() в тексте
индикатора (0, 1, 2, 3 и так далее);
- din - параметр, позволяющий изменять параметры Length и Phase на каждом
баре. 0 - запрет изменения параметров, любое другое значение
- разрешение;
- MaxBar - максимальное значение, которое может принимать номер
рассчитываемого бара (bar). Обычно равно Bars-1-period; Где "period"
- это количество баров, на которых исходная величина series не рассчитывается;
- limit - Количество ещё не посчитанных баров плюс один или номер
последнего непосчитанного бара. Должно быть обязательно равно
Bars-IndicatorCounted()-1;
- Length - глубина сглаживания;
- Phase - параметр, изменяющийся в пределах -100 .. . +100, влияет на качество
переходного процесса;
- series - входной параметр, по которому производится расчёт функции
JJMASeries();
- bar - номер рассчитываемого бара, параметр должен изменяться
оператором цикла от максимального значения к нулевому. Причём
его максимальное значение всегда должно равняться значению
параметра limit!
Выходные параметры:
- JMASeries() - значение функции JMA. При значениях параметра bar больше, чем MaxBar-30 функция JJMASeries() всегда возвращает ноль!
- reset - параметр, возвращающий по ссылке значение, отличенное от 0, если произошла ошибка в расчёте функции, и 0, если расчёт прошёл нормально. Этот параметр может быть только переменной, но не значением!
Инициализация функции
Перед обращениями к функции JJMASeries(), когда количество уже посчитанных
баров равно 0, (а ещё лучше это сделать в блоке инициализации
пользовательского индикатора или эксперта) следует изменить
размеры внутренних буферных переменных функции. Для этого необходимо
обратиться к переменным функции JJMASeries() через вспомогательную
функцию JJMASeriesResize() со следующими параметрами: JJMASeriesResize(number+1);
необходимо сделать параметр number (MaxJMA.number) равным количеству
обращений к функции JJMASeries, то есть на единицу больше, чем максимальный
number. Помимо изменения размеров буферов функции JJMASeries() в блоке
инициализации можно проверить значения входных параметров
индикатора Length и Phase, являющихся входными параметрами функции
JJMASeries(), на соответствие диапозону их изменения с помощью функции
JJMASeriesAlert():
JJMASeriesAlert(int Number, string name, int ExternVar)
- Number - параметр принимающий два значения: 0 - для проверки входного
параметра ExternVar на соответствие диапозону изменения входного
параметра Length функции JJMASeries() и 1 - для проверки входного параметра
ExternVar на соответствие диапазону изменения входного параметра
Phase функции JJMASeries();
- name - стринговое имя входного параметра ExternVar для подачи алерта;
- ExternVar - входной параметр индикатора
Индикация ошибок
При отладке индикаторов и экспертов их коды могут содержать
ошибки, для выяснения причин которых следует смотреть логфайл.
Все ошибки функция JJMASeries() пишет в лог файл в папке \MetaTrader\EXPERTS\LOGS\.
Если перед обращением к функции JJMASeries() в коде, который предшествовал
функции, возникла MQL4-ошибка, то функция запишет в лог файл код
ошибки и содержание ошибки. Если при выполнении функции JJMASeries()
в алгоритме JJMASeries() произошла MQL4-ошибка, то функция также запишет
в лог файл код ошибки и содержание ошибки. При неправильном
задании номера number обращения к функции JJMASeries() или неверном
определении размера буферных переменных nJJMAResize. Size в лог файл
будет записаны сообщения о неверном определении этих параметров.
Также в лог файл пишется информация при неправильном определении
параметра limit.
Если при выполнении функции инициализации init() произошёл сбой
при изменении размеров буферов функции JJMASeries, то функция JJMASeriesResize()
запишет в лог файл информацию о неудачном изменении размеров.
Если при обращении к функции JJMASeries() через внешний оператор
цикла была нарушена правильная последовательность изменения
параметра bar, то в лог файл будет записана и эта информация. Следует
учесть, что некоторые ошибки программного кода будут порождать
дальнейшие ошибки в его исполнении и поэтому, если функция JJMASeries()
пишет в лог файл сразу несколько ошибок, то устранять их следует
в порядке времени возникновения. В правильно написанном индикаторе
функция JJMASeries() может делать записи в лог файл только при нарушениях
работы операционной системы. Исключение составляет запись
изменения размеров буферных переменных при перезагрузке индикатора
или эксперта, которая происходит при каждом вызове функции
init(). Все MQL4-ошибки в лог файл пишутся с помощью функции JMA_ErrDescr(),
которая сбрасывает в лог файл код и содержание ошибки по её
коду, полученному с помощью функции GetLastError().
Пример обращения к функции JJMASeries() (двойное JMA сглаживание входной
цены):
/* Для работы индикатора следует положить файлы JJMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+------------------------------------------------------------------+ //| J2JMA.mq4 | //| JMA code: Copyright © 2005, Jurik Research | //| http://www.jurikres.com/ | //| MQL4 JJMASeries+J2JMA: Copyright © 2006, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в главном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвет индикатора #property indicator_color1 Magenta //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int Length1 = 5; // глубина первого сглаживания extern int Length2 = 5; // глубина второго сглаживания // параметр первого сглаживания, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Phase1 = 100; // параметр второго сглаживания, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Phase2 = 100; // cдвиг индикатора вдоль оси времени extern int Shift = 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.) */ extern int Input_Price_Customs = 0; //---- индикаторные буферы double J2JMA[]; //---- переменные с плавающей точкой double Temp_Series; //----+ Введение функции JJMASeries //----+ Введение функции JJMASeriesResize //----+ Введение функции JJMASeriesAlert //----+ Введение функции JMA_ErrDescr #include <JJMASeries.mqh> //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| J2JMA indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- определение стиля исполнения графика SetIndexStyle (0, DRAW_LINE); //---- 1 индикаторный буфер использован для счёта SetIndexBuffer(0, J2JMA); //---- горизонтальный сдвиг индикаторной линии SetIndexShift (0, Shift); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0, 0); //---- имя для окон данных и лэйба для субъокон IndicatorShortName ("J2JMA(Length1=" + Length1 + ", Phase1=" + Phase1 + ", Length2=" + Length2 + ", Phase2=" + Phase2 + ", Shift=" + Shift + ")"); SetIndexLabel (0, "J2JMA"); //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //----+ Изменение размеров буферных переменных функции JJMASeries, //nJMAnumber=2(Два обращения к функции JJMASeries) if(JJMASeriesResize(2) != 2) return(-1); //---- установка алертов на недопустимые значения внешних переменных JJMASeriesAlert (0,"Length1", Length1); JJMASeriesAlert (0,"Length2", Length2); JJMASeriesAlert (1,"Phase1", Phase1 ); JJMASeriesAlert (1,"Phase2", Phase2 ); PriceSeriesAlert(Input_Price_Customs); //---- завершение инициализации return(0); } //+------------------------------------------------------------------+ //| J2JMA iteration function | //+------------------------------------------------------------------+ int start() { //---- Проверка количества баров на достаточность для дальнейшего расчёта if(Bars - 1 < 61) return(0); //----+ Введение целых переменных и получение уже подсчитанных баров int reset, MaxBar1, MaxBar2, counted_bars = IndicatorCounted(); //---- проверка на возможные ошибки if(counted_bars < 0) return(-1); //---- последний подсчитанный бар должен быть пересчитан //---- (без этого пересчёта для counted_bars функция JJMASeries будет // работать некорректно!!!) if(counted_bars > 0) counted_bars--; //---- определение номера самого старого бара, начиная с которого будет // произедён пересчёт новых баров int limit = Bars - counted_bars - 1; MaxBar1 = Bars - 1; MaxBar2 = MaxBar1 - 30; //----+ ОСНОВНОЙ ЦИКЛ ВЫЧИСЛЕНИЯ ИНДИКАТОРА for(int bar = limit; bar >= 0; bar--) { // Обращение к функции PriceSeries для получения входной цены Series Temp_Series = PriceSeries(Input_Price_Customs, bar); // Два обращения к функции JJMASeries за номерами 0, 1. Параметры //nJMA.Phase и nJMA.Length //не меняются на каждом баре (nJMA.din=0) //(Во втором обращении параметр nJMA.MaxBar уменьшен на 30 т. к. это //повторное JMA сглаживание) Temp_Series = JJMASeries(0,0,MaxBar1,limit,Phase1,Length1, Temp_Series,bar,reset); // проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); Temp_Series = JJMASeries(1,0,MaxBar2,limit,Phase2,Length2, Temp_Series,bar,reset); // проверка на отсутствие ошибки в предыдущей операции if(reset != 0) return(-1); J2JMA[bar] = Temp_Series; } //---- завершение вычислений значений индикатора return(0); } //+--------------------------------------------------------+
Таким образом в применении этой функции можно выделить следующие моменты:
1. Объявление функций, входящих в состав файла JJMASeries. mqh строкой #include <JJMASeries.mqh> в начале текста индикатора. Объявляются переменные и четыре функции: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert() и JMA_ErrDescr();
2. Изменение размеров буферных элементов, с которыми работает функция JJMASeries() с помощью функции JJMASeriesResize() в блоке инициализации;
3. Проверка на корректность значений внешних переменных индикатора, которые являются внешними переменными функции JJMASeries() с помощью функции JJMASeriesAlert() в блоке инициализации;
4. Сами обращения к функции JJMASeries(), сделанные через оператор цикла с соответствующими проверками на ошибку.
Другие функции
Алгоритм обращения к остальным функциям абсолютно аналогичен рассмотренному выше алгоритму, но имеются некоторые отличия по количеству внешних переменных, присутствующих в функциях:
JJMASeries (int number, int din, int MaxBar, int limit, int Phase, int Length, double series, int bar, int&reset) JLiteSeries(int number, int din, int MaxBar, int limit, int Phase, int Length, double series, int bar, int&reset) JurXSeries (int number, int din, int MaxBar, int limit, int Length, double series, int bar, int&reset) T3Series (int number, int din, int MaxBar, int limit, int Phase, int Length, double series, int bar, int&reset ) ParMASeries(int number, int MaxBar, int limit, int period, double series, int bar, int&reset) LRMASeries (int number, int MaxBar, int limit, int period, double series, int bar, int&reset )
Следует учесть, что функции JJMASeries() и JLiteSeries() несовместимы в одном эксперте или индикаторе! На самом деле в файле JLiteSeries. mqh помещён тот же самый JMA код с названием функции JJMASeries() без адаптации! Для замены в эксперте или индикаторе функции JJMASeries() на JLiteSeries() достаточно поменять строку #include<JJMASeries. mqh> на строку #include<JLiteSeries. mqh>. Все обращения к функциям файла JLiteSeries. mqh идут как обращения к функциям, идентичным обращениям к функциям файла JJMASeries. mqh.
Остальные функции абсолютно совместимы в тексте одного индикатора
или эксперта. В функциях ParMASeries() и LRMASeries() значение внешней переменной
period ограниченно величиной 501. Если необходимы большие значения,
то следует поменять первые (не нулевые!) измерения буферов
dParMA.TempBuffer[][501] и dParMA.TEMPBUFFER[][501] для функции ParMASeries() или dLRMA. TempBuffer[][501]
и dLRMA.TEMPBUFFER[][501] для функции LRMASeries() в файлах ParMASeries. mqh и LRMASeries.
mqh соотвественно.
Функциии JurXSeries()
Пример обращения к функциии JurXSeries() (Ультралинейное сглаживание входной цены дополнительным JMA сглаживанием):
/* Для работы индикатора следует положить файлы JurXSeries.mqh, JJMASeries.mqh, PriceSeries.mqh, в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ В основе этого индикатора лежит алгоритм сглаживания от индикатора JRSX. Конечный результат этого алгоритма имеет некоторое сходство с двойным JMA сглаживанием, но в силу большей простоты менее совершенен. */ //+------------------------------------------------------------------+ //| JJurX.mq4 | //| Copyright © 2006, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в главном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвет индикатора #property indicator_color1 Gold //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int JurX_Length = 5; // глубина JurX сглаживания extern int JJMA_Length = 4; // глубина JJMA сглаживания // параметр JJMA сглаживания, изменяющийся в пределах -100 ... +100, // влияет на качество переходного процесса; extern int JJMA_Phase = -100; extern int Shift = 0; // cдвиг индикатора вдоль оси времени /* Выбор цен, по которым производится расчёт индикатора (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.) */ extern int Input_Price_Customs = 0; //---- индикаторные буферы double Ind_Buffer[]; //---- переменные с плавающей точкой double Price,JurX,JJurX,Error; //+------------------------------------------------------------------+ //----+ Введение функции JJMASeries //----+ Введение функции JJMASeriesResize //----+ Введение функции JJMASeriesAlert //----+ Введение функции JMA_ErrDescr #include <JJMASeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции JurXSeries //----+ Введение функции JurXSeriesResize //----+ Введение функции JurXSeriesAlert //----+ Введение функции JurX_ErrDescr #include <JurXSeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| JJurX indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- определение стиля исполнения графика SetIndexStyle (0,DRAW_LINE); //---- 1 индикаторный буфер использован для счёта SetIndexBuffer(0,Ind_Buffer); //---- горизонтальный сдвиг индикаторной линии SetIndexShift (0, Shift); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0,0); //---- имя для окон данных и лэйба для субъокон IndicatorShortName ("JJurX( JurX_Length="+JurX_Length+", Shift="+Shift+")"); SetIndexLabel (0, "JJurX"); //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //----+ Изменение размеров буферных переменных функции JurXSeries, // nJurXnumber=2 //(Два обращения к функции JurXSeries) if (JurXSeriesResize(2)!=2)return(-1); //----+ Изменение размеров буферных переменных функции JJMASeries, // nJMAnumber=1 //(Одно обращение к функции JJMASeries) if (JJMASeriesResize(1)!=1)return(-1); //---- установка алертов на недопустимые значения внешних переменных JurXSeriesAlert(0,"JurX_Length",JurX_Length); JJMASeriesAlert(0,"JJMA_Length",JJMA_Length); JJMASeriesAlert(1,"JJMA_Phase",JJMA_Phase); PriceSeriesAlert(Input_Price_Customs); //---- завершение инициализации return(0); } //+------------------------------------------------------------------+ //| JJurX iteration function | //+------------------------------------------------------------------+ int start() { //---- Проверка количества баров на достаточность для дальнейшего расчёта if (Bars-1<JurX_Length+32)return(0); //----+ Введение целых переменных и получение уже подсчитанных баров int reset,MaxBar,counted_bars=IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars<0)return(-1); //---- последний подсчитанный бар должен быть пересчитан //(без этого пересчёта для counted_bars функция JurXSeries будет // работать некорректно!!!) if (counted_bars>0) counted_bars--; //---- определение номера самого старого бара, начиная с которого // будет произедён пересчёт новых баров int limit=Bars-counted_bars-1; //---- определение номера самого старого бара, начиная с которого // будет произедён пересчёт всех баров MaxBar=Bars-1; //----+ ОСНОВНОЙ ЦИКЛ ВЫЧИСЛЕНИЯ ИНДИКАТОРА for(int bar=limit;bar>=0;bar--) { //----+ Обращение к функции PriceSeries для получения входной // цены Series Price=PriceSeries(Input_Price_Customs,bar); //----+ Одно обращение к функции JurXSeries за номером 0. //Параметр nJJurX.Length не меняется на каждом баре (nJurXdin=0) JurX=JurXSeries(0,0,MaxBar,limit,JurX_Length,Price,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); //----+ определение ошибки вычисления параметра JurX //----+ второе обращение к функции JurXSeries за номером 1. //Параметр nJJurX.Length не меняtтся на каждом баре (nJurXdin=0) Error=JurXSeries(1,0,MaxBar,limit,JurX_Length,100,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); if(Error==0)Error=100; JurX*=100/Error; //----+ Обращение к функции JJMASeries за номерам 0. // Параметры nJMA.Phase и nJMA.Length не меняются на каждом баре // (nJMA.din=0) JJurX=JJMASeries(0,0,MaxBar,limit,JJMA_Phase,JJMA_Length,JurX,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); Ind_Buffer[bar]=JJurX; } //---- завершение вычислений значений индикатора return(0); } //+-------------------------------------------------------------------------+
В данном примере следует обратить внимание на тот факт, что помимо
усреднения входной цены функция JurXSeries() усредняет ещё и константу!
Если полученный результат усреднения разделить на значение
самой константы, то мы получим ошибку сглаживания. Для более
точного результата сглаживания ценового ряда, следует результат
сглаживания разделить на эту ошибку. Что и было сделано в этом
случае. В следующих двух случаях происходит раздельное сглаживание
числителя и знаменателя дроби и поэтому необходимости в подобной
процедуре нет. Для других функций сглаживания такой ошибки
не возникает.
Пример обращений к функциям JJMASeries() и JurXSeries() (Аналог индикатора
CCI с дополнительным JMA сглаживанием):
/* Для работы индикатора следует положить файлы JJMASeries.mqh JurSeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+------------------------------------------------------------------+ //| JCCIX.mq4 | //| Copyright © 2006, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в отдельном окне #property indicator_separate_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвета индикатора #property indicator_color1 BlueViolet //---- параметры горизонтальных уровней индикатора #property indicator_level1 0.5 #property indicator_level2 -0.5 #property indicator_level3 0.0 #property indicator_levelcolor MediumBlue #property indicator_levelstyle 4 //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int JJMA.Length = 8; // глубина JJMA сглаживания входной цены // глубина JurX сглаживания полученного индикатора extern int JurX.Length = 8; // параметр, изменяющийся в пределах -100 ... +100, влияет // на качество переходныx процессов сглаживания extern int JJMA.Phase = 100; /* Выбор цен, по которым производится расчёт индикатора (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.) */ extern int Input_Price_Customs = 0; //---- индикаторные буферы double Ind_Buffer1[]; //---- целые константы int w; //+------------------------------------------------------------------+ //----+ Введение функции JJMASeries //----+ Введение функции JJMASeriesResize //----+ Введение функции JJMASeriesAlert //----+ Введение функции JMA_ErrDescr #include <JJMASeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции JurXSeries //----+ Введение функции JurXSeriesResize //----+ Введение функции JurXSeriesAlert //----+ Введение функции JurX_ErrDescr #include <JurXSeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| JCCIX initialization function | //+------------------------------------------------------------------+ int init() { //---- стили изображения индикатора SetIndexStyle(0,DRAW_LINE); //---- 1 индикаторный буфер использован для счёта. SetIndexBuffer(0,Ind_Buffer1); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0,0); //---- имена для окон данных и лэйбы для субъокон SetIndexLabel(0,"JCCIX"); IndicatorShortName("JCCIX(JJMA.Length="+JJMA.Length+", JurX.Length"+ JurX.Length+")"); //---- Установка формата точности (количество знаков после десятичной точки) //для визуализации значений индикатора IndicatorDigits(2); //----+ Изменение размеров буферных переменных функции JurXSeries, // nJurXnumber=2 //(Два обращения к функции JurXSeries) if (JurXSeriesResize(2)!=2)return(-1); //----+ Изменение размеров буферных переменных функции JJMASeries, // nJMAnumber=1 //(Одно обращение к функции JJMASeries) if (JJMASeriesResize(1)!=1)return(-1); //---- установка алертов на недопустимые значения внешних переменных JurXSeriesAlert (0,"JurX.Length",JurX.Length); JJMASeriesAlert (0,"JJMA.Length",JJMA.Length); JJMASeriesAlert (1,"JJMA.Phase",JJMA.Phase); PriceSeriesAlert(Input_Price_Customs); //---- установка номера бара, начиная с которого будет отрисовываться // индикатор SetIndexDrawBegin(0,JurX.Length+31); //---- инициализация коэффициентов для расчёта индикатора if (JurX.Length>5) w=JurX.Length-1; else w=5; //---- завершение инициализации return(0); } //+------------------------------------------------------------------+ //| JCommodity Channel IndexX | //+------------------------------------------------------------------+ int start() { //---- Введение переменных с плавающей точкой double price,Jprice,JCCIX,UPCCI,DNCCI,JUPCCIX,JDNCCIX; //----+ Введение целых переменных и получение уже подсчитанных баров int reset,MaxBar,MaxBarJ,limit,counted_bars=IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars<0)return(-1); //---- последний подсчитанный бар должен быть пересчитан //---- (без этого пересчёта для counted_bars функции JJMASeries //и JurXSeries будут работать некорректно!!!) if (counted_bars>0) counted_bars--; //---- определение номера самого старого бара, начиная с которого будет //произедён пересчёт новых баров limit=Bars-counted_bars-1; //---- определение номера самого старого бара, начиная с которого будет //произедён пересчёт всех баров MaxBar=Bars-1; MaxBarJ=MaxBar-30; //---- корекция стартового расчётого бара в цикле if(limit>=MaxBar)limit=MaxBar; for(int bar=limit; bar>=0; bar--) { //----+ Обращение к функции PriceSeries для получения входной // цены Series price=PriceSeries(Input_Price_Customs, bar); //+--------------------------------------------------------------- //----+ Одно обращение к функции JJMASeries за номерам 0 //----+ Параметры nJMA.Phase и nJMA.Length не меняются на каждом // баре (nJMA.din=0) //+---------------------------------------------------------------+ Jprice=JJMASeries(0,0,MaxBar,limit,JJMA.Phase,JJMA.Length,price, bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); //+---------------------------------------------------------------+ UPCCI=price-Jprice; DNCCI=MathAbs(UPCCI); //----+ Два обращения к функции JurXSeries за номерами 0 и 1. Параметр nJJurXLength не //меняtтся на каждом баре (nJurXdin=0) //----+ проверка на отсутствие ошибки в предыдущей операции JUPCCIX=JurXSeries(0,0,MaxBarJ,limit,JurX.Length,UPCCI,bar,reset); if(reset!=0)return(-1); JDNCCIX=JurXSeries(1,0,MaxBarJ,limit,JurX.Length,DNCCI,bar,reset); if(reset!=0)return(-1); //----+ if (bar>MaxBarJ-w)JCCIX=0; else if (JDNCCIX!=0) { JCCIX=JUPCCIX/JDNCCIX; if(JCCIX>1)JCCIX=1; if(JCCIX<-1)JCCIX=-1; } else JCCIX=0; Ind_Buffer1[bar]=JCCIX; //----+ } //---- return(0); } //+-------------------------------------------------------------------+
Следует обратить внимание на тот факт, что после двух сглаживаний
функцией JurXSeries(), одно из полученных значений проверяется на
неравенство нулю, по той причине, что оно является знаменателем
дроби!
Пример обращений к функциям JJMASeries() и иJurXSeries (Аналог индикатора
RSI с дополнительным JMA сглаживанием):
/* Для работы индикатора следует положить файлы JurXSeries.mqh JJMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+------------------------------------------------------------------+ //| JJRSX.mq4 | //| MQL4 JJRSX: Copyright © 2006, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в отдельном окне #property indicator_separate_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвета индикатора #property indicator_color1 BlueViolet //---- параметры горизонтальных уровней индикатора #property indicator_level1 0.5 #property indicator_level2 -0.5 #property indicator_level3 0.0 #property indicator_levelcolor MediumBlue #property indicator_levelstyle 4 //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int Length = 8; // глубина JurX сглаживания индикатора // глубина JJMA сглаживания полученного индикатора extern int Smooth = 3; // параметр, изменяющийся в пределах -100 ... +100, влияет на //качество переходныx процессов сглаживания extern int Phase = 100; /* Выбор цен, по которым производится расчёт индикатора (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.) */ extern int Input_Price_Customs = 0; //---- индикаторные буферы double Ind_Buffer[]; //---- целые переменные int w; //+------------------------------------------------------------------+ //----+ Введение функции JJMASeries //----+ Введение функции JJMASeriesResize //----+ Введение функции JJMASeriesAlert //----+ Введение функции JMA_ErrDescr #include <JJMASeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции JurXSeries //----+ Введение функции JurXSeriesResize //----+ Введение функции JurXSeriesAlert //----+ Введение функции JurX_ErrDescr #include <JurXSeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| JJRSX initialization function | //+------------------------------------------------------------------+ int init() { //---- стили изображения индикатора SetIndexStyle(0,DRAW_LINE); //---- 1 индикаторныQ буфер использован для счёта. SetIndexBuffer(0,Ind_Buffer); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0,0); //---- имена для окон данных и лэйбы для субъокон SetIndexLabel(0,"JRSX"); IndicatorShortName("JRSX(Length="+Length+", Input_Price_Customs="+ Input_Price_Customs+")"); //---- Установка формата точности (количество знаков после десятичной // точки) для визуализации значений индикатора IndicatorDigits(2); //----+ Изменение размеров буферных переменных функции JurXSeries, nJurXnumber=2 //(Два обращения к функции JurXSeries) if (JurXSeriesResize(2)!=2)return(-1); //----+ Изменение размеров буферных переменных функции JJMASeries, nJMAnumber=1 //(Одно обращение к функции JJMASeries) if (JJMASeriesResize(1)!=1)return(-1); //---- установка алертов на недопустимые значения внешних переменных JurXSeriesAlert (0,"Length",Length); JJMASeriesAlert (0,"Smooth",Smooth); JJMASeriesAlert (1,"Phase",Phase); PriceSeriesAlert(Input_Price_Customs); //---- установка номера бара, начиная с которого будет отрисовываться индикатор SetIndexDrawBegin(0,Length+31); //---- корекция недопустимого значения параметра Length if(Length<1)Length=1; //---- инициализация коэффициентов для расчёта индикатора if (Length>5) w=Length-1; else w=5; //---- завершение инициализации return(0); } //+------------------------------------------------------------------+ //| JJRSX iteration function | //+------------------------------------------------------------------+ int start() { //---- Введение переменных с плавающей точкой double dPrice,dPriceA,UPJRSX,DNJRSX,JRSX,JJRSX; //----+ Введение целых переменных и получение уже подсчитанных баров int bar,limit,reset,MaxBar,MaxBarJ,counted_bars=IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars<0)return(-1); //---- последний подсчитанный бар должен быть пересчитан if (counted_bars>0) counted_bars--; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт всех баров MaxBar=Bars-2; MaxBarJ=MaxBarJ-w-1; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт новых баров limit=Bars-counted_bars-1; //----+ if (limit>MaxBar){limit=MaxBar;Ind_Buffer[MaxBar]=0.0;} for(bar=limit;bar>=0;bar--) { //----+ два обращения к функции PriceSeries для получения разницы // входных цен dPrice dPrice = PriceSeries(Input_Price_Customs, bar)- PriceSeries(Input_Price_Customs, bar+1); //----+ dPriceA=MathAbs(dPrice); //----+ Два обращения к функции JurXSeries за номерами 0 и 1. // Параметр nJJurXLength //не меняtтся на каждом баре (nJurXdin=0) //проверка на отсутствие ошибки в предыдущей операции UPJRSX=JurXSeries(0,0,MaxBar,limit,Length,dPrice, bar,reset); if(reset!=0)return(-1); DNJRSX=JurXSeries(1,0,MaxBar,limit,Length,dPriceA,bar,reset); if(reset!=0)return(-1); //----+ if (bar>MaxBar-w)JRSX=0; else if (DNJRSX!=0){JRSX=UPJRSX/DNJRSX; if(JRSX>1)JRSX=1; if(JRSX<-1)JRSX=-1;}else JRSX=0; //+---------------------------------------------------------------+ //----+ Одно обращение к функции JJMASeries за номерам 0 //----+ Параметры nJMA.Phase и nJMA.Length не меняются на каждом // баре (nJMA.din=0) //+---------------------------------------------------------------+ JJRSX=JJMASeries(0,0,MaxBarJ,limit,Phase,Smooth,JRSX,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); //+---------------------------------------------------------------+ Ind_Buffer[bar]=JJRSX; } //---- завершение вычислений значений индикатора return(0); } //+------------------------------------------------------------------+
Функции T3Series()
Пример обращения к функции T3Series() (Три полосы Боллинджера с дополнительным T3 сглаживанием):
/* Для работы индикатора следует положить файлы T3Series.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+------------------------------------------------------------------+ //| T3.6Bollinger Bands.mq4 | //| Copyright © 2006, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в главном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 7 //---- цвета индикатора #property indicator_color1 Gray #property indicator_color2 Red #property indicator_color3 Blue #property indicator_color4 Lime #property indicator_color5 Blue #property indicator_color6 Red #property indicator_color7 Gray //---- стиль линий индикатора #property indicator_style1 4 #property indicator_style2 2 #property indicator_style3 4 #property indicator_style4 4 #property indicator_style5 4 #property indicator_style6 2 #property indicator_style7 4 //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА // период усреднения J2Bollinger Bands extern int Bands_Period = 100; extern double Bands_Deviations = 2.0; // девиатация extern int MA_method = 0; // метод усреднения // глубина сглаживания полученного Moving Avereges extern int MA_Smooth = 20; // глубина сглаживания полученных Bollinger Bands extern int Bands_Smooth = 20; // параметр сглаживания, изменяющийся в пределах -100 ... +100, // влияет на качество переходного процесса; extern int Smooth_Curvature = 100; // cдвиг индикатора вдоль оси времени extern int Bands_Shift = 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 High, 12-Heiken Ashi Low, 13-Heiken Ashi Open, 14-Heiken Ashi Close.)*/ extern int Input_Price_Customs = 0; //---- индикаторные буферы double UpperBuffer3 []; double UpperBuffer2 []; double UpperBuffer1 []; double T3MovingBuffer[]; double LowerBuffer1 []; double LowerBuffer2 []; double LowerBuffer3 []; double Series_buffer []; //+------------------------------------------------------------------+ //----+ Введение функции T3Series //----+ Введение функции T3SeriesResize //----+ Введение функции T3SeriesAlert //----+ Введение функции T3_ErrDescr #include <T3Series.mqh> //+------------------------------------------------------------------+ //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| T3.6Bollinger Bands initialization function | //+------------------------------------------------------------------+ int init() { //---- определение стиля исполнения графика SetIndexStyle(0,DRAW_LINE); SetIndexStyle(1,DRAW_LINE); SetIndexStyle(2,DRAW_LINE); SetIndexStyle(3,DRAW_LINE); SetIndexStyle(4,DRAW_LINE); SetIndexStyle(5,DRAW_LINE); SetIndexStyle(6,DRAW_LINE); //---- 4 индикаторных буфера использованы для счёта IndicatorBuffers(8); SetIndexBuffer(0,UpperBuffer3 ); SetIndexBuffer(1,UpperBuffer2 ); SetIndexBuffer(2,UpperBuffer1 ); SetIndexBuffer(3,T3MovingBuffer); SetIndexBuffer(4,LowerBuffer1 ); SetIndexBuffer(5,LowerBuffer2 ); SetIndexBuffer(6,LowerBuffer3 ); SetIndexBuffer(7,Series_buffer); //---- установка значений индикатора, которые не будут видимы на графике SetIndexEmptyValue(0,0); SetIndexEmptyValue(1,0); SetIndexEmptyValue(2,0); SetIndexEmptyValue(3,0); SetIndexEmptyValue(4,0); SetIndexEmptyValue(5,0); SetIndexEmptyValue(6,0); //---- установка номера бара, начиная с которого будет отрисовываться // индикатор int drawbegin=100+Bands_Shift; SetIndexDrawBegin(0,drawbegin); SetIndexDrawBegin(1,drawbegin); SetIndexDrawBegin(2,drawbegin); SetIndexDrawBegin(3,drawbegin); SetIndexDrawBegin(4,drawbegin); SetIndexDrawBegin(5,drawbegin); SetIndexDrawBegin(6,drawbegin); //---- горизонтальный сдвиг индикаторных линий SetIndexShift (0, Bands_Shift); SetIndexShift (1, Bands_Shift); SetIndexShift (2, Bands_Shift); SetIndexShift (3, Bands_Shift); SetIndexShift (4, Bands_Shift); SetIndexShift (5, Bands_Shift); SetIndexShift (6, Bands_Shift); //---- имя для окон данных и лэйба для субъокон IndicatorShortName ("T3.4Bollinger Bands( Period="+Bands_Period+ ", Deviations="+Bands_Deviations+")"); SetIndexLabel (0, "Upper3 Bands"); SetIndexLabel (1, "Upper2 Bands"); SetIndexLabel (2, "Upper1 Bands"); SetIndexLabel (4, "Lower1 Bands"); SetIndexLabel (5, "Lower2 Bands"); SetIndexLabel (6, "Lower3 Bands"); string Moving; switch(MA_method) { case 0: Moving= "T3SMA";break; case 1: Moving= "T3EMA";break; case 2: Moving="T3SSMA";break; case 3: Moving="T3LWMA";break; default: Moving="T3SMA"; } SetIndexLabel (3, "Moving Avereges "+Moving+" ("+Bands_Period+")"); //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //----+ Изменение размеров буферных переменных функции T3Series, //nT3.number=7(Семь обращений к функции T3Series) if (Bands_Smooth<=1){if (T3SeriesResize(1)!=1)return(-1);} else if (T3SeriesResize(7)!=7)return(-1); //---- установка алертов на недопустимые значения внешних переменных T3SeriesAlert(0,"MA_Smooth",MA_Smooth); T3SeriesAlert(0,"Bands_Period",Bands_Period); PriceSeriesAlert(Input_Price_Customs); if((MA_method<0)||(MA_method>3)) Alert("Параметр MA_method должен быть от 0 до 3" + " Вы ввели недопустимое " +MA_method+ " будет использовано 0"); //---- корекция недопустимого значения параметра Bands_Period if(Bands_Period<1)Bands_Period=1; //---- завершение инициализации return(0); } //+------------------------------------------------------------------+ //| T3.6Bollinger Bands iteration function | //+------------------------------------------------------------------+ int start() { //---- проверка количества баров на достаточность для расчёта if(Bars-1<=Bands_Period) return(0); //---- Введение переменных с плавающей точкой double deviation1,deviation2,deviation3,Temp_Series,sum,midline, priceswing,Resalt; //----+ Введение целых переменных и получение уже подсчитанных баров int reset,MaxBar,MaxBarBB,MaxBarBB1,bar,kk,counted_bars=IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars<0)return(-1); //---- последний подсчитанный бар должен быть пересчитан // (без этого пересчёта для counted_bars функция T3Series будет работать // некорректно!!!) if (counted_bars>0) counted_bars--; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт новых баров int limit=Bars-counted_bars-1; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт всех баров MaxBar=Bars-1-Bands_Period; MaxBarBB=MaxBar-30-Bands_Period; MaxBarBB1=MaxBarBB-1; //----+ загрузка входных цен в буфер для расчёта for(bar=limit;bar>=0;bar--) Series_buffer[bar]=PriceSeries(Input_Price_Customs,bar); //---- проверка бара на достаточность для расчёта Bollinger Bands //---- инициализация нуля if (limit>MaxBar) { for(bar=limit;bar>=MaxBar;bar--)T3MovingBuffer[bar]=0; limit=MaxBar; } //----+ цикл расчёта Moving Avereges for(bar=limit;bar>=0;bar--) { //----+ формула для расчёта Moving Avereges Temp_Series=iMAOnArray(Series_buffer,0,Bands_Period,0, MA_method, bar); //----+ сглаживание полученного Moving Avereges //----+ обращение к функции T3Series за номером 0. // Параметры nT3.Curvature и nT3.Length не меняются на // каждом баре (nT3.din=0) Resalt=T3Series(0,0,MaxBar,limit,Smooth_Curvature,MA_Smooth, Temp_Series,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); T3MovingBuffer[bar]=Resalt; } //---- РАСЧЁТ Bollinger Bands //---- инициализация нуля if (limit>MaxBarBB) { for(bar=limit;bar>=MaxBarBB;bar--) { UpperBuffer2[bar]=0; UpperBuffer1[bar]=0; LowerBuffer1[bar]=0; LowerBuffer2[bar]=0; } limit=MaxBarBB; } for(bar=limit;bar>=0;bar--) { sum=0.0; midline=T3MovingBuffer[bar]; kk=bar+Bands_Period-1; while(kk>=bar) { priceswing=PriceSeries(Input_Price_Customs,kk)-midline; sum+=priceswing*priceswing; kk--; } deviation2=Bands_Deviations*MathSqrt(sum/Bands_Period); deviation1=0.5*deviation2; deviation3=1.5*deviation2; if (Bands_Smooth>1) { //----+ вычисление и T3 сглаживание Bollinger Bands //----+ ------------------------------------------------------+ //----+ шесть параллельных обращений к функции T3Series за // номерами 1, 2, 3, 4, 5, 6. //----+ Параметры nT3.Length не меняются на каждом баре // (nT3.din=0) //----+ ------------------------------------------------------+ Resalt=T3Series(1,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline+deviation3,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); UpperBuffer3[bar]=Resalt; //----+ ------------------------------------------------------+ Resalt=T3Series(2,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline+deviation2,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); UpperBuffer2[bar]=Resalt; //----+ ------------------------------------------------------+ Resalt=T3Series(3,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline+deviation1,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); UpperBuffer1[bar]=Resalt; //----+ ------------------------------------------------------+ Resalt=T3Series(4,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline-deviation1,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); LowerBuffer1[bar]=Resalt; //----+ ------------------------------------------------------+ Resalt=T3Series(5,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline-deviation2,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); LowerBuffer2[bar]=Resalt; //----+ ------------------------------------------------------+ Resalt=T3Series(6,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth, midline-deviation3,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); LowerBuffer3[bar]=Resalt; //----+ ------------------------------------------------------+ } else { //----+ вычисление Bollinger Bands без T3 сглаживания UpperBuffer3[bar]=midline+deviation3; UpperBuffer2[bar]=midline+deviation2; UpperBuffer1[bar]=midline+deviation1; LowerBuffer1[bar]=midline-deviation1; LowerBuffer2[bar]=midline-deviation2; LowerBuffer3[bar]=midline-deviation3; } } //---- завершение вычислений значений индикатора return(0); } //+-------------------------------------------------------------------+
Функции ParMASeries()
Пример обращения к функции ParMASeries() (ParMA мувинг с дополнительным JMA сглаживанием):
/* Скользящая средняя ParMA,рассчитаннная на основе параболической регрессии с полосами Для работы индикатора следует положить файлы JJMASeries.mqh ParMASeries.mqh PriceSeries.mqh в папку (директорию): MetaTrader\experts\include\ Heiken Ashi#.mq4 в папку (директорию): MetaTrader\indicators\ */ //+------------------------------------------------------------------+ //| JParMA.mq4 | //| ParMA MQL4 CODE: Copyright © 2006, alexjou | //| JParMA Indicator: Copyright © 2006, Nikolay Kositsin | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- отрисовка индикатора в основном окне #property indicator_chart_window //---- количество индикаторных буферов #property indicator_buffers 1 //---- цвет индикатора #property indicator_color1 Red //---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА extern int MA_Period = 8; // период ParMA extern int Length = 3; // глубина сглаживания // параметр, изменяющийся в пределах -100 ... +100, //влияет на качество переходного процесса; extern int Phase = 100; extern int Shift = 0; // cдвиг индикатора вдоль оси времени //Выбор цен, по которым производится расчёт индикатора /*(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 High, 12-Heiken Ashi Low, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int Input_Price_Customs = 0; //---- индикаторные буферы double IndBuffer[]; //---- переменные с плавающей точкой double JResalt, Price, Resalt; //+------------------------------------------------------------------+ //----+ Введение функции JJMASeries //----+ Введение функции JJMASeriesResize //----+ Введение функции JJMASeriesAlert //----+ Введение функции JMA_ErrDescr #include <JJMASeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции ParMAMASeries //----+ Введение функции ParMASeriesResize //----+ Введение функции ParMASeriesAlert //----+ Введение функции ParMA_ErrDescr #include <ParMASeries.mqh> //+------------------------------------------------------------------+ //----+ Введение функции PriceSeries //----+ Введение функции PriceSeriesAlert #include <PriceSeries.mqh> //+------------------------------------------------------------------+ //| JParMA initialization function | //+------------------------------------------------------------------+ int init() { //---- Установка формата точности отображения индикатора IndicatorDigits(Digits); //---- определение стиля исполнения графика SetIndexStyle(0, DRAW_LINE); //---- 1 индикаторный буфер использован для счёта SetIndexBuffer(0, IndBuffer); //---- горизонтальный сдвиг индикаторной линии SetIndexShift (0, Shift); //---- установка значений индикатора, которые не будут видимы на // графике SetIndexEmptyValue(0, 0.0); //---- имя для окон данных и лэйба для субъокон IndicatorShortName ("JParMA( Length="+Length+", Phase="+Phase+", Shift="+Shift+")"); SetIndexLabel(0, "JParMA Line"); //---- установка номера бара, начиная с которого будет отрисовываться индикатор SetIndexDrawBegin(0, MA_Period); //----+ Изменение размеров буферных переменных функции JJMASeries, //nJMAnumber=1(Одно обращение к функции JJMASeries) if (JJMASeriesResize(1)!=1)return(-1); //----+ Изменение размеров буферных переменных функции ParMASeries, //nParMAnumber=1(Одно обращение к функции ParMASeries) if (ParMASeriesResize(1)!=1)return(-1); //---- установка алертов на недопустимые значения внешних переменных JJMASeriesAlert (0,"Length",Length); JJMASeriesAlert (1,"Phase", Phase ); ParMASeriesAlert(0,"MA_Period",MA_Period); PriceSeriesAlert(Input_Price_Customs); return(0); } //+------------------------------------------------------------------+ //| JParMA iteration function | //+------------------------------------------------------------------+ int start() { //---- проверка количества баров на достаточность для расчёта if (Bars-1<MA_Period)return(0); //----+ Введение целых переменных и получение уже подсчитанных баров int reset,MaxBar,MaxBarP,bar,Limit,counted_bars=IndicatorCounted(); //---- проверка на возможные ошибки if (counted_bars<0)return(-1); //---- последний подсчитанный бар должен быть пересчитан if (counted_bars>0) counted_bars--; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт всех баров MaxBar=Bars-1; MaxBarP=MaxBar-MA_Period; //---- определение номера самого старого бара, начиная с которого //будет произедён пересчёт новых баров Limit=Bars-counted_bars-1; //---- Вычисление индикатора for (bar=Limit; bar>=0; bar--) { //----+ Price=PriceSeries(Input_Price_Customs,bar); //----+ получение исходного индикатора //----+ Обращение к функции ParMASeries за номером 0 Resalt=ParMASeries(0,MaxBar,Limit,MA_Period,Price,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); //----+ JMA сглаживание полученного индикатора, //параметр nJMA.MaxBar уменьшен на MA_Period //----+ Обращение к функции JJMASeries за номером 0, // параметры nJMA.Phase и nJMA.Length не меняются на каждом баре // (nJMA.din=0) JResalt=JJMASeries(0,0,MaxBarP,Limit,Phase,Length,Resalt,bar,reset); //----+ проверка на отсутствие ошибки в предыдущей операции if(reset!=0)return(-1); IndBuffer[bar]=JResalt; } //---- return(0); } //+-------------------------------------------------------------------+Во всех индикаторах вместо обычно применяемого массива таймсерии Close[] используется функция PriceSeries(), с применением которой не должно возникнуть никаких проблем:
double PriceSeries(int Input_Price_Customs, int bar)
Входной параметр Input_Price_Customs может изменяться от 0 и до 14. В зависимости
от значения этого параметра функция возвращает значение цены
для текущего графика по номеру бара, используемого в качестве
второго параметра: 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 High, 12-Heiken Ashi Low, 13-Heiken Ashi
Open, 14-Heiken Ashi Close. При необходимости в кейсы функции можно дописать
какие-либо другие алгебраические выражения для определения
входных цен на основе массивов таймсерий. Индикаторы с применением
функции PriceSeries() очень удобно использовать при оптимизации и
тестировании советников.
Заключение
В архиве NK_library.zip находится более ста индикаторов, написанных с применением этих алгоритмов. Этих примеров более чем достаточно, что научиться применять рассмотренные в этой статье функции для написания любых других индикаторов. Все индикаторы из архива с данными версиями функций сглаживания поддерживают экспертов и работают с ними без ошибок. Исключение составляют индикаторы, название которых оканчиваются на HTF. Эти индикаторы в силу специфики расчёта использоваться с экспертами не могут! Индикаторы из архива следует положить в папку клиентского терминала Метатрейдер: \MetaTrader\EXPERTS\indicators. Сами функции находятся в архиве в папке INCLUDE. Всё содержимое этой папки следует поместить в папку клиентского терминала Метатрейдер: \MetaTrader\EXPERTS\INCLUDE.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Едик
Temp_Series=PriceSeries(Input_Price_Customs, bar);
Temp_Series2=PriceSeries(Input_Price_Customs, bar);
//----+ Обращение к функции JJMASeries за номерам 0. Параметры nJMA.Phase и nJMA.Length не меняются на каждом баре (nJMA.din=0)
Resalt = JJMASeries(0,0,MaxBar,limit,Phase,Length,Temp_Series,bar,reset);
Resalt2 = JJMASeries(0,0,MaxBar,limit,Phase,Length,Temp_Series2,bar+1,reset); //перемесчаем на один бар
//----+ проверка на отсутствие ошибки в предыдущей операции
if(reset!=0)return(-1);
JJMA[bar]=Resalt-Resalt2;
На chart'e фукции JJMA[shift], JJMA[shift+1]
на окне индикатора JJMA[bar]=Resalt-Resalt2;
Они не соответстует друг другу.
Николай, на данный момент, ноябрь 2014 года, в индикаторах из архива компилятор выдаёт более 100 ошибок в каждом – я пытался несколько из них скомпилировать. Все индикаторы я не просматривал, их более 100, но в окне «пользовательские индикаторы» в терминале в их иконках серая точка, указывающая, что нет исходника (в данном случае они есть), либо исходник не принят из-за ошибок в коде. Компилятор указывает на точку в коде, вот пример: '.' - semicolon expected JLiteSeries.mqh 138 14. Уже почти год работают 600-е версии МТ4 и уже на очереди 700-е. Я уже сталкивался с такими видом ошибки при переходе на новую версию языка в кодах, но чтобы исправить её при импорте библиотек, моего опыта не хватает. Жаль будет, если такой кусок работы пропадёт.