Одно событие срабатывает несколько раз. В чём причина?

 

Есть библиотека с функциями. Нас интересуют вот эти 2:

//=======================================================================================================================================================================================================
// Возвращает true, если сделки с тикетом ticket 'своя', иначе false. ===================================================================================================================================
bool choiceDealPrimary(const string symbolName,        // Название торгового инструмента
                       const ulong magic,              // Magic number позиции
                       const ulong ticket) export {    // Тикет сделки
//---
  if (!HistoryDealSelect(ticket))
    return false;
  if (selectedHistoryDealSymbol(ticket) != symbolName)
    return false;
  if (selectedHistoryDealMagic(ticket) != magic)
    return false;
//---
  return true;
}
//=======================================================================================================================================================================================================
// Возвращает DEAL_TYPE_BUY, если тип транзакции DEAL_TYPE_BUY или DEAL_TYPE_SELL, если тип транзакции DEAL_TYPE_SELL, иначе -1. ========================================================================
ENUM_DEAL_TYPE isOrderTransformToPosition(const MqlTradeTransaction& transaction,    // Транзакция
                                          const SymbolInstance *ptrSymbol,           // Указатель на класс свойств торгового инструмента
                                          const ulong magic) export {                // Magic number позиции
//---
  if (transaction.type == TRADE_TRANSACTION_DEAL_ADD) {
    if (!choiceDealPrimary(ptrSymbol.getName(), magic, transaction.deal))
      return false;
    if (selectedHistoryDealEntry(transaction.deal) == DEAL_ENTRY_IN) {
      if (selectedHistoryDealType(transaction.deal) == DEAL_TYPE_BUY) {
        return DEAL_TYPE_BUY;
      } else if (selectedHistoryDealType(transaction.deal) == DEAL_TYPE_SELL) {
        return DEAL_TYPE_SELL;
      }
    }
  }
//---
  return -1;
}

В OnTradeTransaction() вот что имеется:

  ENUM_DEAL_TYPE dealType = isOrderTransformToPosition(transaction, prSymbol, g_magic);

  // Если сделки, представляет собой преобразование ордера в позицию, тогда откроем противовес..
  if (dealType == DEAL_TYPE_BUY) {
    Print("dealType = DEAL_TYPE_BUY");
    if (!putOrder(ORDER_TYPE_SELL_STOP, g_price1, g_price2, false)) {    // Открывает ордер
      return;
    }
  } else if (dealType == DEAL_TYPE_SELL) {
    Print("dealType = DEAL_TYPE_SELL");
    if (!putOrder(ORDER_TYPE_BUY_STOP, g_price1, g_price2, false)) {    // Открывает ордер
      return;
    }
  }

Суть этого всего в том, что бы в тот момент, когда отложенный ордер станет позицией открыть противоположный. Так вот интересно, что неколько недель на низком ТФ много сделок проходит. Всё отрабатывается корректно. Но, попадаются места, где событие косячит. Происходит установка не 1, а 2 отложенных ордеров, что есс-но не требуется. Здесь мы видим Print(), который я сделал, когда отлавливал, где косяк.

В логе видно:

2018.08.13 14:13:07.587 2016.01.04 21:08:20   deal #6 sell 0.10 GBPJPY at 175.453 done (based on order #8)
2018.08.13 14:13:07.587 2016.01.04 21:08:20   deal performed [#6 sell 0.10 GBPJPY at 175.453]
2018.08.13 14:13:07.587 2016.01.04 21:08:20   order performed sell 0.10 at 175.453 [#8 sell stop 0.10 GBPJPY at 175.453]
2018.08.13 14:13:07.587 2016.01.04 21:08:20   dealType = DEAL_TYPE_SELL
2018.08.13 14:13:07.587 2016.01.04 21:08:20   buy stop 0.10 GBPJPY at 175.660 (175.450 / 175.481 / 175.450)
2018.08.13 14:13:07.587 2016.01.04 21:08:20   dealType = DEAL_TYPE_SELL
2018.08.13 14:13:07.587 2016.01.04 21:08:20   buy stop 0.20 GBPJPY at 175.660 (175.450 / 175.481 / 175.450)
2018.08.13 14:13:08.116 2016.01.04 21:10:00   position modified [#6 buy 0.10 GBPJPY 175.660]
2018.08.13 14:13:08.116 2016.01.04 21:10:00   position modified [#7 sell 0.10 GBPJPY 175.453]
2018.08.13 14:13:08.116 2016.01.04 21:10:00   position modified [#8 sell 0.10 GBPJPY 175.453]

Очевидно, что в блок:

 else if (dealType == DEAL_TYPE_SELL) {
}

Вошли несколько раз, хотя.. не было там 2 преобразований рыночных ордеров в позиции, что и логично. Может как-то можно это обработать, что бы не натыкаться на подобный косяк?

 

Причина в том, что у Вас нет флага, что предыдущее событие полностью отработало.

Посылая ордер, в OnTick и/или OnBookEvent нужно выставлять флаг запрета обработки кода, пока

Вы точно не выяснили как отработал отосланный ордер.

 
prostotrader:

Причина в том, что у Вас нет флага, что предыдущее событие полностью отработало.

Посылая ордер, в OnTick и/или OnBookEvent нужно выставлять флаг запрета обработки кода, пока

Вы точно не выяснили как отработал отосланный ордер.

Ну так у меня внутри функции выяснятся.Зачем мне дублировать что-то? Если он принят, значит уже всё в порядке. Я так понимаю.

 
Viktar Dzemikhau:

Ну так у меня внутри функции выяснятся.Зачем мне дублировать что-то? Если он принят, значит уже всё в порядке. Я так понимаю.

***

Но сначала необходимо одно уточнение специфики работы на бирже: после сервера брокера (Broker's MT5 Server) наш торговый приказ пересылается дальше - на биржу и только после того как торговый размещён на бирже (Executed) можно уже судить об успешности выполнения торгового приказа:

Scheme of trade operations: from order creation to execution by broker


Например код открытия позиции BUY (который отлично работает на Forex), даже в случае успешного размещения торгового приказа на бирже и появлении позиции вернёт ошибку.


***

Работа на бирже и на Форекс (в части контроля открытия позиции) различаются тем, что на бирже после принятия торгового приказа сервером брокера, этот торговый приказ пересылается дальше - на биржу. И это (как указали выше) - нужно контролировать через флаги и ожидание.

 
Viktar Dzemikhau:

...

Почему в одном случае лот 0.1, а потом 0.2?

 
Dmitry Fedoseev:

Почему в одном случае лот 0.1, а потом 0.2?

Так задуано. Это не мартышка. Лоты беруться из определённого диапазона, выше которого лот не подымает. Система это самопридуманная. Я такого не встречал ни где.

 
Vladimir Karputov:

***

Но сначала необходимо одно уточнение специфики работы на бирже: после сервера брокера (Broker's MT5 Server) наш торговый приказ пересылается дальше - на биржу и только после того как торговый размещён на бирже (Executed) можно уже судить об успешности выполнения торгового приказа:



Например код открытия позиции BUY (который отлично работает на Forex), даже в случае успешного размещения торгового приказа на бирже и появлении позиции вернёт ошибку.


***

Работа на бирже и на Форекс (в части контроля открытия позиции) различаются тем, что на бирже после принятия торгового приказа сервером брокера, этот торговый приказ пересылается дальше - на биржу. И это (как указали выше) - нужно контролировать через флаги и ожидание.

А почему об этом нигде особо не написано? Это называется нужно что бы каждый наткнулся на косяк? Ведь протестировать, если нет информации полно по этому поводу не выйдет. Если на реальную биржу (я об акцияю пишу) пойти торговать, придётся заливать деньги тестируя, пусть даже прибыльный алгоритм.

 
Viktar Dzemikhau:

Так задуано. Это не мартышка. Лоты беруться из определённого диапазона, выше которого лот не подымает. Система это самопридуманная. Я такого не встречал ни где.

Если второй ордер, это ошибочное дублирование, то он должен быть полностью идентичным.

 
Viktar Dzemikhau:

А почему об этом нигде особо не написано? Это называется нужно что бы каждый наткнулся на косяк? Ведь протестировать, если нет информации полно по этому поводу не выйдет. Если на реальную биржу (я об акцияю пишу) пойти торговать, придётся заливать деньги тестируя, пусть даже прибыльный алгоритм.

Это касается торговых запросов, то есть ордеров. У вас же данные о сделке. В справке есть куча констант касающихся исполнения ордеров - исходя из их наличия и количества, можно понять-что все на так просто (хотя бы догадаться). Что касается сделок - она либо есть либо нет. Если сообщение о сделке есть, а фактически ее нет, а способа узнать об этом нет, то практически всей этой системой пользоваться невозможно, поэтому - такого быть не может. Просто есть такая категория людей - любят давать советы не вникая в проблему.

 
Dmitry Fedoseev:

Если второй ордер, это ошибочное дублирование, то он должен быть полностью идентичным.

На сей раз оказалось, что я не прав. Вопрос снят. Логика в одном моменте нарушена была и у меня заклинило и в коде и в голове от размышлений. По поводу, выполнености аявки я полностью согласен. Я всегда проверяю, если сервер вернул TRADE_RETCODE_DONE значит всё чётко. Если нет, возможен косяк.

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

Причина обращения: