struct sextr { datetime time; //дата окончания тренда double price; //цена окончания тренда datetime reg_time; //дата регистрации тренда double reg_price; //цена регистрации тренда int interval; //длительность тренда, в минутах double distance; //расстояние, которое прощёл тренд, в пунктах int direction; //направление тренда +1/-1 } Extremes[]; //здесь записываем экстремумы в массив void WriteExtremum(sextr &eExtremes[], double eDistance, datetime eQualityHistory, string eSymbol, ENUM_TIMEFRAMES eTimeFrame, datetime eTime) { int eFinish=ArraySize(eExtremes)-1; int eShift=iBarShift(eSymbol,eTimeFrame,eTime); double eHigh=iHigh(eSymbol,eTimeFrame,eShift); double eLow=iLow(eSymbol,eTimeFrame,eShift); double eClose=iClose(eSymbol,eTimeFrame,eShift); //если массив пустой if(eFinish<0) { ArrayResize(eExtremes,++eFinish+1); eExtremes[eFinish].time=eTime; //пока мы не знаем какой из экстремумов будет в первом элементе, поэтому берём цену по середине //можно сделать более грамотнее, но лень. Поэтому первый экстремум у нас будет бракованный //и мы его потом затрём eExtremes[eFinish].price=(eHigh+eLow)/2; eExtremes[eFinish].reg_time=eTime; eExtremes[eFinish].reg_price=eClose; eExtremes[eFinish].interval=0; eExtremes[eFinish].distance=0; eExtremes[eFinish].direction=0; } //если в массиве есть элементы else { //текущий элемент - максимум if(eExtremes[eFinish].direction==1) { //произошло обновление текущего экстремума if(eHigh-eExtremes[eFinish].price>0) { eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eHigh; if(eFinish>0) { eExtremes[eFinish].interval=GetInterval(eExtremes[eFinish-1].time,eTime,eQualityHistory,eSymbol,eTimeFrame); eExtremes[eFinish].distance=eHigh-eExtremes[eFinish-1].price; } } else { //произошло превышение расстояния между противоположными экстремумами if(eExtremes[eFinish].price-eLow>eDistance && eTime-eExtremes[eFinish].time>0) { ArrayResize(eExtremes,++eFinish+1,10000); eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eLow; eExtremes[eFinish].reg_time=eTime; eExtremes[eFinish].reg_price=eClose; if(eFinish>0) { eExtremes[eFinish].interval=GetInterval(eExtremes[eFinish-1].time,eTime,eQualityHistory,eSymbol,eTimeFrame); eExtremes[eFinish].distance=eExtremes[eFinish-1].price-eLow; } eExtremes[eFinish].direction=-1; } } } //текущий элемент - минимум if(eExtremes[eFinish].direction==-1) { //произошло обновление текущего экстремума if(eExtremes[eFinish].price-eLow>0) { eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eLow; if(eFinish>0) { eExtremes[eFinish].interval=GetInterval(eExtremes[eFinish-1].time,eTime,eQualityHistory,eSymbol,eTimeFrame); eExtremes[eFinish].distance=eExtremes[eFinish-1].price-eLow; } } else { //произошло превышение расстояния между противоположными экстремумами if(eHigh-eExtremes[eFinish].price>eDistance && eTime-eExtremes[eFinish].time>0) { ArrayResize(eExtremes,++eFinish+1,10000); eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eHigh; eExtremes[eFinish].reg_time=eTime; eExtremes[eFinish].reg_price=eClose; if(eFinish>0) { eExtremes[eFinish].interval=GetInterval(eExtremes[eFinish-1].time,eTime,eQualityHistory,eSymbol,eTimeFrame); eExtremes[eFinish].distance=eHigh-eExtremes[eFinish-1].price; } eExtremes[eFinish].direction=1; } } } //эта ситуация, когда первый элемент не закрылся, и не понятно максимум это будет или минимум //если произошло превышение в любую сторону, тогда затираем значения первого элемента if(eExtremes[eFinish].direction==0) { //произошло превышение расстояния между противоположными экстремумами if(eHigh-eExtremes[eFinish].price>eDistance) { eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eHigh; eExtremes[eFinish].reg_time=eTime; eExtremes[eFinish].reg_price=eClose; eExtremes[eFinish].interval=0; eExtremes[eFinish].distance=0; eExtremes[eFinish].direction=1; } if(eExtremes[eFinish].price-eLow>eDistance) { eExtremes[eFinish].time=eTime; eExtremes[eFinish].price=eLow; eExtremes[eFinish].reg_time=eTime; eExtremes[eFinish].reg_price=eClose; eExtremes[eFinish].interval=0; eExtremes[eFinish].distance=0; eExtremes[eFinish].direction=-1; } } } } //Записываем время первого бара, принадлежащего текущему таймфрейму, отсеивая дневные бары на младших таймфреймах, //которые встречаются в начале старой истории, когда цена регистрировалась раз в сутки. //Пока "родного" бара нет, eQualityHistory равен -1 void SetQualityHistory(datetime &eQualityHistory, string eSymbol, ENUM_TIMEFRAMES eTimeFrame, datetime eTime) { if(eQualityHistory>=0) return; if(PeriodSeconds(eTimeFrame)>=86400) { eQualityHistory=iTime(eSymbol,eTimeFrame,iBars(eSymbol,eTimeFrame)-1); } else { int eShift=iBarShift(eSymbol,eTimeFrame,eTime)+1; if(eShift>iBars(eSymbol,eTimeFrame)-1) return; MqlDateTime eCurrentTime, ePreviousTime; TimeToStruct(eTime,eCurrentTime); TimeToStruct(iTime(eSymbol,eTimeFrame,eShift),ePreviousTime); if(eCurrentTime.day==ePreviousTime.day) { eQualityHistory=iTime(eSymbol,eTimeFrame,eShift); } } } //находим интервал времени между двумя точками в минутах, с учётом возможности некачественной истории int GetInterval(datetime eStartTime, datetime eFinishTime, datetime eQualityHistory, string eSymbol, ENUM_TIMEFRAMES eTimeFrame) { if(eFinishTime==0) return(0); //пока идёт некачественная история или интервал находится до начала качественной истории if(eQualityHistory<0 || eQualityHistory>eFinishTime) { return((iBarShift(eSymbol,eTimeFrame,eStartTime)-iBarShift(eSymbol,eTimeFrame,eFinishTime))*1440); } //если начало периода было не раньше даты начала качественной истории if(eStartTime>=eQualityHistory) { return((int)(iBarShift(eSymbol,eTimeFrame,eStartTime)-iBarShift(eSymbol,eTimeFrame,eFinishTime))*PeriodSeconds(eTimeFrame)/60); } return((int)(iBarShift(eSymbol,eTimeFrame,eQualityHistory)-iBarShift(eSymbol,eTimeFrame,eFinishTime)+1)*PeriodSeconds(eTimeFrame)/60 +(iBarShift(eSymbol,eTimeFrame,eStartTime)-iBarShift(eSymbol,eTimeFrame,eQualityHistory)-1)*1440); }
И теперь вызываем
input int Distance=1000; string SymboL; ENUM_TIMEFRAMES TimeFrame; //дата окончания обработанного периода datetime CalculationTime=0; //время начала качественной истории datetime QualityHistory=-1; int OnInit() { //текущий символ и таймфрейм SymboL=Symbol(); TimeFrame=(ENUM_TIMEFRAMES)Period(); return(INIT_SUCCEEDED); } int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //время окончания цикла datetime eFinishTime=iTime(SymboL,TimeFrame,1); do { //отслеживаем некачественную историю SetQualityHistory(QualityHistory,SymboL,TimeFrame,CalculationTime); //записываем экстремумы в массив WriteExtremum(Extremes,Distance,QualityHistory,SymboL,TimeFrame,CalculationTime); //ваш код //переводим время на один бар вперёд в будущее if(CalculationTime<eFinishTime) { CalculationTime=iTime(SymboL,TimeFrame,(iBarShift(SymboL,TimeFrame,CalculationTime)-1)); } else { break; } } while(CalculationTime<=eFinishTime); return(rates_total); }
![](https://c.mql5.com/3/337/drinks.gif)
Привет всем и заранее спасиби за помощь!
Где найти простейший индикатор, вычисляющий и рисующий тупо минимумы и максимумы, при условии, что разница между мимимумом и максимумом не менее заданного параметра?
Спасибо
Hallo zusammnen und Danke m Voraus für die Hilfe!
Gibt es / wo kann man einen Indikator finden, der einfach und stupide die Minimume und Maximume unter Bedingung, dass die Differenz zwischen Min und Max nicht kleiner als ein vorgegebener Parameter ist?
Danke!
Hello everyone and thank you in advance for the help!
Is there / where can I find an indicator that simply and stupidly calculates and draws the minimums and maximums on the condition that the difference between min and max is not less than a given parameter?
Thanks!
Привет всем и заранее спасиби за помощь!
Где найти простейший индикатор, вычисляющий и рисующий тупо минимумы и максимумы, при условии, что разница между мимимумом и максимумом не менее заданного параметра?
В стандартной поставке MT. Называется ZigZag.
Обнаружен новый минимум - смотрим, каково расстояние между ним и предыдущим максимумом; если расстояние меньше заданного - ищем дальше...
Спасибо, но ZigZag действует по другому принципу.
По какому? Параметр Deviation как раз за количество пунктов и отвечает.
По какому? Параметр Deviation как раз за количество пунктов и отвечает.
По количеству баров. Фактически по каналу Дончианна он работает, это экспериментально установлено, но в коде есть и ещё какие то факторы.
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Подскажите. пожалуйста, класс/метод в MQL5, который позволяет вычислять локальные минимумы и максимумы!
Еще лучше был бы метод/класс, позволяющий вычислить, какой длинны тренд/движение.
Заранее благодарен
Einen schönen guten Tag,
kann mir jemand eine Methode /eine Klasse nennen, mit der man lokale Miminums/Maximums erkennt? Noch besser wäre eine Methode/Klasse, die berechnet, wieviele Punkte ein Trend / eine Bewegung ist.
Danke im Voraus!
Hello everybody,
can someone give / name me a method / class which recognizes local minima / maxima? Even better would be a method / class that calculates how many poins a trend / movement is.
Thank you in advance!