Отправлено: 14.04.14 09:56. Заголовок: Я в шоке! Подскажите.
Всем привет! Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Игорь подскажи, где можно ознакомиться с изменениями в MQL4? Хотел перенести все данные на новый комп, но некоторые индикаторы после компиляции перестают работать. Вот один из них. http://gfile.ru/a8cCP Хотя не перекомпилированные файлы работают. Компиляция ошибок в коде не выявляет. Но при отладке выдается ошибка формирования массива стр.67. Но в чем ошибка не пойму. Буду благодарен, если найдешь время исправить.
OsMA_Handle = iOsMA(NULL,PERIOD_CURRENT ,FastEMA,SlowEMA,SignalSMA,applied_price); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Функция деинициализации | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных ArrayFree(Dn_OsMA_Buffer); ArrayFree(OsMA_Buffer); } //==================================================================== //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { int calculated=BarsCalculated(OsMA_Handle); if(calculated<rates_total) { Alert("Not all data of OsMA_Handle is calculated (",calculated,"bars ). Error",GetLastError()); return(0); }
//--- we can copy not all data int to_copy; if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total; else { to_copy=rates_total-prev_calculated; to_copy++; } //--- get OsMA_Buffer buffer if(IsStopped()) return(0); //Checking for stop flag if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0) { Print("Getting OsMA_Buffer is failed! Error",GetLastError()); return(0); }
//--- int k,limit; if(prev_calculated==0) limit=0; else limit=prev_calculated-1; //--- the main loop of calculations for(k=limit;k<rates_total;k++) { //Dn_OsMA_Buffer[k]=0.0; Up_OsMA_Buffer[k]=0.0; //--- calculate OsMA //if(OsMA_Buffer[k]>OsMA_Buffer[k+1]) //Up_OsMA_Buffer[k]=OsMA_Buffer[k]; //else Dn_OsMA_Buffer[k]=OsMA_Buffer[k];
Если вместо выше выделенного текста подставить нижнюю строку и (#property indicator_plots 1), то все работает, но в одном цвете. А так, нет. Отображается абра-кадабра какая-то.
Up_OsMA_Buffer[k]=OsMA_Buffer[k]; }
//--- return value of prev_calculated for next call return(rates_total); } //====================================================================
Что не правильно в выделенном тексте? А если задать ArraySetAsSeries(OsMA_Buffer,true); , то и этот вариант не работает.
Отправлено: 25.01.18 22:45. Заголовок: Sergey пишет: Что н..
Sergey пишет:
цитата:
Что не правильно в выделенном тексте? А если задать ArraySetAsSeries(OsMA_Buffer,true); , то и этот вариант не работает.
Дело в том, что без ArraySetAsSeries нумерация баров в таймсериях ведется слева направо по графику. То есть бар с индексом 0 - где-то глубоко в истории, а текущий бар - это rates_total - 1. Поэтому для такой нумерации нужно:
Начинать перебор баров не с бара 0, а с бара 1, т. к. нам нужно взять высоты гистограммы предыдущего бара, которого для бара 0 нет. То есть limit ставится не на 0, а на 1.
Понять, что предыдущий бар, это не k + 1, а k - 1.
OsMA_Handle=iOsMA(NULL,PERIOD_CURRENT,FastEMA,SlowEMA,SignalSMA,applied_price); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Функция деинициализации | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных ArrayFree(Dn_OsMA_Buffer); ArrayFree(OsMA_Buffer); } //==================================================================== //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { int calculated=BarsCalculated(OsMA_Handle); if(calculated<rates_total) { Alert("Not all data of OsMA_Handle is calculated (",calculated,"bars ). Error",GetLastError()); return(0); }
//--- we can copy not all data int to_copy; if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total; else { to_copy=rates_total-prev_calculated; to_copy++; } //--- get OsMA_Buffer buffer if(IsStopped()) return(0); //Checking for stop flag if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0) { Print("Getting OsMA_Buffer is failed! Error",GetLastError()); return(0); }
//--- int k,limit; if(prev_calculated==0) limit=1; else limit=prev_calculated-1; //--- the main loop of calculations for(k=limit;k<rates_total;k++) { Dn_OsMA_Buffer[k]=0.0; Up_OsMA_Buffer[k]=0.0; //-- calculate OsMA if(OsMA_Buffer[k]>OsMA_Buffer[k-1]) Up_OsMA_Buffer[k]=OsMA_Buffer[k]; else Dn_OsMA_Buffer[k]=OsMA_Buffer[k]; }
//--- return value of prev_calculated for next call return(rates_total); }
Отправлено: 26.01.18 07:35. Заголовок: Спасибо! Но хотелось..
Спасибо! Но хотелось бы разобраться до конца. Как изменить код с использованием ArraySetAsSeries(OsMA_Buffer,true); Поскольку именно этот вариант в дальнейшем будет использован в советниках и рекомендован во всех статьях, а у меня не вышел.
Отправлено: 26.01.18 17:44. Заголовок: Тогда нужно всю инде..
Тогда нужно всю индексацию развернуть, а не просто использовать ArraySetAsSeries. Т. к. цикл расчета данных для каждого бара в "правильном" индикаторе должен следовать слева направо по графику, то нужно идти от rates_total (limit поддерживать) до 0 с декрементом.
Тогда нужно всю индексацию развернуть, а не просто использовать ArraySetAsSeries. Т. к. цикл расчета данных для каждого бара в "правильном" индикаторе должен следовать слева направо по графику, то нужно идти от rates_total (limit поддерживать) до 0 с декрементом.
На словах я это понимаю, с практикой туго. Устанавливаем порядок индексации массива как в таймсерии if(CopyBuffer(OsMA_Handle,0,0,to_copy,OsMA_Buffer)<=0) { Print("Getting OsMA_Buffer is failed! Error",GetLastError()); return(0); } ArraySetAsSeries(OsMA_Buffer,true);
Как не пересчитываю слева-направо или наоборот, получается фигня. В чем не прав не знаю. Я это смогу понять, лишь проанализировав правильный код. Не зачти за лишний труд. Плиз!
Отправлено: 28.01.18 17:10. Заголовок: Sergey пишет: Как н..
Sergey пишет:
цитата:
Как не пересчитываю слева-направо или наоборот, получается фигня. В чем не прав не знаю. Я это смогу понять, лишь проанализировав правильный код. Не зачти за лишний труд. Плиз!
Установка признака таймсерии делается один раз, а не на каждом тике. И не для одного буфера, а для всех. Поэтому и проблема:
OsMA_Handle=iOsMA(NULL,PERIOD_CURRENT,FastEMA,SlowEMA,SignalSMA,applied_price); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Функция деинициализации | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(OsMA_Handle); // удаляет хэндл индикатора и освобождает память занимаемую им ArrayFree(Up_OsMA_Buffer); // освобождаем динамический массив от данных ArrayFree(Dn_OsMA_Buffer); ArrayFree(OsMA_Buffer); } //==================================================================== //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { int calculated = BarsCalculated(OsMA_Handle); if(calculated < rates_total) { Alert("Not all data of OsMA_Handle is calculated (", calculated, "bars ). Error", GetLastError()); return(0); }
//--- we can copy not all data int to_copy; if(prev_calculated>rates_total || prev_calculated<0) to_copy = rates_total; else { to_copy = rates_total-prev_calculated; to_copy++; } //--- get OsMA_Buffer buffer if(CopyBuffer(OsMA_Handle, 0, 0, to_copy, OsMA_Buffer)<=0) { Print("Getting OsMA_Buffer is failed! Error", GetLastError()); return(0); }
//--- int k,limit; if(prev_calculated == 0) limit = rates_total - 2; else limit = fmin(rates_total - prev_calculated, rates_total - 2); //--- the main loop of calculations for(k = limit; k >= 0; --k) { Dn_OsMA_Buffer[k] = 0.0; Up_OsMA_Buffer[k] = 0.0;
Установка признака таймсерии делается один раз, а не на каждом тике. И не для одного буфера, а для всех. Поэтому и проблема:
Все точно! В этом проблема. А что с советниками? Вот пример на сайте mql5.com /---- indicator buffers double MA[]; // массив для индикатора iMA //---- handles for indicators int MA_handle; // указатель на индикатор iMA //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- создание указателя на объект - индикатор iMA MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); return(0); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- заполнение массива MA[] текущими значениями индикатора iMA //--- в массив будет записано 100 элементов CopyBuffer(MA_handle,0,0,100,MA); //--- задаём порядок индексации массива MA[] как в MQL4 ArraySetAsSeries(MA,true); //--- а дальше делайте с этими данными всё что угодно, например: if(MA[0]>MA[1]) { //--- выполнение каких-то операций } }
1. Почему в советниках порядок индексации делается на каждом тике? 2. Есть ли возможность в советниках обновлять последние бары как в индикаторах, если для анализа нужно большое их количество. 3. И стоит ли использовать динамический массив, если для анализа брать 2 последних бара.
Можно ли написать так:
double MA[2]; // массив для индикатора iMA //---- handles for indicators int MA_handle; // указатель на индикатор iMA //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- создание указателя на объект - индикатор iMA MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); //--- задаём порядок индексации массива MA[] как в MQL4 ArraySetAsSeries(MA,true); return(0); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- заполнение массива MA[] текущими значениями индикатора iMA //--- в массив будет записано 2 элементов CopyBuffer(MA_handle,0,0,2,MA);
//--- а дальше делайте с этими данными всё что угодно, например: if(MA[0]>MA[1]) { //--- выполнение каких-то операций } }
Статический массив нельзя сделать таймсерией. Но ничего страшного в динамических массивах нет. Ведь функция CopyBuffer сама перераспределит память под массив при первом вызове. При последующих вызовах на это не будет уходить время. Поэтому вполне можно сделать так, проверяя попутно формирование нового бара:
Отправлено: 18.02.18 09:47. Заголовок: Столкнулся с не пони..
Столкнулся с не пониманием обращения к функции... в mql4. //+------------------------------------------------------------------+ //| Проверяет объем ордера на корректность | //+------------------------------------------------------------------+ bool CheckVolumeValueStart(double volume,string &description) { //--- минимально допустимый объем для торговых операций double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); if(volume<min_volume) { description=StringFormat("Объем меньше минимально допустимого SYMBOL_VOLUME_MIN=%.2f",min_volume); return(false); }
//--- максимально допустимый объем для торговых операций double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); if(volume>max_volume) { description=StringFormat("Объем больше максимально допустимого SYMBOL_VOLUME_MAX=%.2f",max_volume); return(false); }
int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { description=StringFormat("Объем не является кратным минимальной градации SYMBOL_VOLUME_STEP=%.2f, ближайший корректный объем %.2f", volume_step,ratio*volume_step); return(false); } description="Корректное значение объема"; return(true); } //============================================================================= Что делать с &description? if (!CheckVolumeValueStart(Lot,................)) return; Конечно, можно его убрать из функции, а в тексте заменить на Print. Но хотелось бы разобраться, что это значит и как правильно применить. Спасибо!
Отправлено: 18.02.18 16:55. Заголовок: Sergey пишет: Что д..
Sergey пишет:
цитата:
Что делать с &description? if (!CheckVolumeValueStart(Lot,................)) return; Конечно, можно его убрать из функции, а в тексте заменить на Print. Но хотелось бы разобраться, что это значит и как правильно применить.
Этот аргумент функции нужно рассматривать как сообщение об ошибке. Пользоваться так:
Отправлено: 18.02.18 19:03. Заголовок: Admin пишет: Могу с..
Admin пишет:
цитата:
string description = "";
А вот это я и пропустил. Забыл объявить. Спасибо Игорь! Admin пишет:
цитата:
Могу согласиться с тем, что в качестве примера такой прием вызывает недоумение. Скорее всего взято из какого-то готового проекта и вставлено как есть.
В маркете на mql5.com при валидации (автоматической проверки на наличие ошибок) это выдано в качестве примера. Авто контроль проверяет каждую из позиций: минимальный и максимальный лот, кратность шагу и достаточность свободных средств для стартового лота в советнике. Причем ошибка обязательно должна быть выведена в журнал (Print) иначе проверку сова на проходит. Пришлось сделать отдельную объединенную функцию на будущее. Замучился, пока понял, что ошибка неправильные объемы относятся к стартовому лоту.
Отправлено: 19.02.18 12:12. Заголовок: Сейчас другая пробле..
Сейчас другая проблема:"Необходимо добавить возможность проверки торговых функций программы на наличие ошибок в Тестере стратегий." В советнике заложен вывод (Alert), если ордер не установлен, при условии, что все параметры заданы правильно. Что еще нужно не пойму. Ведь Alert в журнал тоже выводится. Может кто подскажет, что означает выше указанная ошибка..... И вот это: TickValue = MarketInfo(Symbol(), MODE_TICKVALUE); double Lot = CalculatedProfit/TickValue/TakeProfit;
TickValue почему-то именно для золота равно 0. Валютные пары тестирование проходят. Бред какой-то. Как обойти не знаю. В тестере ошибок нет.
Сейчас другая проблема:"Необходимо добавить возможность проверки торговых функций программы на наличие ошибок в Тестере стратегий." В советнике заложен вывод (Alert), если ордер не установлен, при условии, что все параметры заданы правильно. Что еще нужно не пойму. Ведь Alert в журнал тоже выводится. Может кто подскажет, что означает выше указанная ошибка.....
Alert при тестировании выводится в журнал тестера по аналогии с функцией Print. Само окно и звуковой сигнал, конечно же, не отображается ни в одном из режимов тестирования.
Sergey пишет:
цитата:
И вот это: TickValue = MarketInfo(Symbol(), MODE_TICKVALUE); double Lot = CalculatedProfit/TickValue/TakeProfit;
TickValue почему-то именно для золота равно 0. Валютные пары тестирование проходят. Бред какой-то. Как обойти не знаю. В тестере ошибок нет.
Проверил для золота на Альпари. Есть значение. А в онлайн что показывает? Еще можно попробовать заменить на более современную форму:
ще можно попробовать заменить на более современную форму:
За эту подсказку спасибо. Что современнее , то и надо применять. Scriptong пишет:
цитата:
А в онлайн что показывает?
Значения есть. Мне видится дело не в этом, а в настойках стартового лота. Проблему решил так: Установил в стартовых настройках вместо расчетного постоянный лот. Таким образом строка в авто проверку не попала. Теперь жду замечания от модератора.....
Все даты в формате GMT
2 час. Хитов сегодня: 0
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет