Подскажите, пожалуйста. Пишу робота на минутках. Начинаю анализ последнего бара за пару секунд до его закрытия. И иногда, очень редко, выполнение моего кода анализа занимает больше двух секунд, почему-то то ли подвисает терминал, то ли ещё что.. и тогда уже появляется новый бар, и в конце анализа (не успевший выполниться код) в выражении типа Close[0], Open[0] и т.д. - начинает рассматриваться уже новый бар, потому что нужный мне уже имеет значения Close[1], Open[1] и т.д. . Не знаю, понятно ли объяснил, но как можно избежать такой ситуации...?
- Как кодировать?
- Рисуем значок индикатором, когда не нужен - он всеравно остается....
- Если в эксперте, который я пишу, мне нужно анализировать массивы цен только тогда, когда бары обновились по истечению времени. Что применить?
Максим Пругло:
Подскажите, пожалуйста. Пишу робота на минутках. Начинаю анализ последнего бара за пару секунд до его закрытия. И иногда, очень редко, выполнение моего кода анализа занимает больше двух секунд, почему-то то ли подвисает терминал, то ли ещё что.. и тогда уже появляется новый бар, и в конце анализа (не успевший выполниться код) в выражении типа Close[0], Open[0] и т.д. - начинает рассматриваться уже новый бар, потому что нужный мне уже имеет значения Close[1], Open[1] и т.д. . Не знаю, понятно ли объяснил, но как можно избежать такой ситуации...?
Подскажите, пожалуйста. Пишу робота на минутках. Начинаю анализ последнего бара за пару секунд до его закрытия. И иногда, очень редко, выполнение моего кода анализа занимает больше двух секунд, почему-то то ли подвисает терминал, то ли ещё что.. и тогда уже появляется новый бар, и в конце анализа (не успевший выполниться код) в выражении типа Close[0], Open[0] и т.д. - начинает рассматриваться уже новый бар, потому что нужный мне уже имеет значения Close[1], Open[1] и т.д. . Не знаю, понятно ли объяснил, но как можно избежать такой ситуации...?
При открытии нового бара фиксируйте его дату и по ней проверяйте
Могут отсутствовать тики для генерации события, нужен таймер
То есть единственный вариант, например, при начале работы кода записать в глобальную переменную чёткое значение Time[0] и уже конкретно по нему посредством iBarShift вычислять номер бара в процессе работы всего кода..?
int CopyRates( string symbol_name, // имя символа ENUM_TIMEFRAMES timeframe, // период datetime start_time, // с какой даты int count, // сколько копируем MqlRates rates_array[] // массив, куда будут скопированы данные );
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyRates
- www.mql5.com
CopyRates - Доступ к таймсериям и индикаторам - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
Максим Пругло:
То есть единственный вариант, например, при начале работы кода записать в глобальную переменную чёткое значение Time[0] и уже конкретно по нему посредством iBarShift вычислять номер бара в процессе работы всего кода..?
То есть единственный вариант, например, при начале работы кода записать в глобальную переменную чёткое значение Time[0] и уже конкретно по нему посредством iBarShift вычислять номер бара в процессе работы всего кода..?
Либо через iBarShift, либо как Алексей посоветовал. Но проверять нужно через время бара... Можно так же просто создать переменные цен... Типа:
if(lastBarTime != Time(0)){ check(); lastBarTime = Time(0); // и обнулить переменные цен наверное... }else{ lastHigh = High[0], lastOpen = Open[0], lastClose = Close[0], lastLow = low[0]; }
всем спасибо за помощь, вариантов несколько, выберу один из них)))
Максим Пругло:
Подскажите, пожалуйста. Пишу робота на минутках.
Подскажите, пожалуйста. Пишу робота на минутках.
интересно посмотреть на Ваш начальный способ реализации
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
https://www.mql5.com/ru/docs/event_handlers/ontesterinit
//+------------------------------------------------------------------+ //| OnTesterInit_Sample.mq5 | //| Copyright 2018, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property description "Пример советника с обработчиком OnTesterInit()" #property description "в котором устанавливаются зачения и границы " #property description "входных параметров при оптимизации" input double lots=0. 1; // объем в лотах input double kATR=3; // длина сигнальной свечи в ATR input int ATRperiod=20; // период индикатора ATR input int holdbars=8; // сколько баров удерживаем позицию input int slippage=10; // допустимое проскальзывание input bool revers=false; // переворачиваем сигнал? input ulong EXPERT_MAGIC=0; // MagicNumber эксперта //--- для хранения хендла индикатора ATR int atr_handle; //--- здесь будем хранить последние значения ATR и тела свечи double last_atr,last_body; datetime lastbar_timeopen; double trade_lot; //--- запоминаем время начала оптимизации datetime optimization_start; //--- для вывода на график длительности после окончании оптимизации string report; //+------------------------------------------------------------------+ //| TesterInit function | //+------------------------------------------------------------------+ void OnTesterInit() { //--- установим значения входных параметров для оптимизации ParameterSetRange("lots",false,0.1,0,0,0); ParameterSetRange("kATR",true,3.0,1.0,0.3,7.0); ParameterSetRange("ATRperiod",true,10,15,1,30); ParameterSetRange("holdbars",true,5,3,1,15); ParameterSetRange("slippage",false,10,0,0,0); ParameterSetRange("revers",true,false,false,1,true); ParameterSetRange("EXPERT_MAGIC",false,123456,0,0,0); Print("Установлены начальные значения и границы параметров оптимизации"); //--- запомним начало оптимизации optimization_start=TimeLocal(); report=StringFormat("%s: оптимизация запущена в %s", __FUNCTION__,TimeToString(TimeLocal(),TIME_MINUTES|TIME_SECONDS)); //--- выведем собщения на график и в журнал терминала Print(report); Comment(report); //--- } //+------------------------------------------------------------------+ //| TesterDeinit function | //+------------------------------------------------------------------+ void OnTesterDeinit() { //--- продолжительность оптимизации string log_message=StringFormat("%s: оптимизация заняла %d секунды", __FUNCTION__,TimeLocal()-optimization_start); PrintFormat(log_message); report=report+"\r\n"+log_message; Comment(report); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- инициализируем глобальные переменные last_atr=0; last_body=0; //--- установим правильный объем double min_lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); trade_lot=lots>min_lot? lots:min_lot; //--- создадим хендл индикатора ATR atr_handle=iATR(_Symbol,_Period,ATRperiod); if(atr_handle==INVALID_HANDLE) { PrintFormat("%s: не удалось создать iATR, код ошибки %d",__FUNCTION__,GetLastError()); return(INIT_FAILED); } //--- успешная инициализация эксперта return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- торговый сигнал static int signal=0; // +1 означает сигнал на покупку, -1 означает сигнал на продажу //--- проверим и закроем старые позиции, открытые более holdbars баров назад ClosePositionsByBars(holdbars,slippage,EXPERT_MAGIC); //--- проверим появление нового бара if(isNewBar()) { //--- проверим наличие сигнала signal=CheckSignal(); } //--- если открыта неттинговая позиция, то сигнал пропускаем - ждем, пока она закроется if(signal!=0 && PositionsTotal()>0 && (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_NETTING) { signal=0; return; // выходим из обработчика события NewTick и не входим в рынок до появления нового бара } //--- для хеджингового счета каждая позиция живет и закрывается раздельно if(signal!=0) { //--- сигнал на покупку if(signal>0) { PrintFormat("%s: Есть сигнал на покупку! Revers=%s",__FUNCTION__,string(revers)); if(Buy(trade_lot,slippage,EXPERT_MAGIC)) signal=0; } //--- сигнал на продажу if(signal<0) { PrintFormat("%s: Есть сигнал на продажу! Revers=%s",__FUNCTION__,string(revers)); if(Sell(trade_lot,slippage,EXPERT_MAGIC)) signal=0; } } //--- конец функции OnTick } //+------------------------------------------------------------------+ //| Проверяет наличие торгового сигнала | //+------------------------------------------------------------------+ int CheckSignal() { //--- 0 означает отсутствие сигнала int res=0; //--- получим значение ATR на предпоследнем завершенном баре (индекс бара равен 2) double atr_value[1]; if(CopyBuffer(atr_handle,0,2,1,atr_value)!=-1) { last_atr=atr_value[0]; //--- получим данные последнего закрытого бара в массив типа MqlRates MqlRates bar[1]; if(CopyRates(_Symbol,_Period,1,1,bar)!=-1) { //--- вычислим размер тела бара на последнем закрытом баре last_body=bar[0].close-bar[0].open; //--- если тело последнего бара (с индексом 1) превышает предыдущее значение ATR (на баре с индексом 2), то торговый сигнал получен if(MathAbs(last_body)>kATR*last_atr) res=last_body>0?1:-1; // для растущей свечи положительное значение } else PrintFormat("%s: Не удалось получить последний бар! Ошибка",__FUNCTION__,GetLastError()); } else PrintFormat("%s: Не удалось получить значение индикатора ATR! Ошибка",__FUNCTION__,GetLastError()); //--- если включен реверсивный режим торговли res=revers?-res:res; // если нужно, то развернем сигнал (вместо 1 вернем -1, а вместо -1 вернем +1) //--- вернем значение торгового сигнала return (res); } //+------------------------------------------------------------------+ //| Возвращает true при появлении нового бара | //+------------------------------------------------------------------+ bool isNewBar(const bool print_log=true) { static datetime bartime=0; // храним время открытия текущего бара //--- получим время открытия нулевого бара datetime currbar_time=iTime(_Symbol,_Period,0); //--- если время открытия изменилось, значит появился новый бар if(bartime!=currbar_time) { bartime=currbar_time; lastbar_timeopen=bartime; //--- нужно ли выводить в лог информацию о времени открытия нового бара if(print_log && !(MQLInfoInteger(MQL_OPTIMIZATION)||MQLInfoInteger(MQL_TESTER))) { //--- выведем сообщение о времени открытия нового бара PrintFormat("%s: new bar on %s %s opened at %s",__FUNCTION__,_Symbol, StringSubstr(EnumToString(_Period),7), TimeToString(TimeCurrent(),TIME_SECONDS)); //--- получим данные о последнем тике MqlTick last_tick; if(!SymbolInfoTick(Symbol(),last_tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); //--- выведем время последнего тика с точностью до миллисекунд PrintFormat("Last tick was at %s.%03d", TimeToString(last_tick.time,TIME_SECONDS),last_tick.time_msc%1000); } //--- у нас есть новый бар return (true); } //--- нового бара нет return (false); } //+------------------------------------------------------------------+ //| Покупка по рынку с заданным объемом | //+------------------------------------------------------------------+ bool Buy(double volume,ulong deviation=10,ulong magicnumber=0) { //--- покупаем по рыночной цене return (MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber)); } //+------------------------------------------------------------------+ //| Продажа по рынку с заданным объемом | //+------------------------------------------------------------------+ bool Sell(double volume,ulong deviation=10,ulong magicnumber=0) { //--- продаем по рыночной цене return (MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber)); } //+------------------------------------------------------------------+ //| Закрытие позиций по времени удержания в барах | //+------------------------------------------------------------------+ void ClosePositionsByBars(int holdtimebars,ulong deviation=10,ulong magicnumber=0) { int total=PositionsTotal(); // количество открытых позиций //--- перебор всех открытых позиций for(int i=total-1; i>=0; i--) { //--- параметры позиции ulong position_ticket=PositionGetTicket(i); // тикет позиции string position_symbol=PositionGetString(POSITION_SYMBOL); // символ ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber позиции datetime position_open=(datetime)PositionGetInteger(POSITION_TIME); // время открытия позиции int bars=iBarShift(_Symbol,PERIOD_CURRENT,position_open)+1; // сколько баров назад была открыта позиция //--- если позиция живет уже долго, а также MagicNumber и символ совпадают if(bars>holdtimebars && magic==magicnumber && position_symbol==_Symbol) { int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // количество знаков после запятой double volume=PositionGetDouble(POSITION_VOLUME); // объем позиции ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // тип позиции string str_type=StringSubstr(EnumToString(type),14); StringToLower(str_type); // понижаем регистр текста для правильного форматирования сообщения PrintFormat("Закрываем позицию #%d %s %s %.2f", position_ticket,position_symbol,str_type,volume); //--- установка типа ордера и отправки торгового запроса if(type==POSITION_TYPE_BUY) MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber,position_ticket); else MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber,position_ticket); } } } //+------------------------------------------------------------------+ //| Подготовка и отправка торгового запроса | //+------------------------------------------------------------------+ bool MarketOrder(ENUM_ORDER_TYPE type,double volume,ulong slip,ulong magicnumber,ulong pos_ticket=0) { //--- объявление и инициализация cтруктур MqlTradeRequest request={0}; MqlTradeResult result={0}; double price=SymbolInfoDouble(Symbol(),SYMBOL_BID); if(type==ORDER_TYPE_BUY) price=SymbolInfoDouble(Symbol(),SYMBOL_ASK); //--- параметры запроса request.action =TRADE_ACTION_DEAL; // тип торговой операции request.position =pos_ticket; // тикет позиции, если закрываем request.symbol =Symbol(); // символ request.volume =volume; // объем request.type =type; // тип ордера request.price =price; // цена совершения сделки request.deviation=slip; // допустимое отклонение от цены request.magic =magicnumber; // MagicNumber ордера //--- отправка запроса if(!OrderSend(request,result)) { //--- выведем информацию о неудаче PrintFormat("OrderSend %s %s %.2f at %.5f error %d", request.symbol,EnumToString(type),volume,request.price,GetLastError()); return (false); } //--- сообщим об успешной операции PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); return (true); }
Документация по MQL5: Обработка событий / OnTesterInit
- www.mql5.com
OnTesterInit - Обработка событий - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
SanAlex:
интересно посмотреть на Ваш начальный способ реализации
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь