Как мониторить факт срабатывания отложенного ордера? - страница 4

 
fxsaber:

Если ордер исполнился частично, то его не будет в Истории до тех пор, пока он не исполнится полностью (но здесь делать FILLED-проверку делать бессмыленно), либо будет отменен (но здесь и STATE станет Cancelled, т.е. опять же FILLED-проверка не актуальна).

Согласен. Я это обдумывал. Нужно контролировать эту ситуацию. Я даже написал уже себе заготовку для этого. Но, по скольку не нужно было ещё это и не как проверить пока что забил т.к. и без этого полно дел.
 

Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:

    if (transaction.type == TRADE_TRANSACTION_DEAL_ADD) {
      Print("transaction.order = ", transaction.order);
      Print("historyType = ", EnumToString(selectedHistoryOrderType(transaction.order)));
      HistoryOrderSelect(transaction.order);
      if (selectedHistoryOrderState(transaction.order) == ORDER_STATE_FILLED)
        if (request.type == ORDER_TYPE_BUY) {
          if (!putOrder(ORDER_TYPE_SELL, g_price1, g_price2))
            return;
      } else if (request.type == ORDER_TYPE_SELL) {
        if (!putOrder(ORDER_TYPE_BUY_STOP, g_price1, g_price2))
          return;
      }
    }

Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:

2018.08.07 01:34:08.373 2016.01.04 03:19:40   transaction.order = 3
2018.08.07 01:34:08.373 2016.01.04 03:19:40   historyType = ORDER_TYPE_BUY

Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?

 
Viktar Dzemikhau:

Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:

Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:

Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?

Пример: EES Hedger.

Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
//--- get transaction type as enumeration value 
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      long     deal_ticket       =0;
      long     deal_order        =0;
      long     deal_time         =0;
      long     deal_time_msc     =0;
      long     deal_type         =-1;
      long     deal_entry        =-1;
      long     deal_magic        =0;
      long     deal_reason       =-1;
      long     deal_position_id  =0;
      double   deal_volume       =0.0;
      double   deal_price        =0.0;
      double   deal_commission   =0.0;
      double   deal_swap         =0.0;
      double   deal_profit       =0.0;
      string   deal_symbol       ="";
      string   deal_comment      ="";
      string   deal_external_id  ="";
      if(HistoryDealSelect(trans.deal))
        {
         deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
         deal_order        =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
         deal_time         =HistoryDealGetInteger(trans.deal,DEAL_TIME);
         deal_time_msc     =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
         deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
         deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
         deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
         deal_reason       =HistoryDealGetInteger(trans.deal,DEAL_REASON);
         deal_position_id  =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);

         deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
         deal_price        =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
         deal_commission   =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
         deal_swap         =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
         deal_profit       =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);

         deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
         deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);
         deal_external_id  =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
        }
      else
         return;
      if(deal_symbol==m_symbol.Name() && deal_magic==Original_EA_Magic)
         if(deal_entry==DEAL_ENTRY_IN)
            if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
              {
               if(deal_type==DEAL_TYPE_BUY) // buy
                 {
                  double sl=(InpStopLoss==0)?0.0:m_symbol.Bid()+ExtStopLoss;
                  double tp=(InpTakeProfit==0)?0.0:m_symbol.Bid()-ExtTakeProfit;
                  OpenSell(sl,tp);
                 }
               if(deal_type==DEAL_TYPE_SELL) // sell
                 {
                  double sl=(InpStopLoss==0)?0.0:m_symbol.Ask()-ExtStopLoss;
                  double tp=(InpTakeProfit==0)?0.0:m_symbol.Ask()+ExtTakeProfit;
                  OpenBuy(sl,tp);
                 }
              }
     }
  }
 
Vladimir Karputov:

Пример: EES Hedger.

Ловим транзакцию TRADE_TRANSACTION_DEAL_ADD, если сделка по текущему символу и magic равен Original_EA_Magic (если задать его в ноль, то будут отлавливаться только сделки произошедшие от ручной установки отложенных ордеров или от ручной отсылки торговых приказов по-рынку), если тип сделки DEAL_ENTRY_IN (вход в рынок) то открываемся в противоположную сторону.

Здесь есть стрёмный момент, на первый взгляд:

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
//--- get transaction type as enumeration value 
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      long     deal_ticket       =0;
      long     deal_order        =0;
      long     deal_time         =0;
      long     deal_time_msc     =0;
      long     deal_type         =-1;
      long     deal_entry        =-1;
      long     deal_magic        =0;
      long     deal_reason       =-1;
      long     deal_position_id  =0;
      double   deal_volume       =0.0;
      double   deal_price        =0.0;
      double   deal_commission   =0.0;
      double   deal_swap         =0.0;
      double   deal_profit       =0.0;
      string   deal_symbol       ="";
      string   deal_comment      ="";
      string   deal_external_id  ="";
      if(HistoryDealSelect(trans.deal))
        {
         deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
         deal_order        =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
         deal_time         =HistoryDealGetInteger(trans.deal,DEAL_TIME);
         deal_time_msc     =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
         deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
         deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
         deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
         deal_reason       =HistoryDealGetInteger(trans.deal,DEAL_REASON);
         deal_position_id  =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);

         deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
         deal_price        =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
         deal_commission   =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
         deal_swap         =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
         deal_profit       =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);

         deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
         deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);
         deal_external_id  =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
        }
      else
         return;
      if(deal_symbol==m_symbol.Name() && deal_magic==Original_EA_Magic)
         if(deal_entry==DEAL_ENTRY_IN)
            if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
              {
               if(deal_type==DEAL_TYPE_BUY) // buy
                 {
                  double sl=(InpStopLoss==0)?0.0:m_symbol.Bid()+ExtStopLoss;
                  double tp=(InpTakeProfit==0)?0.0:m_symbol.Bid()-ExtTakeProfit;
                  OpenSell(sl,tp);
                 }
               if(deal_type==DEAL_TYPE_SELL) // sell
                 {
                  double sl=(InpStopLoss==0)?0.0:m_symbol.Ask()-ExtStopLoss;
                  double tp=(InpTakeProfit==0)?0.0:m_symbol.Ask()+ExtTakeProfit;
                  OpenBuy(sl,tp);
                 }
              }
     }
  }

Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.

 
Viktar Dzemikhau:

Здесь есть стрёмный момент, на первый взгляд:

Блок, где происходит инициализация дефолтными значениями свойств сделки.. Зачем? Нам же нужно получить значения совершённой транзакции.. Они придут какие и есть, на самом деле. К чему нам их обнуление. Ведь значения этих свойств зависят от сервера.. т.е. как он их отработает и вернёт терминалу.

Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки. 

Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.

 
Viktar Dzemikhau:

Что-то не работает вообще это всё. Например, имеется несколько ордеров и позиций в рынке, как рынояные так и отложенные buyStop и sellStop. Срабатывает sellStop. В этот момент я хочу открыть противовес. Код такой:

Хотя, срабатывает sellStop, но я попадаю в условие типа сработал buyStop. Это как вообще такое может быть? У меня при тесте нет рыночной позиции buy. Но в журнале вижу:

Как мне тогда сделать так, что бы если ордер перешёл в состояние позиции.. выполнить какое-то действие?

Здесь есть код на эту тему.

 
Vladimir Karputov:

Это привычка: всегда всё инициализировать. И только потом уже работать. Те кто работает надеясь на авось и не инициализируют - потом часто попадают на трудно вылавливаемые ошибки. 

Для примера: Структура торговой транзакции - обратите внимание, что каждый вид транзакции заполняет только НЕКОТОРЫЕ поля, в остальных может быть что угодно.

Да. Но это нужно проверять на реале. Потому что никаких данных нет в справке. Там вообще как-то всё убого. Многие вещи сам проверяю. Просто, если понятие ордера и позиции у меня уже пару лет как сложилось, то со сделками только вот пару дней назад как столкнулся. Потому что раньше не нужно было.

Я обычно тоже всё инициализирую, но это локальные вещи, а когда приходят данные из вне, здесь вопрос.. Нужно на реале будет прогнать и поглядеть. Я сторонник минимализма. Если столкнулся с чем-то, тогда включаю в код. А так можно было бы весь спектр ошибок обрабатывать, например. Но это заколебёшся проверять всё. Я об этом тоже думал. Пришёл к выводу, что нужно самые очевидные моменты анализировать. На данный момент, всё и так чётко, кроме кк вот этот аспект со сделками ещё разрулить. Уже работает, но хочу всё это хозяйство запаковать в библиотеку и разгруппировать. Потому что такие пачки кода повторяющиеся это не есть желаемый вариант. Да и у меня в прошлом варианте, всё было правильно, кроме как я выбирал не сделку, а ордер:

    if (transaction.type == TRADE_TRANSACTION_DEAL_ADD) {
      if (request.action == TRADE_ACTION_DEAL)

      if (!HistoryDealSelect(transaction.deal))    // Здесь был выбор ордера из истории
        return;
      if (selectedDealDirection(transaction.deal) == DEAL_ENTRY_IN) {
        if (selectedDealType(transaction.deal) == DEAL_TYPE_BUY) {
          if (!putOrder(ORDER_TYPE_SELL, g_price1, g_price2)) {
            return;
          }
        } else if (selectedDealType(transaction.deal) == DEAL_TYPE_SELL) {
           if (!putOrder(ORDER_TYPE_BUY_STOP, g_price2, g_price1)) {
            return;
          }
        }
      }
    }

Только вот всё-равно, здесь ещё 1 косяк есть очевидный. В наших обоих вариантах есть недочёт. Если ордер не открылся, то он пропариться и больше не откроется. Здесь придётся флаг заводить, на вскидку. А так всё остальное верно.

 

Viktar Dzemikhau

Вы всё очень усложняете.

Всё очень просто

1. Ордер

Если Вы отправили ордер, то

а) Ордер исполнился полностью

б) Ордер исполнился частично

в) Ордер отклонен

г) Ордер поставлен в очередь

2. Позиция

а) Есть позиция

б) Нет позиции

Коль скоро ордер первичен в торговле, то после оправки ордера

необходимо знать, что с ним произошло (OnTradeTransaction()) в помощь

Если ордер исполнялся, то PositionSelect(symbol) даст всю необходимую инфориацию о позиции.

Вот функция, которая даст всю необходимую инфу об ордере.

#define ERR_ZERO_TICKET -111
enum ENUM_ORD_REAL_STATE
{
  ORDER_NOT_SPECIFIED         = 0, //Состояние ордера не определено
  ORDER_NONE_CANCELED         = 1, //Ордера нет, отменён пользователем
  ORDER_NONE_PARTIAL_CANCELED = 2, //Ордера нет, исполнился частично (не был залит вторым объёмом)
  ORDER_NONE_PARTIAL          = 3, //Ордера нет, исполнился частично
  ORDER_NONE_EXPIRED          = 4, //Ордера нет, удалён по сроку
  ORDER_NONE_FILLED           = 5, //Ордера нет, исполнился полностью
  ORDER_NONE_REJECTED         = 6, //Ордера нет, отклонён брокером(биржей)
  ORDER_BUSY                  = 7, //Ордер находится в переходном состоянии
  ORDER_EXIST                 = 8, //Ордер выставлен на биржу, возможны действия над ним
  ORDER_EXIST_PARTIAL         = 9  //Ордер выставлен на биржу, частично исполнился, возможны действия над ним
};
//---
enum ENUM_ORD_SELECT
{
  SELECT_ERROR = 0,
  SELECT_FALSE = 1,
  SELECT_TRUE  = 2,
  SELECT_BUSY  = 3
};
//---
struct ORDER_DATA
{
  int                     error_code;
  ulong                   ticket;
  datetime                time_setup;
  ENUM_ORDER_TYPE         type;
  ENUM_ORDER_STATE        state;
  ENUM_ORD_REAL_STATE     real_state;
  datetime                expiration;
  datetime                time_done;
  long                    t_set_msc;
  long                    t_done_msc; 
  ENUM_ORDER_TYPE_FILLING type_filling;
  ENUM_ORDER_TYPE_TIME    type_time;
  long                    magic;
  ENUM_ORDER_REASON       reason;
  long                    pos_id;
  long                    pos_by_id;
  double                  vol_init;
  double                  vol_cur;
  double                  price_open;
  double                  sl;
  double                  tp;
  double                  price_cur;
  double                  price_stlim;
  string                  symbol;
  string                  comment;
  string                  ext_id;       
};
//+------------------------------------------------------------------+
// Expert Order Real Select function                                 |
//+------------------------------------------------------------------+
ENUM_ORD_SELECT OrderRealSelect(const ulong ticket, ORDER_DATA &ord_data, const bool get_data)
{
  double init_vol = 0;
  double cur_vol = 0;
  ZeroMemory(ord_data);
  ord_data.real_state = ORDER_NOT_SPECIFIED;
  ord_data.error_code = ERR_SUCCESS;
  ResetLastError();
  if(ticket > 0)
  {
    if(HistoryOrderSelect(ticket))
    {
      if(get_data)
      {
        ord_data.comment = HistoryOrderGetString(ticket, ORDER_COMMENT);
        ord_data.expiration = datetime( HistoryOrderGetInteger(ticket, ORDER_TIME_EXPIRATION)); 
        ord_data.magic = HistoryOrderGetInteger(ticket, ORDER_MAGIC);
        ord_data.pos_id = HistoryOrderGetInteger(ticket, ORDER_POSITION_ID);
        ord_data.price_cur = HistoryOrderGetDouble(ticket, ORDER_PRICE_CURRENT);
        ord_data.price_open = HistoryOrderGetDouble(ticket, ORDER_PRICE_OPEN);
        ord_data.price_stlim = HistoryOrderGetDouble(ticket, ORDER_PRICE_STOPLIMIT);
        ord_data.sl = HistoryOrderGetDouble(ticket, ORDER_SL);
        ord_data.state = ENUM_ORDER_STATE( HistoryOrderGetInteger(ticket, ORDER_STATE));
        ord_data.symbol = HistoryOrderGetString(ticket, ORDER_SYMBOL);
        ord_data.t_done_msc = datetime(HistoryOrderGetInteger(ticket, ORDER_TIME_DONE_MSC));
        ord_data.t_set_msc = datetime(HistoryOrderGetInteger(ticket, ORDER_TIME_SETUP_MSC));
        ord_data.time_done = datetime(HistoryOrderGetInteger(ticket, ORDER_TIME_DONE));
        ord_data.time_setup = datetime(HistoryOrderGetInteger(ticket, ORDER_TIME_SETUP));
        ord_data.tp = HistoryOrderGetDouble(ticket, ORDER_TP);
        ord_data.type = ENUM_ORDER_TYPE( HistoryOrderGetInteger(ticket, ORDER_TYPE));
        ord_data.type_filling = ENUM_ORDER_TYPE_FILLING( HistoryOrderGetInteger(ticket, ORDER_TYPE_FILLING));
        ord_data.type_time = ENUM_ORDER_TYPE_TIME( HistoryOrderGetInteger(ticket, ORDER_TYPE_TIME));
        ord_data.vol_cur = HistoryOrderGetDouble(ticket, ORDER_VOLUME_CURRENT);
        ord_data.vol_init = HistoryOrderGetDouble(ticket, ORDER_VOLUME_INITIAL);
        ord_data.ext_id = HistoryOrderGetString(ticket, ORDER_EXTERNAL_ID);
        ord_data.reason = ENUM_ORDER_REASON(HistoryOrderGetInteger(ticket, ORDER_REASON));
      }
      else
      {
        ord_data.state = ENUM_ORDER_STATE(HistoryOrderGetInteger(ticket, ORDER_STATE));
        cur_vol = HistoryOrderGetDouble(ticket, ORDER_VOLUME_CURRENT);
        init_vol = HistoryOrderGetDouble(ticket, ORDER_VOLUME_INITIAL);
      }   
//---
      switch(ord_data.state)
      { 
        case ORDER_STATE_CANCELED:
          if(get_data)
          {
            if(ord_data.vol_init == ord_data.vol_cur)
            {
              ord_data.real_state = ORDER_NONE_CANCELED;
            }
            else
            {
              ord_data.real_state = ORDER_NONE_PARTIAL_CANCELED;
            }
          }
          else
          {
            if(init_vol == cur_vol)
            {
              ord_data.real_state = ORDER_NONE_CANCELED;
            }
            else
            {
              ord_data.real_state = ORDER_NONE_PARTIAL_CANCELED;
            }
          }    
        break;
         
        case ORDER_STATE_PARTIAL:
          ord_data.real_state = ORDER_NONE_PARTIAL;
        break;
                                         
        case ORDER_STATE_EXPIRED:
          ord_data.real_state = ORDER_NONE_EXPIRED;
        break;
                                                                              
        case ORDER_STATE_FILLED:
          ord_data.real_state = ORDER_NONE_FILLED;
        break;
                                         
        case ORDER_STATE_REJECTED:
          ord_data.real_state = ORDER_NONE_REJECTED;
        break;  
      }
    }
    else
    if(OrderSelect(ticket))
    {
      if(get_data)
      {
        ord_data.comment = OrderGetString(ORDER_COMMENT);
        ord_data.expiration = datetime( OrderGetInteger(ORDER_TIME_EXPIRATION)); 
        ord_data.magic = OrderGetInteger(ORDER_MAGIC);
        ord_data.pos_id = OrderGetInteger(ORDER_POSITION_ID);
        ord_data.price_cur = OrderGetDouble(ORDER_PRICE_CURRENT);
        ord_data.price_open = OrderGetDouble(ORDER_PRICE_OPEN);
        ord_data.price_stlim = OrderGetDouble(ORDER_PRICE_STOPLIMIT);
        ord_data.sl = OrderGetDouble(ORDER_SL);
        ord_data.state = ENUM_ORDER_STATE(OrderGetInteger(ORDER_STATE));
        ord_data.symbol = OrderGetString(ORDER_SYMBOL);
        ord_data.t_done_msc = datetime(OrderGetInteger(ORDER_TIME_DONE_MSC));
        ord_data.t_set_msc = datetime(OrderGetInteger(ORDER_TIME_SETUP_MSC));
        ord_data.time_done = datetime(OrderGetInteger(ORDER_TIME_DONE));
        ord_data.time_setup = datetime(OrderGetInteger(ORDER_TIME_SETUP));
        ord_data.tp = OrderGetDouble(ORDER_TP);
        ord_data.type = ENUM_ORDER_TYPE( OrderGetInteger(ORDER_TYPE));
        ord_data.type_filling = ENUM_ORDER_TYPE_FILLING(OrderGetInteger(ORDER_TYPE_FILLING));
        ord_data.type_time = ENUM_ORDER_TYPE_TIME(OrderGetInteger(ORDER_TYPE_TIME));
        ord_data.vol_cur = OrderGetDouble(ORDER_VOLUME_CURRENT);
        ord_data.vol_init = OrderGetDouble(ORDER_VOLUME_INITIAL);
        ord_data.ext_id = OrderGetString(ORDER_EXTERNAL_ID);
        ord_data.reason = ENUM_ORDER_REASON(OrderGetInteger(ORDER_REASON));
      }
      else ord_data.state = ENUM_ORDER_STATE(OrderGetInteger(ORDER_STATE));
      switch(ord_data.state)
      { 
        case ORDER_STATE_STARTED:
        case ORDER_STATE_REQUEST_ADD:
        case ORDER_STATE_REQUEST_MODIFY:
        case ORDER_STATE_REQUEST_CANCEL:
          ord_data.real_state = ORDER_BUSY;
        break; 
        case ORDER_STATE_PARTIAL:
          ord_data.real_state = ORDER_EXIST_PARTIAL;
        break;
        case ORDER_STATE_PLACED:
          ord_data.real_state = ORDER_EXIST;
        break;
      }
    }
    else ord_data.error_code = GetLastError();
    if((ord_data.error_code != ERR_SUCCESS) ||
       (ord_data.real_state == ORDER_NOT_SPECIFIED))
    {
      return(SELECT_ERROR);
    }
    else
    {
      switch(ord_data.real_state)
      {
        case ORDER_BUSY:
          return(SELECT_BUSY);
        break;
        case ORDER_EXIST:   
        case ORDER_EXIST_PARTIAL:
          return(SELECT_TRUE);
        break;
        default:   
          return(SELECT_FALSE);
        break;                                             
      }
    }
  } 
  else
  {
    ord_data.error_code = ERR_ZERO_TICKET; 
    return(SELECT_ERROR);
  }
}
 

prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.

А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.
 
Viktar Dzemikhau:

prostotrader, да я и не спорю даже. У меня такое иногда бывает. Всегда продумываю всё наперёд. Это не просто. Привычка к оптимизации кода.

А Вашу инфу ещё нужно переварить для начала. Но вижу, что enum'ы можно было взять дефолтные, по идее. А так логика в общем ясно. Хотя, параметр get_data не особо я ещё понял для чего.

get_data == true - даёт возможность получить абсолютно всю информацию об ордере.

Если get_data == false, то только состояние ордера и его наличие.

Добавлено

В том - то и дело, что дефолтные enum'ы не дают полной картины состояния ордера, в тот момент, когда приходит сообщение в OnTradeTransaction()

Посмотрите, как получаются ORDER_NONE_PARTIAL_CANCELED и ORDER_NONE_PARTIAL, предварительно прочитав комментарий к enum'у

Не так всё просто, как кажется на первый взгляд.

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