Разработчикам и кому интересно - WHILE неравильно работает в тестере (вообще не работает с переменной на основе времени)
Особенности и ограничения тестирования торговых стратегий в MetaTrader 4:
Особенности работы тестера стратегий на истории
- Некоторые функции отрабатываются/пропускаются без вывода
Это Sleep(), Alert(), SendMail(), SpeechText(), PlaySound(), MessageBox(), WindowFind(), WindowHandle(), WindowIsVisible()
то что sleep пропускается вполне объяснимо..
если бы я написал вышеприведенную конструкцию и пытался тестировать какие-то там задержки, то мне и в голову бы не пришло связывать время, которое эмулирует тестер с реальным временем - это бред какой-то (!!!) - время должно анализироваться в рамках пространства времени того, что внутри тестера..
при чем тут реальное время ?
Попробую объяснить.
Не суть принципиально какое использовать время Current или Local или еще какое - факт в том, что стратегия на основе временной последовательности с задержкой (т.е имеем событие А. Когда оно наступило подождем N секунд если B не наступило - подождем еще и т.д. пока не наступит B при N циклов, которое может не иметь ограничения. Если N > limit т.е. ждем уже слишком долго - тогда отменяется условие А [если имеем А - то ждем появления B. Общее количество циклов ожидания ограничено limit по t секунд или maxdelay по сумме секунд на всех уже проиденных циклах] т.е. нет привязки ко времени суток, дня или года.1. Просто жалко, что из-за тиковой природы тестера стратегий, то что работает на задержках между запросами на DEMO, и работает абсолютно нормально, при этом не перегружая сервер данных слишком частыми запросами, начисто виснет при запуске на тестере. Т.е. система с зацикленным внутри "старт" циклом "WHILE" (т.е. поле первого тика start не перезапускается никогда и дальнейший процесс идет внутри While с запросами новых данных через RefrashRates) на демо работает нормально. 2. При разрыве связи вместе с крохотной строчкой "нет связи" в углу окна терминала система периодически выдает на экран предупреждение, что связь потеряна и надо принять меры. 3. При появлении ошибок. которые система не может откорректировать сама - сразу выдаются сообщения и не нужно ждать свежего тика от сервера. Т.е. нет такого долго-занудного процесса, когда у нас позиция открыта уже 15 часов (с утра пятницы), порвалась связь с сервером или инетом, стопов нету, а терминал молчит как раба. и мы узнаем об этом утром понедельника т.к. торговля была закрыта в выходные и сервера данных молчали. Опачки мы в минусе на 500 бакинских рублей или вылетели по StopOut и кто виноват? 4. Зацикленная while'ом система не пропускает ничего мимо ушей, но тестировать на тестере стратегий ее в таком варианте невозможно. т.к. тестер работает на тиковых данных и игнорирует некоторые команды. А перезапуск "Старт" внутри цикла не происходит никода.
1. 4. Есть такая функция IsTesting(), при помощи нее можно разделить алгоримы работающие в тестере и на счете.
2. Для этих целей можно написать отдельного советника, который бы постоянно работал в терминаеле независимо от всего остального.
3. Не нужно ждать следующнго тика, чтобы получить собщение об ошибке, его можно получить на тике, на котором выполнялдся запрос. А вот как можно получить сообщение об ошибке на следующем тике очень интересно.
1. 4. Есть такая функция IsTesting(), при помощи нее можно разделить алгоримы работающие в тестере и на счете.
2. Для этих целей можно написать отдельного советника, который бы постоянно работал в терминаеле независимо от всего остального.
3. Не нужно ждать следующнго тика, чтобы получить собщение об ошибке, его можно получить на тике, на котором выполнялдся запрос. А вот как можно получить сообщение об ошибке на следующем тике очень интересно.
В ообще-то я про нее знаю и сейчас переписываю советника по принципу: если мы на тестере - тогда вырубаем все зацикливания на основе времени т.к. тестер их пролетает. А также не будут вызываться функции IstradeAllowed(), MarketInfo(Symbol(),MODE_TRADEALLOWED), sleep(), Alert(), MessageBox() некоторые другие функции, которые игнорируются тестером или завешивают его и WHILE циклы с уходом в старт без выхода (т.е. Start-->While {IsStopped != true} while бесконечен пока не остановлен вручную через {IsStopped==true} ) т.е. программа будет в слегка урезанной версии запускаться на тестере и в полной на DEMO или REAL, а опознание режима работы будет происходить в Init(). Т.е. если мы не на тестере {IsTesting !=true или IsOptimization != true} тогда некий флаг для каждой отключаемой функции будет переводиться в иное состояние и каждый компонент будет знать запускаться ему или пропускаться. Всего одним флаго из Init() должно получиться несложно - правда повозиться придется.
P.S. Чтоб у вас все было и вам за это ничего не было. :)
А вот что делать, если советник обязательно должен крутиться в бесконечном цикле while? Как его тестировать в таком случае?
Суть проблемы в следующем: основная работа советника производится во внешней программе - MATLAB Engine, связь через вызовы функций DLL. Для запуска и остановки матлабовской машины используются две функции в DLL, и исполняются они, само собой, достаточно долго . По этому логично запускать их только один раз - в начале работы и при завершении соответственно, а не на каждом тике. То есть логично использовать бесконечный цикл - тогда ф-я start вызывается только один раз. Процесс работы советника тогда такой: 1)start() 2)Запускаем MATLAB 3)Бесконечный цикл while, в котором происходит основная работа и торговля 4)Выгружаем MATLAB 5)Завершение start().
При этом запустить MATLAB в init() и выгрузить его в deinit() нельзя по ряду причин. По крайней мере, мне это не удалось, может быть я что-то не понимаю.
Если убрать цикл, старт и стоп матлабовской машины будет происходить на каждом тике и занимать кучу времени - до нескольких секунд. Я правильно понимаю, что тестирование в этом случае будет невозможно? Просто до стадии тестирования пока не еще не дошел. Кто что может посоветовать?
А вот что делать, если советник обязательно должен крутиться в бесконечном цикле while? Как его тестировать в таком случае?
Суть проблемы в следующем: основная работа советника производится во внешней программе - MATLAB Engine, связь через вызовы функций DLL. Для запуска и остановки матлабовской машины используются две функции в DLL, и исполняются они, само собой, достаточно долго . По этому логично запускать их только один раз - в начале работы и при завершении соответственно, а не на каждом тике. То есть логично использовать бесконечный цикл - тогда ф-я start вызывается только один раз. Процесс работы советника тогда такой: 1)start() 2)Запускаем MATLAB 3)Бесконечный цикл while, в котором происходит основная работа и торговля 4)Выгружаем MATLAB 5)Завершение start().
При этом запустить MATLAB в init() и выгрузить его в deinit() нельзя по ряду причин. По крайней мере, мне это не удалось, может быть я что-то не понимаю.
Если убрать цикл, старт и стоп матлабовской машины будет происходить на каждом тике и занимать кучу времени - до нескольких секунд. Я правильно понимаю, что тестирование в этом случае будет невозможно? Просто до стадии тестирования пока не еще не дошел. Кто что может посоветовать?
Я этот момент обошел на редкость лениво и просто - через INIT.
bool GoToWhile;
int init()
{
//Для тестового режима запускаем простой старт.
//А для реального - зацикленный в WHILE.
if (IsTesting()==false && IsOptimization()==false) {GoToWhile=true; return(0);}
else {GoToWhile=false; return(0);}
}
int start();
{
if (GoToWhile==true) //Для работы на REAL И DEMO.
{
while (true)
{
//Все тело программы находится здесь
Sleep(500);
RefreshRates();
//Данные принудительно обновляются через строгие
//интервалы - если мы находимся в реальной торговле.
if (IsExpertEnabled()==false || IsStopped==true) {break;}
//WHILE прерывается кнопкой "Советники" в окне терминала.
}
}
if (GoToWhile==false) // Для тестирования и оптимизации.
{
//Все тело программы находится здесь.
//Данные идут потиково и перезапускается Старт.
}
return(0);
}
Может я чего-то не доглядел, но пока эта конструкция работает на DEMO и на тестере без проблем.
P.S. Чтоб у вас все было и вам за это ничего не было.
Доброе время суток. Лениво и просто - перед закрывающей while скобкой прописать if(IsTesting()) break; проверял. работает. У меня проблема: while не работает без строки Comment(). При запуске на демо приведённого ниже кода открываю терминал и слежу насколько код успевает за реальным показанием профита.
extern string Symbols = "-1"; extern int Magic = -1; extern string Comments = "-1"; extern int Set_Y = 20; // Смещение по вертикали extern int Set_X = 50; // Смещение по горизонтали extern double updatesecond = 0.3; //время обновления в секундах double CurrentProfitAll; //------- Поключение внешних модулей ------------------------------------------- #include <stdlib.mqh> //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() {return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- Comment(""); ObjectDelete("1"); ObjectDelete("2"); //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() {while (IsExpertEnabled()) {Sleep (1000*updatesecond); RefreshRates(); //Comment("без Comment не работает ?!"); CurrentProfitAll = GetProfitOpenPosInCurrency("", -1, Magic, Comments); SetLabel("1", DoubleToStr(CurrentProfitAll,2), "Arial Black",Red, Set_X, Set_Y, 1, 10); SetLabel("2", "CurrentProfit", "Arial Black",Red, Set_X+80, Set_Y, 1, 10); } return(0); } //+----------------------------------------------------------------------------+ // текущий профит. //+----------------------------------------------------------------------------+ double GetProfitOpenPosInCurrency(string sy, int op, int mn ,string comm) { double p, pr=0; int i, k=OrdersTotal(); if (sy=="0") sy=Symbol(); for (i=0; i<k; i++) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) { if ((mn<0 || OrderMagicNumber()==mn)&&(comm=="-1" || OrderComment()==comm)) { p=MarketInfo(OrderSymbol(), MODE_POINT); if (p==0) if (StringFind(OrderSymbol(), "JPY")<0) p=0.0001; else p=0.01; if (OrderType()==OP_BUY) { pr+=OrderProfit()+OrderCommission()+OrderSwap();// } if (OrderType()==OP_SELL) { pr+=OrderProfit()+OrderCommission()+OrderSwap();// } } } } } return(pr); } //+----------------------------------------------------------------------------+ void SetLabel(string nm, string tx, string font_name,color cl, int xd, int yd, int cr=0, int fs=9) { if (ObjectFind(nm)<0) ObjectCreate(nm, OBJ_LABEL, 0, 0,0); ObjectSetText(nm, tx, fs, font_name); ObjectSet(nm, OBJPROP_COLOR , cl); ObjectSet(nm, OBJPROP_XDISTANCE, xd); ObjectSet(nm, OBJPROP_YDISTANCE, yd); ObjectSet(nm, OBJPROP_CORNER , cr); ObjectSet(nm, OBJPROP_FONTSIZE , fs); } //+----------------------------------------------------------------------------+
так вот если убрать из кода строчку
Comment("без Comment не работает ?!");
(она закомментирована) то цикл явно не работает. Тоесть в таком виде как выложен данные обрабатываются некорректно. Так должно быть или чтото не то пытаюсь сделать?
Доброе время суток. Лениво и просто - перед закрывающей while скобкой прописать if(IsTesting()) break; проверял. работает. У меня проблема: while не работает без строки Comment(). При запуске на демо приведённого ниже кода открываю терминал и слежу насколько код успевает за реальным показанием профита.
так вот если убрать из кода строчку
(она закомментирована) то цикл явно не работает. Тоесть в таком виде как выложен данные обрабатываются некорректно. Так должно быть или чтото не то пытаюсь сделать?
Доброго времени суток! А вот мне кажется, что тут все нормально. Может у вас терминал кривой - не 221 случайно, или выключены бибиотеки и импорт из DLL. У меня ваша функция отработала на демо как положено. С проверкой через Print() и ВЫКЛюченном Comment'е.
Дело по моему не в функции, поищите проблемму где-то в другом месте. Может быть вы на демо как-то некорректно работаете с объектами - у меня-то ведь с первого раза запустилась как надо. Или именно в том и лажа, что библиотеки не все подключены, поэтому некоторые команды игнорируются. Да еще одно замечание - может стоит поменять местами вызов функции и RefreshRates().
Я обычно подключаю <WinUser32.mqh> <stdlib.mqh> <stderror.mqh> и все путем :)
P.S. Чтоб у вас все бало и вам за это ничего не было.
Доброго времени суток! А вот мне кажется, что тут все нормально. Может у вас терминал кривой - не 221 случайно, или выключены бибиотеки и импорт из DLL. У меня ваша функция отработала на демо как положено. С проверкой через Print() и ВЫКЛюченном Comment'е.
Терминал 224. бибиотеки и импорт из DLL включены. уточню ситуацию. С проверкой через Print() и ВЫКЛюченном Comment'е это выглядит так:
видно что циклы проходят, но показания кода и терминала явно расходятся. А вот если Comment включить, то графика кода вполне успевает за терминалом. Вариации с расположением RefreshRates(), Comment() и Print() ничего не меняют. Вот и ломаю голову - почему эта строчка Comment так влияет на цикл. Или на графику. Или плюнуть на всё.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Доброго времени суток! Давече я писАл о глюках While, но похоже, что глюки не у While, а скорее у RefreshRates и Sleep. Они не работают в тестере вообще (или в тестере, когда они внутри While). Следующий код это наглядно демонстрирует.
int start()
{
int i=0; //Счетчик циклов WHILE
int delay=(1000*60*60); // 1секунда * 60секунд * 60минут (Время ожидания между проходами цикла 1 час)
Print ("Local ДО ",TimeHour(TimeLocal()),"H",TimeMinute(TimeLocal()),"M",TimeSeconds(TimeLocal()),"S");
Print ("Тик до цикла ", GetTickCount());
while(true)
{ //Управление находится внутри WHILE и START НЕ должен запускаться по тику
i++; //Пока WHILE не завершит работу
Print("Проход №",i," Local В ЦИКЛЕ ДО задержки ",TimeHour(TimeLocal()),"H",TimeMinute(TimeLocal()),"M",TimeSeconds(TimeLocal()),"S");
Print ("Проход №",i," Тик до ожидания ", GetTickCount());
Sleep(delay); //************* Подождем 1 час *******************
RefreshRates(); //Обновим данные (через час после входа в цикл)
Print("Local В ЦИКЛЕ ПОСЛЕ задержки ", TimeHour(TimeLocal()),"H",TimeMinute(TimeLocal()),"M",TimeSeconds(TimeLocal()),"S");
Print ("Тик после ожидания ", GetTickCount());
if (i==10) break; //Прерываем после 10 циклов ожидания по 1 часу каждый
}
RefreshRates(); //Обновим данные после выхода из WHILE
Print ("Local ПОСЛЕ ",TimeHour(TimeLocal()),"H",TimeMinute(TimeLocal()),"M",TimeSeconds(TimeLocal()),"S");
Print ("Тик после цикла ", GetTickCount());
return(0);
}
В журнале после запуска на тестере получам примерно следуюшее.
09:02:28 WhileTest started for testing
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local ДО 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик до цикла 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №1 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №1 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S (А где же тут разница в 1 час?!)
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №2 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №2 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №3 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №3 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №4 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №4 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №5 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №5 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №6 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №6 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №7 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №7 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №8 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №8 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №9 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №9 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №10 Local В ЦИКЛЕ ДО задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Проход №10 Тик до ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local В ЦИКЛЕ ПОСЛЕ задержки 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после ожидания 8277937
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Local ПОСЛЕ 17H49M0S
09:02:28 2008.05.30 17:49 WhileTest USDCAD,M1: Тик после цикла 8277937
Из чего можно сделать вывод: While перезапускался 10 раз без Refresh'а и без Sleep'а. Если погонять эту прогу на DEMO она перезапускает WHILE раз в час и через 10 часов заканчивает его исполнять. Таким образом получается, что проги с While'ом на основе временных факторов работать не могут и Refresh, а также Sleep на тестере не реализованы как надо.
Если у кого есть мнения или объяснения - милости прошу ;)
А что касается DEMO. то у меня уже пару дней там вертится Советник с зацикленным на чисто While'ом внутри старта. который в отличие от глюков тестера не залипает глухо при обрыве связи или Отжатой кнопке [Советники], а терпеливо ожидает прокручивая while с интервалом в 10 секунд. в любой не очень аварийной ситуации Советник сам готов перезапуститься и откоректировать свои ошибки типа (нет цены., сервер занят, связь потеряна, поток занят, ненормализованная цена, торги закрыты из-за выходных и др.) При обрыве он ждет. А при коннекте пересчитывает позиции и начинает работать, как ни в чем ни бывало. Страно то. что мане почти не попадалось советников. которые себя корректируют, большинство только выкидывает код ошибки.
P.S. Чтоб у Вас Все было и Вам за это Ничего не было