Как правильно выяснить, что рынок закрыт? (mql4)

 

Перевел советника в режим работы OnTimer() теперь когда рынок закрыт он этого не понимает и пытается торговать, в общем обращается к серверу и естественно получает ошибки и забивает логи журнала. GetLastError() = Рынок закрыт. Какие ещё условия проверки на выходной день или закрытый рынок можно придумать ?

   if (DayOfWeek()==0 || DayOfWeek()==6) // Не помогает, последнее время сервера 21:54 ПЯТНИЦА хотя реально сейчас суббота!
      {
         TradeEnabled = 0;
      }
   else
      {
         TradeEnabled = 1;
      } 
MarketInfo(symbol,MODE_TRADEALLOWED) // не помогает, всегда возвращает True
 
добавьте паузу или запрет торговых приказов в определенное время
 
Мне под mql4 надо, и да эксперт видит что сегодня пятница, хотя фактически суббота.
 

Если правильно, то ни одним из указанных способов, т. к. делать код для каждого брокера (у каждого свой регламент) под разные символы неудобно.

Однозначно определяется так:

1. Осуществляется любая торговая операция.

2. В ответ на  операцию получаем код ошибки 132 (ERR_MARKET_CLOSED).

 

Далее, чтобы не пропустить открытие рынка, можно повторять торговые операции с некоторой периодичностью.

К примеру, в одном советнике, который работает с множеством символов, я сделал так:

bool DoTrade(ENUM_TRADE_TYPE tradeType, TradeParam &tradeParam)
{
   // Проверка возможности проведения торговой операции по символу
   if (!IsSymbolTradeAllowed(tradeParam.symbol))
      return false;
   
   bool res = true;
   int ticket = 0;
   switch (tradeType)
   {
      case TRADE_TYPE_DELETE:    res = OrderDelete(tradeParam.orderTicket);                                                                  break;
      case TRADE_TYPE_CLOSE:     res = OrderClose(tradeParam.orderTicket, tradeParam.orderVolume, tradeParam.orderCP, i_slippage);           break;
      case TRADE_TYPE_CLOSEBY:   res = OrderCloseBy(tradeParam.orderTicket, tradeParam.orderTicketCounter);                                  break;
      case TRADE_TYPE_MODIFY:    res = OrderModify(tradeParam.orderTicket, tradeParam.orderOP, tradeParam.orderSL, tradeParam.orderTP, 0);   break;
      case TRADE_TYPE_OPEN:      {
                                    tradeParam.orderTicket = OrderSend(tradeParam.symbol, tradeParam.orderType, 
                                                                       tradeParam.orderVolume, tradeParam.orderOP, 
                                                                       i_slippage, tradeParam.orderSL, tradeParam.orderTP, 
                                                                       "", tradeParam.orderMN);  
                                    res = (tradeParam.orderTicket > 0);
                                    break;
                                 }
   }
   
   int error = GetLastError();
   if (!res)
   {
      ... // обработка других ошибок
      if (error == ERR_MARKET_CLOSED || error == ERR_OFF_QUOTES)
         AddSymbolToMarketClosedList(tradeParam.symbol);
   }
      
   return res;
}

 Функция проверки возможности торговли по символу:

bool IsSymbolTradeAllowed(string symbol)
{
   if (SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_FULL)
   {
      Alert(WindowExpertName(), ": невозможно совершить торговую операцию по символу ", symbol, ", т. к. по нему торговля запрещена!");
      AddSymbolToMarketClosedList(symbol, true);
      return false;
   }

   for (int i = g_marketSymbolsCnt - 1; i >= 0; i--)
      if (g_marketClosedSymbols[i].symbol == symbol)
         return (TimeCurrent() - g_marketClosedSymbols[i].lastRequest) > 60;
      
   return true;
}

 Функция записи символа, по которому нельзя торговать:

void AddSymbolToMarketClosedList(string symbol, bool isStopTrade = false)
{
   datetime time = TimeCurrent();
   if (isStopTrade)
      time = StringToTime("3000.01.01");

   for (int i = g_marketSymbolsCnt - 1; i >= 0; i--)
      if (g_marketClosedSymbols[i].symbol == symbol)
      {
         g_marketClosedSymbols[i].lastRequest = time;
         return;
      }
      
   if (g_marketSymbolsCnt >= MAX_SYMBOLS_AMOUNT)
      return;
      
   g_marketClosedSymbols[g_marketSymbolsCnt].symbol = symbol;
   g_marketClosedSymbols[g_marketSymbolsCnt].lastRequest = time;
   g_marketSymbolsCnt++;
}

 Как нетрудно догадаться, массив g_marketClosedSymbols - это массив структур.

 
Kino:

Перевел советника в режим работы OnTimer() теперь когда рынок закрыт он этого не понимает и пытается торговать, в общем обращается к серверу и естественно получает ошибки и забивает логи журнала. GetLastError() = Рынок закрыт. Какие ещё условия проверки на выходной день или закрытый рынок можно придумать ?

тики не приходят

серверное время не меняется 

if (DayOfWeek()==0 || DayOfWeek()==6) по времени компа  +/- серверное время 

 

если такая ошибка, то наверно выходные 

Scriptong 

 2. В ответ на  операцию получаем код ошибки 132 (ERR_MARKET_CLOSED).

 
input int       Timer_Sleep_After = 3600; // Если тиков нет уже час, знач рынок закрыт

datetime gt_Last_Tick_Time = 0;


void OnTimer() {
        if(TimeLocal() - gt_Last_Tick_Time > Timer_Sleep_After) return;
}


void OnTick() {
        gt_Last_Tick_Time = TimeLocal();
}
 
Scriptong:

Если правильно, то ни одним из указанных способов, т. к. делать код для каждого брокера (у каждого свой регламент) под разные символы неудобно.

Однозначно определяется так:

1. Осуществляется любая торговая операция.

2. В ответ на  операцию получаем код ошибки 132 (ERR_MARKET_CLOSED).

 

Далее, чтобы не пропустить открытие рынка, можно повторять торговые операции с некоторой периодичностью.

К примеру, в одном советнике, который работает с множеством символов, я сделал так:

 Функция проверки возможности торговли по символу:

 Функция записи символа, по которому нельзя торговать:

 Как нетрудно догадаться, массив g_marketClosedSymbols - это массив структур.

Спасибо за наводку на путь истинный, но когда рынок открыт пытаться определить возможность работы с ордерами это как то всеравно не корректно, но работать будет.
 
f2011:
Тоже спасибо, интересное решение.
 

Теперь вопрос к разработчикам МК, зачем делать событие которое никогда не сработает ? https://docs.mql4.com/ru/dateandtime/dayofweek

if(DayOfWeek()==0 || DayOfWeek()==6) return(0);

если работаю по тикам, то тиков нет и событие не произойдет, если работаю по таймеру то сервер выдает время прихода последнего ника к нему, то есть последние минуты пятницы и событие тоже никогда не произойдет. Получается у меня советник по таймеру, а сервер по тикам работает как и раньше, но сервер онлайн так как при отправке запроса выдает ошибку 132. Исправьте пожалуйста или чтобы на сервере время менялось по таймеру тоже или чтобы я мог проверить закрыт ли рынок без отправки торгового приказа. Это баг лютый, надеюсь на понимание и решение вопроса.

DayOfWeek - Документация на MQL4
  • docs.mql4.com
DayOfWeek - Документация на MQL4
 

int Weekday = TimeDayOfWeek(TimeLocal());                                                          //Локальное время  |
int Weekdays = TimeDayOfWeek(TimeCurrent());                                                       //Серверное время  |

while(IsExpertEnabled())                                                                 //До тех пор пока запушенно  |

     {
     if(Weekday!=0||Weekday!=6){Exp=true;if(Weekday==1){Info(4,Weekday,0);}}       //Если не Сбб. Воск. то разрешено  |
     if(Weekdays==0||Weekdays==6)                                                  //Если Сбб. Воск. то не разрешено  |
       {
       Exp=false;Info(5,Weekdays,0);
       if(Weekdays==6){Sleep(86400000);}                                                //Если суббота пауза 24 часа  |
       if(Weekdays==0){Sleep(3600000);}                                               //Если воскресение пауза 1 час  |
       }

Я примерно, так решил, через паузы и циклы, но это старый код, до обновления версии терминала. Сейчас есть более простые способы, нужно просто, немного почитать литературу.
 
Опять к МК! Если сервер знает что рынок закрыт и выдает ошибку 132, другими словами дайте запрос проверки открыт рынок или нет без обращения к работе с ордерами, это важно так как определение субботы и воскресения не совсем корректно, есть праздники и раннее закрытие торговой сессии и у каждого ДЦ оно отличается.
Причина обращения: