Таймер торгового времени

 

Всем здравствуйте!

в испытании на реальном счете  по этим условиям закрытия позы  возникает дребезг позиции на клирингах , т.е  открытие и немедленное закрытие ордера ,,,,, такое впечатление что советник  закрывает позицию объемом в два раза больше чем открыта позиция, устанавливает ордер и опять закрывает  .и так пока все не сольет 

в чем причина и как с этим бороться не могу сообразить , подскажите!

вот конструкция кода  таймера

input string                                    i_sTimeSettings                 = "Настройки времени торговли";                //   input bool                                      i_bExitClearing1      = true;              // Закрывать позицию перед клирингом 1 input string                                    i_sClearing1StartTime   = "13:00";         // Время начала клиринга 1 input string                                    i_sClearing1EndTime     = "13:03";        // Время окончания клиринга 1 input bool                                      i_bExitClearing2        = true;           // Закрывать позицию перед клирингом 2 input string                                    i_sClearing2StartTime   = "15:45";        // Время начала клиринга 2 input string                                    i_sClearing2EndTime     = "16:00";        // Время окончания клиринга 2 input bool                                      i_bExitEndSession       = true;          // Закрывать позицию перед окончанием сессии input string                                    i_sEndSessionTime       = "22:55";       // Время окончания сессии // Глобальные переменные. // время начала и окончания клиринга и окочания сессии datetime g_dtClearing1StartTime, g_dtClearing1EndTime; datetime g_dtClearing2StartTime, g_dtClearing2EndTime; datetime g_dtEndSessionTime; // время открытия последнего бара datetime g_dtLastBarTime = 0; int OnInit() { // время торгов         g_dtClearing1StartTime = StringToTime(i_sClearing1StartTime) % 86400;         g_dtClearing1EndTime = StringToTime(i_sClearing1EndTime) % 86400;                  g_dtClearing2StartTime = StringToTime(i_sClearing2StartTime) % 86400;         g_dtClearing2EndTime = StringToTime(i_sClearing2EndTime) % 86400;                  g_dtEndSessionTime = StringToTime(i_sEndSessionTime) % 86400;                  // Сохраним в глобальной переменной время открытия текущего бара.         datetime dtTime[1];         CopyTime(_Symbol, _Period, 0, 1, dtTime);         g_dtLastBarTime = dtTime[0];                  // Если дошли до этого места, значит всё в порядке, инициализация эксперта прошла успешно.         return(INIT_SUCCEEDED); } void OnTick() {         // Проверим, находимся ли мы на открытии нового бара,         // для этого сравним время текущего бара с сохранённым в глобальной переменной временем.         bool bNewBar = false;                  datetime dtTime[1];         CopyTime(_Symbol, _Period, 0, 1, dtTime);                  if(dtTime[0] > g_dtLastBarTime)                 bNewBar = true;                          g_dtLastBarTime = dtTime[0];         // Определим, торговое ли сейчас время (не перед клирином ли и не конец ли сессии)         // Конструкции вида dtCurrentTime % 86400 - остаток от деления времени на количество секунд в сутках,         // т.е. количество секунд, прошедших с начала суток.         // Закрываемся за минуту до клиринга.         datetime dtCurrentTime = TimeCurrent();         bool bTradeTime = true;                  if(i_bExitClearing1 && (dtCurrentTime % 86400 >= g_dtClearing1StartTime - 60) && (dtCurrentTime % 86400 <= g_dtClearing1EndTime))                 bTradeTime = false;                          if(i_bExitClearing2 && (dtCurrentTime % 86400 >= g_dtClearing2StartTime - 60) && (dtCurrentTime % 86400 <= g_dtClearing2EndTime))                 bTradeTime = false;                          if(i_bExitEndSession && (dtCurrentTime % 86400 >= g_dtEndSessionTime - 60))                 bTradeTime = false;         if(PositionSelect(_Symbol) == true)         {                 // в неторговое время немедленно всё закрываем                 if(bTradeTime == false)                 {                         ClosePosition(_Symbol);

// функция полного или частичного закрытия позиции противоположным маркет ордером

// если указанный в параметрах лот == 0, то позиция закрывается полностью, // в противном случае - сокращается на указанный объём bool ClosePosition(const string sSymbol, double fLot = 0) {         bool bRetVal = false;                  if(PositionSelect(sSymbol) == false)                 return(false);          // нет позиции                  // запрос         MqlTradeRequest oRequest = {0};         MqlTradeResult   oResult = {0};                  double fPoint = SymbolInfoDouble(sSymbol, SYMBOL_POINT);         int nDigits     = (int) SymbolInfoInteger(sSymbol, SYMBOL_DIGITS);                  oRequest.action                 = TRADE_ACTION_DEAL;         oRequest.symbol                 = sSymbol;                  if(fLot == 0)         {                 oRequest.volume         = PositionGetDouble(POSITION_VOLUME);                 oRequest.sl                             = 0;                 oRequest.tp                             = 0;         }         else         {                 oRequest.volume         = fLot;                 oRequest.sl                             = PositionGetDouble(POSITION_SL);                 oRequest.tp                             = PositionGetDouble(POSITION_TP);         }                          oRequest.stoplimit              = 0;         oRequest.deviation              = 1000;         // определим допустимый тип заливки маркет-ордера         switch((int) SymbolInfoInteger(sSymbol, SYMBOL_FILLING_MODE))         {         case SYMBOL_FILLING_FOK:                 oRequest.type_filling = ORDER_FILLING_FOK;                 break;         case SYMBOL_FILLING_IOC:                 oRequest.type_filling = ORDER_FILLING_IOC;                 break;         default:                 oRequest.type_filling = ORDER_FILLING_RETURN;         }                  switch((int) PositionGetInteger(POSITION_TYPE))         {         case POSITION_TYPE_BUY:                 oRequest.type           = ORDER_TYPE_SELL;                 oRequest.price          = NormalizeDouble(SymbolInfoDouble(sSymbol, SYMBOL_BID), nDigits);                 break;         case POSITION_TYPE_SELL:                 oRequest.type           = ORDER_TYPE_BUY;                 oRequest.price          = NormalizeDouble(SymbolInfoDouble(sSymbol, SYMBOL_ASK), nDigits);                 break;         }         // проверка перед отправкой         MqlTradeCheckResult oCheckResult= {0};                  bool bCheck = OrderCheck(oRequest, oCheckResult);         Print("Проверка заявки ClosePosition:",                         " OrderCheck = ",               bCheck,                         ", retcode = ",         oCheckResult.retcode,                         ", balance = ",         NormalizeDouble(oCheckResult.balance, 2),                         ", equity = ",                  NormalizeDouble(oCheckResult.equity, 2),                         ", margin = ",                  NormalizeDouble(oCheckResult.margin, 2),                         ", margin_free = ",     NormalizeDouble(oCheckResult.margin_free, 2),                         ", margin_level = ",    NormalizeDouble(oCheckResult.margin_level, 2),                         ", comment = ",         oCheckResult.comment);                  // если проверка удачная - отправка заявки         if(bCheck == true && oCheckResult.retcode == 0)         {                 bool bResult = false;                                  // 3 попытки закрытия позиции с интервалом 250 мс.                 for(int k = 0; k < 3; k++)                 {                         bResult = OrderSend(oRequest, oResult);                                                  if(bResult == true && oResult.retcode == TRADE_RETCODE_DONE)                                 break;                                                  if(k == 2)                                 break;                                                          Sleep(100);                 }                          Print("Отправка заявки:",                                 " OrderSend = ",        bResult,                                 ", retcode = ", oResult.retcode,                                 ", deal = ",            oResult.deal,                                 ", order = ",           oResult.order,                                 ", volume = ",          NormalizeDouble(oResult.volume, 2),                                 ", price = ",           NormalizeDouble(oResult.price, _Digits),                                 ", bid = ",                     NormalizeDouble(oResult.bid, _Digits),                                 ", ask = ",                     NormalizeDouble(oResult.ask, _Digits),                                 ", comment = ", oResult.comment,                                 ", request_id = ",oResult.request_id);                                                    if(oResult.retcode == TRADE_RETCODE_DONE)                         bRetVal = true;         }                  return(bRetVal); }


 

 

Александр,

В MT5 успешная отправка ордера не означает его исполнение, а только его постановка в очередь. Следовательно, когда вы отправляете повторный ордер на новом тике, возможно в очереди уже весит не исполненый ордер с предыдущего тика. В таком случае, при отправке второго ордера, Ваша позиция перевернется и на следующем тике вы ее будете опять закрывать.

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

Второй вариант, перед отправкой ордера, проверять наличие не исполненных ордеров в очереди.

Третий вариант, сохранить тикет отправленного ордера, установить флаг, что ордер уже отправлен. И прописать функцию OnTradeTransaction на проверку результата исполнения ордера. И только при отклонении ордера или не полном исполнении отправлять повторный ордер на закрытие позиции.

С уважением,

Дмитрий.

 
Dmitriy Gizlyk:

Александр,

В MT5 успешная отправка ордера не означает его исполнение, а только его постановка в очередь. Следовательно, когда вы отправляете повторный ордер на новом тике, возможно в очереди уже весит не исполненый ордер с предыдущего тика. В таком случае, при отправке второго ордера, Ваша позиция перевернется и на следующем тике вы ее будете опять закрывать.

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

Второй вариант, перед отправкой ордера, проверять наличие не исполненных ордеров в очереди.

Третий вариант, сохранить тикет отправленного ордера, установить флаг, что ордер уже отправлен. И прописать функцию OnTradeTransaction на проверку результата исполнения ордера. И только при отклонении ордера или не полном исполнении отправлять повторный ордер на закрытие позиции.

С уважением,

Дмитрий.

Огромное спасибо !!!!

зная о не знании  начал фантазировать с временем ,думал ошибка кроится в интервале  250мс

еще раз огромное спасибо!


  // 3 попытки закрытия позиции с интервалом 250 мс.                 for(int k = 0; k < 3; k++)                 {