Спасибо за очередную хорошую статью. Для меня уже по традиции статьи MQL Community стали способом получения высшего образования после среднего (имеется ввиду встроенный MQL справочник редактора)
Если по делу, то заметил в коде маленький изъян. По задумке автора
//--- флаг для однократного вывода значений price[]
переменную
bool printed=false;
необходимо вынести за пределы функции OnCalculate(), иначе распечатка массива будет на каждом событии.
Еще допущена опечатка здесь
Правило передачи PLOT_DRAW_BEGIN в параметр begin: Значение входного параметра begin в OnCalculate(), при расчетах пользовательского индикатора A на данных другого (базового) индикатора B, всегда равно значению свойства PLOT_DRAW_BEGIN нулевого графического построения базового индикатора B.
Таким образом, если мы создали на графике индикатор RSI (индикатор A) с периодом 14 и затем на данных индикатора RSI(14) построили наш пользовательский индикатор True Strength Index (индикатор B), то:
Судя по правилу и логике индикатор А - это пользовательский TSI, а индикатор B(базовый) - RSI.

- www.mql5.com
Эта статья содержит подробные знания.
Спасибо.
Привет,
Статья действительно интересная и открывает новые возможности по управлению индикаторами.
Так как я новичок в MQL5, я попытался реализовать возможность применения одного индикатора к другому. Я написал небольшой код, который только дублирует
адаптивную скользящую среднюю, надеясь использовать ее на любом индикаторе графика.
К сожалению, в списке параметров, который появляется при запуске индикатора, у меня нет пункта "apply to : previuos indicator's data".
Как должен быть организован код, чтобы иметь возможность применить его к другому индикатору?
Вот мой код:
#property indicator_separate_window #property indicator_minimum 1.3 #property indicator_maximum 1.35 //#свойство indicator_chart_window #property indicator_buffers 2 #property indicator_plots 1 //--- график dMA #property indicator_label1 "dAMA" #property indicator_type1 DRAW_LINE #property indicator_color1 Red #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- входные параметры input int AMAPeriod=9; input int FastEMA=2; input int SlowEMA=20; //--- индикаторные буферы double AMABuffer[]; double dAMABuffer[]; int h_dAMA; int h_AMA; //+------------------------------------------------------------------+ //| Пользовательская функция инициализации индикатора | //+------------------------------------------------------------------+ int OnInit() { //--- отображение индикаторных буферов SetIndexBuffer(0,dAMABuffer,INDICATOR_DATA); SetIndexBuffer(1,AMABuffer,INDICATOR_CALCULATIONS); //PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MAPeriod+1); h_AMA=iAMA(_Symbol,PERIOD_CURRENT,AMAPeriod,FastEMA,SlowEMA,0,PRICE_CLOSE); if(h_AMA == INVALID_HANDLE) { Print("AMA indicator initialization error, Code = ", GetLastError()); return(-1); } ArraySetAsSeries(AMABuffer,true); ArraySetAsSeries(dAMABuffer,true); PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MathMax(AMAPeriod,SlowEMA)); //--- return(0); } //+------------------------------------------------------------------+ //| Пользовательская функция итерации индикатора| //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, // размер массива price[] const int prev_calculated,// количество баров, обработанных при предыдущем вызове const int begin, // откуда начинаются значимые данные const double &price[] // массив для расчета ) { if(BarsCalculated(h_AMA)<rates_total) return(0); //--- мы можем копировать не все данные int to_copy; if(prev_calculated>rates_total || prev_calculated<=0) { to_copy=rates_total; if(CopyBuffer(h_AMA,0,0,to_copy,AMABuffer)<=0) return(0); for (int i=0;i<to_copy-MathMax(AMAPeriod,SlowEMA);i++) { dAMABuffer[i]=AMABuffer[i]; } } else { to_copy=rates_total-prev_calculated+MathMax(AMAPeriod,SlowEMA)-1; //--- последнее значение всегда копируется to_copy++; if(CopyBuffer(h_AMA,0,0,to_copy,AMABuffer)<=0) return(0); for (int i=0;i<to_copy;i++) { dAMABuffer[i]=AMABuffer[i]; } } //--- попытка копирования Print(dAMABuffer[0]); //чтобы узнать, дойдем ли мы до конца //--- возвращаем значение prev_calculated для следующего вызова //--- //--- возвращаем значение prev_calculated для следующего вызова return(rates_total); } //+------------------------------------------------------------------+
А есть какая-нибудь возможность при программном (через iCustom, например) создании индикатора сообщить ему, что нужно брать на вход данные от другого индикатора? Или, еще лучше, дать ему прямо массив данных, на которых он должен построиться.
А есть какая-нибудь возможность при программном (через iCustom, например) создании индикатора сообщить ему, что нужно брать на вход данные от другого индикатора? Или, еще лучше, дать ему прямо массив данных, на которых он должен построиться.
Смотрите функцию iCustom:
Если в индикаторе используется первая форма вызова, то при запуске пользовательского индикатора на вкладке "Parameters" можно дополнительно указать на каких данных он будет рассчитываться. Если параметр "Apply to" не выбран явно, то по умолчанию расчет производится по значениям "Close".
При вызове пользовательского индикатора из mql5-программы параметр Applied_Price или хэндл другого индикатора должен передаваться последним после всех предусмотренных пользовательским индикатором входных переменных.
Здравствуйте,
Это очень хорошая статья, но у меня есть несколько вопросов.
1. только индикаторы, которые используют короткую форму вызова функцииOnCalculate(), могут быть применены к другому индикатору или индикаторы, которые используют длинную форму вызова функцииOnCalculate() тоже могут быть применены? Если да, то как можно применить один индикатор с длинной формой вызова функцииOnCalculate() к другому индикатору?
2. При наложении одного индикатора на другой (TSI на RSI) возникают проблемы с отображением (см. приложенное изображение). В то время как RSI строится от 0 до 100, второй индикатор (TSI) также имеет значения ниже 0, значения, которые не видны на графике. В чем проблема и почему график не настраивается должным образом для корректного отображения обоих индикаторов. Можно ли решить эту проблему или это ошибка MetaTrader?
Решил построить индикатор от индикатора и наткнулся на непонятку.
оба индикатора строятся на базе
int OnCalculate (const int rates_total, // размер массива price[] const int prev_calculated, // обработано баров на предыдущем вызове const int begin, // индекс с которого начинаются значимые данные в массиве price[] const double& price[] // массив для расчета );
соответственно пользователь имеет возможность задать поле applied_price в параметрах.
Вот моя трудность состоит в том как передать внутреннему индикатору (от которого строится внешний) поле applied_price ???
Самое простое решение сделать инпут и предупредить пользователя что инпут applied_price и параметр applied_price должны быть одинаковы, но это как то криво.
Пример для OnCalculate() смотрели?
Для получения значений пользовательского индикатора из других mql5-программ используется функция iCustom(), возвращающая хэндл индикатора для последующих операций. При этом также можно указать необходимый массив price[] или хэндл другого индикатора. Этот параметр должен передаваться последним в списке входных переменных пользовательского индикатора.
Пример:
void OnStart() { //--- string terminal_path=StatusInfoString(STATUS_TERMINAL_PATH); int handle_customMA=iCustom(Symbol(),PERIOD_CURRENT, "Custom Moving Average",13,0, MODE_EMA,PRICE_TYPICAL); if(handle_customMA>0) Print("handle_customMA = ",handle_customMA); else Print("Cannot open or not EX5 file '"+terminal_path+"\\MQL5\\Indicators\\"+"Custom Moving Average.ex5'"); }
В данном примере последним параметром передано значение PRICE_TYPICAL (из перечисления ENUM_APPLIED_PRICE ), которое указывает, что пользовательский индикатор будет построен по типическим ценам, полученным как (High+Low+Close)/3. Если параметр не указывается, то индикатор строится по значениям PRICE_CLOSE, то есть по ценам закрытия каждого бара.
Да смотрел,
int handle_customMA=iCustom(Symbol(),PERIOD_CURRENT, "Custom Moving Average",13,0, MODE_EMA,PRICE_TYPICAL);
applied_price при вызове iCustom указывается явно, но в индикаторе из которого вызывается iCustom где его взять?
ведь пользователь его задаёт в параметрах а не в инпутах.
int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,Buffer,INDICATOR_DATA); hndl=iCustom(_Symbol,_Period,"MyInd",param_ind,???? вот тут нужно указать аплиед_прайс который будет задавать пользователь); //--- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //... return(rates_total); }
PS фишка в том чтоб пользователь задав один раз параметр applied_price и больше не парился, чтоб это значение пошло по всей пирамиде вызовов.
Может я неправильно понимаю вопрос, но попытаюсь подбросить еще одну идею
indicator_applied_price | задает значение по умолчанию для поля "Apply to". Можно задавать одно из значений перечисления ENUM_APPLIED_PRICE. Если свойство не задано, то по умолчанию применяется значение PRICE_CLOSE |

- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Индикатор от индикатора в MQL5:
Вы хотите улучшить индикатор, чтобы он правильно считался не только на ценовых данных, но и значениях другого индикатора? В этой статье мы пройдем все необходимые этапы такой модификации.
Автор: MetaQuotes