Нужно решить к примеру такую задачу - индикатор 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+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь