"Плавающая" ошибка PositionSelect()

 

Привет!

Ситуация следующая МТ5, билд 1375

Робот, в своей работе, при торговле фьючерсами, использует фунцию OrderSendAsync()

Допустим, что есть открытая позиция объёмом 2 контракта.

Посылается ордер на частичное закрытие позиции (объём 1), получая ответ от сервера

в функции OnTradeTransaction(), проверяется позиция PositionSelect(Symbol()) и берутся данные

о позиции. Так вот, достаточно часто, при исполнении ордера о частичном закрытии

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

позиция не изменена (объём остаётся равнм 2).

Как построить логирование, чтобы показать разработчикам наличие ошибки? 

 

Стесняюсь спросить, а откуда такая уверенность, что ошибка есть? Или Вы полагаете, что разработчики такие дремучие как таёжный лес? ;-)

Читайте матчасть про асинхронные операции.

 
Dennis Kirichenko:

Стесняюсь спросить, а откуда такая уверенность, что ошибка есть? Или Вы полагаете, что разработчики такие дремучие как таёжный лес? ;-)

Читайте матчасть про асинхронные операции.

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

Я спросил как построить доказательую базу для разработчикав, а не как пользоваться

ассинхронной функцией! 

В педыдущих билдах (до хеджирования) этой ошибки небыло. 

 

Написал тестового эксперта

//+------------------------------------------------------------------+
//|                                               Test_Pos_selct.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
input uint TrCount=50; //Кол-во транзакций
uint tr_cnt;
ulong order_ticket;
ulong request_id;
ulong Magic=1234567890;
#define ERR_ZERO_TICKET -11;
bool exp_busy;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_ORD_SELECT
  {
   SELECT_ERROR = 0,
   SELECT_FALSE = 1,
   SELECT_TRUE  = 2,
   SELECT_BUSY  = 3
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_ORD_REAL_STATE
  {
   ORD_NOT_SPECIFIED         = 0, //Состояние ордера не определено
   ORD_NONE_CANCELED         = 1, //Ордера нет, отменён пользователем
   ORD_NONE_PARTIAL_CANCELED = 2, //Ордера нет, исполнился частично (не был залит вторым объёмом)
   ORD_NONE_PARTIAL          = 3, //Ордера нет, исполнился частично
   ORD_NONE_EXPIRED          = 4, //Ордера нет, удалён по сроку
   ORD_NONE_FILLED           = 5, //Ордера нет, исполнился полностью
   ORD_NONE_REJECTED         = 6, //Ордера нет, отклонён брокером(биржей)
   ORD_BUSY                  = 7, //Ордер находится в переходном состоянии
   ORD_EXIST                 = 8, //Ордер выставлен на биржу, возможны действия над ним
   ORD_EXIST_PARTIAL         = 9  //Ордер выставлен на биржу, частично исполнился, возможны действия над ним
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct ORDER_DATA
  {
   int               error_code;
   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;
   long              pos_id;
   double            vol_init;
   double            vol_cur;
   double            price_open;
   double            sl;
   double            tp;
   double            price_cur;
   double            price_stlim;
   string            symbol;
   string            comment;
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   Print(__FUNCTION__, ": Start testing: ",TimeTradeServer());
   tr_cnt=0;
   order_ticket=0;
   request_id=0;
   exp_busy=false;
   if(!MarketBookAdd(Symbol())){return(INIT_FAILED);}
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   MarketBookRelease(Symbol());
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   bool is_select=false;
   ENUM_POSITION_TYPE pos_type=NULL;
   long volume=0;
   switch(trans.type)
     {
      case TRADE_TRANSACTION_REQUEST: if((request_id!=0) && (result.request_id==request_id))
        {
         order_ticket=result.order;
         request_id=0;
         Print(__FUNCTION__, ": Order resived #", result.order);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD: if((order_ticket!=0) && (trans.order==order_ticket))
        {
         Print(__FUNCTION__, ": Order #", order_ticket, " add to history."); 
         ORDER_DATA order_data;
         ENUM_ORD_SELECT order_select=OrderRealSelect(order_ticket,order_data,false);
         switch(order_select)
         {
          case SELECT_TRUE: if(PositionSelect(Symbol()))
          {
            pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            volume=(long)PositionGetDouble(POSITION_VOLUME);
            is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");                    
          break;
          case SELECT_FALSE: if(PositionSelect(Symbol()))
          {
           pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
           volume=(long)PositionGetDouble(POSITION_VOLUME);
           is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");
          break;
         }
         if(is_select)
          {
           Print(__FUNCTION__, ": Position exists");
           Print(__FUNCTION__, ": Position type: ", EnumToString(pos_type));
           Print(__FUNCTION__, ": Position volume: ", volume);
          }
          tr_cnt++;
          exp_busy=false; 
        }
      break;
     }
  }
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
//---
   if(symbol==Symbol()&&(!exp_busy))
     {
      if(tr_cnt>=TrCount)
        {
         if(PositionSelect(Symbol()))
           {
            order_ticket=0;
            ENUM_POSITION_TYPE pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            long vol=(long)PositionGetDouble(POSITION_VOLUME);
            ClosePosition(pos_type,vol);
            Print(__FUNCTION__, ": End testing: ",TimeTradeServer());
            if(order_ticket>0) ExpertRemove();
           }
         else
           {
            Print(__FUNCTION__, ": End testing: ",TimeTradeServer());
            ExpertRemove();
           }
        }
      else
        {
         if(PositionSelect(Symbol()))
           {
            ENUM_POSITION_TYPE pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            long vol=(long)PositionGetDouble(POSITION_VOLUME);
            Print(__FUNCTION__, ": Position exists");
            Print(__FUNCTION__, ": Position type: ", EnumToString(pos_type));
            Print(__FUNCTION__, ": Position volume: ", vol);
            switch(int(vol))
            {
              case 1: ClosePosition(pos_type,vol);
              break;
              default: PartClosePos(pos_type);
              break;
            } 
           }
           else
           {
             Print(__FUNCTION__, ": Try open position...");
             OpenPosition();
           }
        }
     }   
  }
//
void ClosePosition(ENUM_POSITION_TYPE p_type,const long volume)
  {
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};
   switch(p_type)
     {
      case POSITION_TYPE_BUY: request.type=ORDER_TYPE_SELL;
      break;
      case POSITION_TYPE_SELL: request.type=ORDER_TYPE_BUY;
      break;
     }
   order_ticket=0;
   request.magic=Magic;
   request.symbol=Symbol();
   request.volume=(double)volume;
   request.type_filling=ORDER_FILLING_IOC;
   request.type_time=ORDER_TIME_DAY;
   request.action=TRADE_ACTION_DEAL;
   request.comment="";
   request.price=0;
   if(OrderSend(request,result))
     {
      if(result.retcode==TRADE_RETCODE_PLACED)
        {
         //order_ticket=result.order;
         exp_busy=false;
         tr_cnt++;
         Print(__FUNCTION__, ": Position slosed.");
        }
     }
   else
     {Print(__FUNCTION__, ": Order not sent for close position!");}
  }
//+------------------------------------------------------------------+  
void PartClosePos(ENUM_POSITION_TYPE p_type)
  {
    MqlTradeRequest request={0};
    MqlTradeResult  result={0};
    switch(p_type)
     {
      case POSITION_TYPE_BUY: request.type=ORDER_TYPE_SELL;
      break;
      case POSITION_TYPE_SELL: request.type=ORDER_TYPE_BUY;
      break;
     }
   order_ticket=0;
   request.magic=Magic;
   request.symbol=Symbol();
   request.volume=1;
   request.type_filling=ORDER_FILLING_IOC;
   request.type_time=ORDER_TIME_DAY;
   request.action=TRADE_ACTION_DEAL;
   request.comment="";
   request.price=0;
   if(OrderSend(request,result))
     {
      if(result.retcode==TRADE_RETCODE_PLACED)
        {
         order_ticket=result.order;
         exp_busy=true;
         tr_cnt++;
         Print(__FUNCTION__, ": Order sent for part close position.");
        }
     }
   else
     {Print(__FUNCTION__, ": Order not sent for part close position!");}
  }
  //+------------------------------------------------------------------+  
void OpenPosition()
  {
    MqlTradeRequest request={0};
    MqlTradeResult  result={0};
    request_id=0;
    order_ticket=0;
    request.magic=Magic;
    request.symbol=Symbol();
    request.volume=2;
    request.type_filling=ORDER_FILLING_IOC;
    request.type_time=ORDER_TIME_DAY;
    request.action=TRADE_ACTION_DEAL;
    request.comment="";
    request.price=0;
    request.type=ORDER_TYPE_BUY;
    if(OrderSendAsync(request,result))
     {
      if(result.retcode==TRADE_RETCODE_PLACED)
        {
          request_id=result.request_id;
          exp_busy=true;
          Print(__FUNCTION__, ": Order sent successfully for open position");
        }
     }
     else
     Print(__FUNCTION__, ": Order not sent for open position!");
  }
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 = ORD_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);
           }
         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=ORD_NONE_CANCELED;
                 }
               else
                 {
                  ord_data.real_state=ORD_NONE_PARTIAL_CANCELED;
                 }
              }
            else
              {
               if(init_vol==cur_vol)
                 {
                  ord_data.real_state=ORD_NONE_CANCELED;
                 }
               else
                 {
                  ord_data.real_state=ORD_NONE_PARTIAL_CANCELED;
                 }
              }
            break;

            case ORDER_STATE_PARTIAL:  ord_data.real_state=ORD_NONE_PARTIAL;
            break;

            case ORDER_STATE_EXPIRED:  ord_data.real_state=ORD_NONE_EXPIRED;
            break;

            case ORDER_STATE_FILLED:   ord_data.real_state=ORD_NONE_FILLED;
            break;

            case ORDER_STATE_REJECTED: ord_data.real_state=ORD_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);
           }
         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=ORD_BUSY;
            break;

            case ORDER_STATE_PARTIAL:        ord_data.real_state=ORD_EXIST_PARTIAL;
            break;

            case ORDER_STATE_PLACED:         ord_data.real_state=ORD_EXIST;
            break;
           }
        }
      else
        {
         ord_data.error_code=GetLastError();
        }
      //---   
      if(( ord_data.error_code!=ERR_SUCCESS) || 
         (ord_data.real_state==ORD_NOT_SPECIFIED))
        {
         return(SELECT_ERROR);
        }
      else
        {
         switch(ord_data.real_state)
           {
            case ORD_BUSY:          return(SELECT_BUSY);
            break;

            case ORD_EXIST:
            case ORD_EXIST_PARTIAL: return(SELECT_TRUE);
            break;

            default:                return(SELECT_FALSE);
            break;
           }
        }
     }
   else
     {
      ord_data.error_code=ERR_ZERO_TICKET;
      return(SELECT_ERROR);
     }
  }  
//+------------------------------------------------------------------+

 Запустил на Демо в Открытии, я считаю, что это ошибка, то что ордер уже в истории, а терминал "не знает", что

позиция открыта 2016.08.02 17:52:34.427 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position not exist.

2016.08.02 17:52:34.403 Test_Pos_selct (GAZR-9.16,M1)   OnBookEvent: Try open position...
2016.08.02 17:52:34.403 Test_Pos_selct (GAZR-9.16,M1)   OpenPosition: Order sent successfully for open position
2016.08.02 17:52:34.409 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Order resived #50224643
2016.08.02 17:52:34.427 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Order #50224643 add to history.
2016.08.02 17:52:34.427 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position not exist.
2016.08.02 17:52:34.437 Test_Pos_selct (GAZR-9.16,M1)   OnBookEvent: Position exists

 

 Полные логи прикреплены

Заявка в сервисдеск отправлена

MetaTrader 5 Platform: ошибка

Необработана, Начата: 2016.08.02 17:20, #1529580 

Файлы:
 

Неужели никто раньше не обращал внимание на этоту багу?

Расширил логирование функции OnTradeTransaction

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   bool is_select=false;
   ENUM_POSITION_TYPE pos_type=NULL;
   long volume=0;
   switch(trans.type)
     {
      case TRADE_TRANSACTION_REQUEST: if((request_id!=0) && (result.request_id==request_id))
        {
         order_ticket=result.order;
         request_id=0;
         Print(__FUNCTION__, ": Order resived #", result.order);
        }
      break;
      case TRADE_TRANSACTION_DEAL_ADD: if((order_ticket!=0) && (trans.order==order_ticket))
      {
       Print(__FUNCTION__, ": Deal, based on order #", order_ticket, " done.");
       if(PositionSelect(Symbol()))
       {
        Print(__FUNCTION__, ": Position exists.");
        pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
        volume=(long)PositionGetDouble(POSITION_VOLUME);
        Print(__FUNCTION__, ": Position type: ", EnumToString(pos_type));
        Print(__FUNCTION__, ": Position volume: ", volume);
       } 
       else
        Print(__FUNCTION__, ": Position not exist.");
      }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD: if((order_ticket!=0) && (trans.order==order_ticket))
        {
         Print(__FUNCTION__, ": Order #", order_ticket, " add to history."); 
         ORDER_DATA order_data;
         ENUM_ORD_SELECT order_select=OrderRealSelect(order_ticket,order_data,false);
         switch(order_select)
         {
          case SELECT_TRUE: if(PositionSelect(Symbol()))
          {
            pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            volume=(long)PositionGetDouble(POSITION_VOLUME);
            is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");
           Print(__FUNCTION__, ": Order #",trans.order," exists.");                    
          break;
          case SELECT_FALSE: if(PositionSelect(Symbol()))
          {
           pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
           volume=(long)PositionGetDouble(POSITION_VOLUME);
           is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");
           Print(__FUNCTION__, ": Order #",trans.order," not found.");
          break;
         }
         if(is_select)
          {
           Print(__FUNCTION__, ": Position exists");
           Print(__FUNCTION__, ": Position type: ", EnumToString(pos_type));
           Print(__FUNCTION__, ": Position volume: ", volume);
          }
          tr_cnt++;
          exp_busy=false; 
        }
      break;
     }
  }

 

Несмотря на то, что события TRADE_TRANSACTION_DEAL_ADD и TRADE_TRANSACTION_HISTORY_ADD

не имеют очерёдности, но терминал-то должен знать состоянии позиции, при любом из этих

приходящих событий, иначе получается просто лажа. Вот пример, когда событие TRADE_TRANSACTION_HISTORY_ADD

приходит первым (ордер в истории, сделка совершена, а в терминале так и "болтается" позиция с объёмом равным 2, а не 1) 

2016.08.02 19:28:02.259 Test_Pos_selct (GAZR-9.16,M1)   OnBookEvent: Position exists
2016.08.02 19:28:02.259 Test_Pos_selct (GAZR-9.16,M1)   OnBookEvent: Position type: POSITION_TYPE_BUY
2016.08.02 19:28:02.259 Test_Pos_selct (GAZR-9.16,M1)   OnBookEvent: Position volume: 2
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   PartClosePos: Order sent for part close position.
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Order #50232966 add to history.
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Order #50232966 not found.
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position exists
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position type: POSITION_TYPE_BUY
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position volume: 2
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Deal, based on order #50232966 done.
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position exists.
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position type: POSITION_TYPE_BUY
2016.08.02 19:28:02.288 Test_Pos_selct (GAZR-9.16,M1)   OnTradeTransaction: Position volume: 1
 

Из справки MQL5

Один торговый запрос, отправленный из терминала вручную или через торговые функции OrderSend()/OrderSendAsync(),
может порождать на торговом сервере несколько последовательных торговых транзакций.
При этом очередность поступления этих транзакций в терминал не гарантирована,
поэтому нельзя свой торговый алгоритм строить на ожидании поступления одних торговых транзакций после прихода других.
Кроме того, транзакции могут потеряться при доставке от сервера к терминалу.

 Всё бы ничего, если бы не последняя фраза.

Если событие TRADE_TRANSACTION_HISTORY_ADD пришло первым, а событие TRADE_TRANSACTION_DEAL_ADD

потерялось :(, то в терминале так и будут "висеть" предыдущие данные о позизиции!  

 
prostotrader:

Из справки MQL5

 Всё бы ничего, если бы не последняя фраза.

Если событие TRADE_TRANSACTION_HISTORY_ADD пришло первым, а событие TRADE_TRANSACTION_DEAL_ADD

потерялось :(, то в терминале так и будут "висеть" предыдущие данные о позизии!  

Бред. Какая связь между кэшем, где сохраняются данные о запрашиваемой позиции, и транзакциями?

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

request.type_filling=ORDER_FILLING_IOC;    // разве так?
request.type_filling=ORDER_FILLING_RETURN; // а может так?

И вообще в каких университетах так учат кодировать?

 switch(trans.type)
     {
      case TRADE_TRANSACTION_REQUEST: if((request_id!=0) && (result.request_id==request_id))
        {
         order_ticket=result.order;
         request_id=0;
         Print(__FUNCTION__, ": Order resived #", result.order);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD: if((order_ticket!=0) && (trans.order==order_ticket))
        {
         Print(__FUNCTION__, ": Order #", order_ticket, " add to history."); 
         ORDER_DATA order_data;
         ENUM_ORD_SELECT order_select=OrderRealSelect(order_ticket,order_data,false);
         switch(order_select)
         {
          case SELECT_TRUE: if(PositionSelect(Symbol()))
          {
            pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            volume=(long)PositionGetDouble(POSITION_VOLUME);
            is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");                    
          break;
          case SELECT_FALSE: if(PositionSelect(Symbol()))
          {
           pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
           volume=(long)PositionGetDouble(POSITION_VOLUME);
           is_select=true;
          }
          else
           Print(__FUNCTION__, ": Position not exist.");
          break;
         }
         if(is_select)
          {
           Print(__FUNCTION__, ": Position exists");
           Print(__FUNCTION__, ": Position type: ", EnumToString(pos_type));
           Print(__FUNCTION__, ": Position volume: ", volume);
          }
          tr_cnt++;
          exp_busy=false; 
        }
      break;
     }
 
Dennis Kirichenko:

Бред. Какая связь между кэшем, где сохраняются данные о запрашиваемой позиции, и транзакциями?

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

И вообще в каких университетах так учат кодировать?

Вы сами-то читали, что написали?

Обязательно находится "учитель", который сам ничего не умеет, но

регулярно пишет... 

Увидит знакомое слово (ORDER_FILLING_IOC) и начинает изголятся.

Для Вас, всезнайка

 ORDER_FILLING_IOC
Означает согласие совершить сделку по максимально доступному на рынке объему в пределах указанного в ордере.
В случае невозможности полного исполнения ордер будет исполнен на доступный объем, а неисполненный объем ордера будет отменен.
 
 
prostotrader:

Вы сами-то читали, что написали?

Обязательно находится "учитель", который сам ничего не умеет, но

регулярно пишет... 

Увилит знакомое слово (ORDER_FILLING_IOC) и начинает изголятся.

Нужно (только завтра) сделать два примера - синхронную отправку и асинхронную. И упростить OnTradeTransaction() - рассматривать только добавление сделки в историю - никаких ордеров, чтобы не было и близко. Но я буду делать исключительно через стандартный класс CTrade.

Кстати, на каком торговом сервере Вы экспериментируете? 

 

Просьба к "учителям" и "всезнайкам" выступать по существу,

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

 
Karputov Vladimir:

Нужно (только завтра) сделать два примера - синхронную отправку и асинхронную. И упростить OnTradeTransaction() - рассматривать только добавление сделки в историю - никаких ордеров, чтобы не было и близко. Но я буду делать исключительно через стандартный класс CTrade.

Кстати, на каком торговом сервере Вы экспериментируете? 

В сообщениях было определённо написано Демо.

А начал разбираться с этим вопросом, потому что на реале сбои пошли. 

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