Нужно решить к примеру такую задачу - индикатор MACD к примеру на M15 идет вниз. Эта пятнашка находится в прошлой пятнице. Нужно определить поворачивает ли MACD на H4 в той же самой пятнице. Количество баров [i] в данном случае разное. Как это можно сделать? Подскажите хотя бы функцию или переменную.
- Momentum - Осцилляторы - Индикаторы - Чарты - MetaTrader 5 для Android
- Momentum - Осцилляторы - Индикаторы - Чарт - MetaTrader 5 для iPhone
- Momentum - Осцилляторы - Использование технических индикаторов - Графики котировок, технический и фундаментальный анализ
посмотрите, как находится бар на другом таймфрейме в примере, соответствующем функции ArraBsearch
А вот в тему индикатор, но не могу найти ошибку, подвешивает МТ:
//+------------------------------------------------------------------+ //| PriceChanel_ut.mq4 | //| Copyright © 2005, Profi_R | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, Profi_R" #property link #property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 DodgerBlue #property indicator_color2 DodgerBlue //---- input parameters extern int Range=6; extern int timeFrame=1440; //---- buffers double UpBuffer[]; double DnBuffer[]; //---- //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { string PeriodName; //хранит имя таймфрейма switch(timeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах { case 1 : timeFrame=PERIOD_M1; break; //в том же порядке, что и кнопки на панели case 5 : timeFrame=PERIOD_M5; break; case 15 : timeFrame=PERIOD_M15; break; case 30 : timeFrame=PERIOD_M30; break; case 60 : timeFrame=PERIOD_H1; break; case 240 : timeFrame=PERIOD_H4; break; case 1440 : timeFrame=PERIOD_D1; break; case 10080 : timeFrame=PERIOD_W1; break; case 43200 : timeFrame=PERIOD_MN1; break; default : timeFrame=Period(); break; } switch(timeFrame) // получение имени таймфрейма { case PERIOD_M1 : PeriodName="M1"; break; case PERIOD_M5 : PeriodName="M5"; break; case PERIOD_M15 : PeriodName="M15"; break; case PERIOD_M30 : PeriodName="M30"; break; case PERIOD_H1 : PeriodName="H1"; break; case PERIOD_H4 : PeriodName="H4"; break; case PERIOD_D1 : PeriodName="D1"; break; case PERIOD_W1 : PeriodName="W1"; break; case PERIOD_MN1 : PeriodName="MN1"; break; } if (timeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем { SetIndexDrawBegin(0,Bars); //очистка от мусора SetIndexDrawBegin(1,Bars); Alert("Требуется график с меньшим таймфреймом"); return(0); } //---- indicators IndicatorBuffers(2); SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,UpBuffer); SetIndexLabel(0,"Up Channel ("+PeriodName+","+Range+")"); SetIndexDrawBegin(0,0); SetIndexStyle(1,DRAW_LINE); SetIndexBuffer(1,UpBuffer); SetIndexLabel(1,"Down Channel ("+PeriodName+","+Range+")"); SetIndexDrawBegin(1,0); //---- name for DataWindow and indicator subwindow label string short_name; //обявление переменной short_name типа "строковый" short_name="PriceChannel("+PeriodName+","+Range+")"; //для отображения на графике присвоим индикатору краткое наименование IndicatorShortName(short_name); //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int cb; int counted_bars=IndicatorCounted(); //---- for(cb=Bars-1-counted_bars;cb>=0;cb--) { UpBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame)); DnBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,1,CorrespBar(cb,timeFrame)); } //---- return(0); } //+------------------------------------------------------------------+ //**********************************************************************************// // Функция возвращает индекс бара на большем таймфрейме соответсвующий переданному // //**********************************************************************************// int CorrespBar(int cb, int tf) { //---- int i,rez; for(i=0;i<=cb;i++) { if(Time[cb]>=iTime(Symbol(),tf,i)) { rez=i; break; } } //---- return(rez); } //+------------------------------------------------------------------+
пытался вывести контрольные значения в лог, но лог создается просто гигантским. Ошибка где-то в функции, потому что если в старте закоментировать вычисление буферов и вместо них сделать вывод номеров бара на текущем и большем таймфрейме, то тормоза остаются, да и значения неверные (те что возвращает функция)
ошибки вроде и нет. при первоначальном запуске (в случае counted_bars==0) у Вас очень долго считаются вызовы CorrespBar. чтобы такого не было, мы и сделали функцию ArrayBsearch
кстати, в приведённом коде совершенно неоправдан вызов iTime. лучше использовать функцию ArrayCopySeries и доступаться к элементам массива, причём массив объявить на глобальном уровне (хотя можно и параметром передать) и скопировать его перед главным циклом
кстати, в приведённом коде совершенно неоправдан вызов iTime. лучше использовать функцию ArrayCopySeries и доступаться к элементам массива, причём массив объявить на глобальном уровне (хотя можно и параметром передать) и скопировать его перед главным циклом
ошибки вроде и нет.
а результат не только задерживается , но к тому же и неверен (верхней линии вообще не видно, а нижняя рисуется выше свечек (может я не правильно понял 0 и 1 в iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame)) - это индексы буферов PChannel?
при первоначальном запуске (в случае counted_bars==0) у Вас очень долго считаются вызовы CorrespBar. чтобы такого не было, мы и сделали функцию ArrayBsearch кстати,
с массивами тоже работает не ахти, да ArrayBsearch будет искать совпадающую по времени, а если не найдет таковую, то вовзвратит ближайшею к последней, а не ту в интервал которой входит наша свечка, т.е. нужна будет дополнительная обработка (Ранее тема работы с массивами уже поднималась "Предложение по улучшению." , но этот вариант неэффективен потому что: например я хочу отрисовать показания индикатора с дневок на получасовках, у меня есть история по дневкам за 20 лет, по получасовкам за 2 года (в одной дневке содержится 48 получасовок т.е. максимум необходимой дневной истории составляет 2 года / 48 = 0,041(7) года, а я буду держать массив с 20 летней историей, а процент использования массива составит 0,208(3) %), да и последующая обработка тоже не прибавит резвости расчетам. Еще тогда предлагался вариант функции возвращающей индекс соответсвующей свечи с другого таймфрейма, а по нему можно было бы узнать и High и Low и остальные параметры, но вы почему-то предпочли добавить несколько функций, как видно не решивший проблему. А вариант индикатора с использованием массива и поиска по нему у меня есть , но тоже жутко тормозной.
в приведённом коде совершенно неоправдан вызов iTime.
???
Одну ошибку я нашел:
SetIndexBuffer(0,UpBuffer);
SetIndexBuffer(1,UpBuffer); - здесь должно быть DnBuffer
SetIndexBuffer(0,UpBuffer);
SetIndexBuffer(1,UpBuffer); - здесь должно быть DnBuffer
Вроде заработало , но не может же быть что все дело было только в этом? И быстрее чем с массивами, правда все равно очень тормозно.
Оптимизировал, так гораздо быстрее:
//+------------------------------------------------------------------+ //| PriceChanel_ut.mq4 | //| Copyright © 2005, Profi_R | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, Profi_R" #property link "" #property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 DodgerBlue #property indicator_color2 DodgerBlue //---- input parameters extern int Range=6; extern int timeFrame=1440; //---- buffers double UpBuffer[]; double DnBuffer[]; //---- datetime bigtftime; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { datetime bigtftime=Time[Bars-1]; string PeriodName; //хранит имя таймфрейма switch(timeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах { case 1 : timeFrame=PERIOD_M1; break; //в том же порядке, что и кнопки на панели case 5 : timeFrame=PERIOD_M5; break; case 15 : timeFrame=PERIOD_M15; break; case 30 : timeFrame=PERIOD_M30; break; case 60 : timeFrame=PERIOD_H1; break; case 240 : timeFrame=PERIOD_H4; break; case 1440 : timeFrame=PERIOD_D1; break; case 10080 : timeFrame=PERIOD_W1; break; case 43200 : timeFrame=PERIOD_MN1; break; default : timeFrame=Period(); break; } switch(timeFrame) // получение имени таймфрейма { case PERIOD_M1 : PeriodName="M1"; break; case PERIOD_M5 : PeriodName="M5"; break; case PERIOD_M15 : PeriodName="M15"; break; case PERIOD_M30 : PeriodName="M30"; break; case PERIOD_H1 : PeriodName="H1"; break; case PERIOD_H4 : PeriodName="H4"; break; case PERIOD_D1 : PeriodName="D1"; break; case PERIOD_W1 : PeriodName="W1"; break; case PERIOD_MN1 : PeriodName="MN1"; break; } if (timeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем { SetIndexDrawBegin(0,Bars); //очистка от мусора SetIndexDrawBegin(1,Bars); Alert("Требуется график с меньшим таймфреймом"); return(0); } //---- indicators IndicatorBuffers(2); SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,UpBuffer); SetIndexLabel(0,"Up Channel ("+PeriodName+","+Range+")"); SetIndexDrawBegin(0,0); SetIndexStyle(1,DRAW_LINE); SetIndexBuffer(1,DnBuffer); SetIndexLabel(1,"Down Channel ("+PeriodName+","+Range+")"); SetIndexDrawBegin(1,0); //---- name for DataWindow and indicator subwindow label string short_name; //обявление переменной short_name типа "строковый" short_name="PriceChannel("+PeriodName+","+Range+")"; //для отображения на графике присвоим индикатору краткое наименование IndicatorShortName(short_name); //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int cb; int counted_bars=IndicatorCounted(); //---- for(cb=Bars-1-counted_bars;cb>=0;cb--) { if(timeFrame>Period()) { if(Time[cb]<bigtftime) { UpBuffer[cb]=UpBuffer[cb+1]; DnBuffer[cb]=DnBuffer[cb+1]; } else { UpBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame)); DnBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,1,CorrespBar(cb,timeFrame)); } } else { UpBuffer[cb]=iCustom(NULL,0,"PChannel",Range,0,cb); DnBuffer[cb]=iCustom(NULL,0,"PChannel",Range,1,cb); } } //---- return(0); } //+------------------------------------------------------------------+ //**********************************************************************************// // Функция возвращает индекс бара на большем таймфрейме соответсвующий переданному // //**********************************************************************************// int CorrespBar(int cb, int tf) { //---- int i,rez; for(i=0;i<=Bars-1;i++) { if(Time[cb]>=iTime(Symbol(),tf,i)) { rez=i; bigtftime=iTime(Symbol(),tf,i-1); break; } } //---- return(rez); } //+------------------------------------------------------------------+
Пересмотрел ранее написанный (с помощью Романа) вариант индикатора, использующий массивы, действительно с маленькими таймфреймами он заработал гораздо быстрее, с большими не уступает вышеприведенным (а может и быстрее, оценивал на "глазок") :) вот его код:
//+------------------------------------------------------------------+ //| PChannel_m.mq4 | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_buffers 3 #property indicator_color1 DodgerBlue #property indicator_color2 DodgerBlue #property indicator_color3 DodgerBlue extern int Range=6; extern int TimeFrame=1440; double UpBuffer[]; double DnBuffer[]; double MdBuffer[]; int i; //счетчик string PeriodName; //хранит имя таймфрейма int init() { string short_name; SetIndexStyle(0,DRAW_LINE,1,2); SetIndexBuffer(0,UpBuffer); SetIndexLabel(0,"Up Channel ("+Range+")"); SetIndexDrawBegin(0,0); SetIndexStyle(1,DRAW_LINE,1,2); SetIndexBuffer(1,DnBuffer); SetIndexLabel(1,"Down Channel ("+Range+")"); SetIndexDrawBegin(1,0); SetIndexStyle(2,DRAW_LINE,2); SetIndexBuffer(2,MdBuffer); SetIndexLabel(2,"Middle Channel"); SetIndexDrawBegin(2,0); IndicatorShortName(short_name); switch(TimeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах { case 1 : TimeFrame=PERIOD_M1; break; //в том же порядке, что и кнопки на панели case 5 : TimeFrame=PERIOD_M5; break; case 15 : TimeFrame=PERIOD_M15; break; case 30 : TimeFrame=PERIOD_M30; break; case 60 : TimeFrame=PERIOD_H1; break; case 240 : TimeFrame=PERIOD_H4; break; case 1440 : TimeFrame=PERIOD_D1; break; case 10080: TimeFrame=PERIOD_W1; break; case 43200: TimeFrame=PERIOD_MN1; break; default : TimeFrame=Period(); break; } switch(TimeFrame) // получение имени таймфрейма { case PERIOD_M1 : PeriodName="M1"; break; case PERIOD_M5 : PeriodName="M5"; break; case PERIOD_M15 : PeriodName="M15"; break; case PERIOD_M30 : PeriodName="M30"; break; case PERIOD_H1 : PeriodName="H1"; break; case PERIOD_H4 : PeriodName="H4"; break; case PERIOD_D1 : PeriodName="D1"; break; case PERIOD_W1 : PeriodName="W1"; break; case PERIOD_MN1 : PeriodName="MN1"; break; } short_name="PriceChannel("+PeriodName+","+Range+")"; return(0); } int start() { int i,counted_bars=IndicatorCounted(); //---- initial zero if(counted_bars<1) for(i=1;i<Bars;i++) { DnBuffer[i]=0.0; UpBuffer[i]=0.0; MdBuffer[i]=0.0; } //---- datetime TimeArray[]; double LowArray[],HighArray[]; int y=0; //счетчик баров другого таймфрейма if (TimeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем { SetIndexDrawBegin(0,Bars); //очистка от мусора SetIndexDrawBegin(1,Bars); SetIndexDrawBegin(2,Bars); Comment("Требуется график с меньшим таймфреймом"); return(0); } //получение времени начала каждого бара с другого таймфрейма ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame); //получение всех Low оттуда же ArrayCopySeries(LowArray,MODE_LOW,Symbol(),TimeFrame); //аналогично High ArrayCopySeries(HighArray,MODE_HIGH,Symbol(),TimeFrame); for(i=0,y=0;i<Bars-counted_bars;i++) { //если время начала бара нашего таймфрейма меньше времени начала бара другого таймфрейма, //то переходим к следующему бару на другом таймфрейме (отсчет в обратном порядке) if (Time[i]<TimeArray[y]) y++; //|выбирает бар с минимальным/максимальным значением с другого таймфрейма, DnBuffer[i]=LowArray[Lowest(NULL,TimeFrame,MODE_LOW,Range,y)]; //|и по номеру бара вытаскивает соответствующее значение из массивов UpBuffer[i]=HighArray[Highest(NULL,TimeFrame,MODE_HIGH,Range,y)]; //|LowArray и HighArray MdBuffer[i]=(UpBuffer[i]+DnBuffer[i])/2; } Comment("PriceChannel по т-ф ", PeriodName, " с периодом ", Range); return(0); }
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь