Подозрение: неправильная работа функции CPositionInfo:Volume!

 

Неоднократно было замечено, что в тестере стратегий функция CPositionInfo:Volume выдает старые значения объема совокупной позиции. Эта ошибка проявляет себя редко, но является критической.

Вот лог советника в тестере стратегий (читаем с низу вверх):

...

2010.09.06 16:36:34 Core 1 2010.01.20 02:18:20 Current lot: 1.1 Limit lot: 14.7 position volume: 0.3
2010.09.06 16:36:34 Core 1 2010.01.20 02:18:19 Order 5 has been remote successfully
2010.09.06 16:36:34 Core 1 2010.01.20 02:18:16 order performed sell 0.30 at 1.42348 [#7 sell 0.30 EURUSD at 1.42348]
2010.09.06 16:36:34 Core 1 2010.01.20 02:18:16 deal performed [#7 sell 0.30 EURUSD at 1.42348]
2010.09.06 16:36:34 Core 1 2010.01.20 02:18:16 deal #7 sell 0.30 EURUSD at 1.42348 done (based on order #7)
2010.09.06 16:36:34 Core 1 2010.01.20 02:18:16 instant sell 0.30 EURUSD at 1.42348 (1.42348 / 1.42366 / 1.42348)
2010.09.06 16:36:34 Core 1 2010.01.20 00:02:03 Order 3 has been remote successfully
2010.09.06 16:36:34 Core 1 2010.01.20 00:02:00 order performed buy 3.40 at 1.42849 [#6 buy 3.40 EURUSD at 1.42849]
2010.09.06 16:36:34 Core 1 2010.01.20 00:02:00 deal performed [#6 buy 3.40 EURUSD at 1.42849]
2010.09.06 16:36:34 Core 1 2010.01.20 00:02:00 deal #6 buy 3.40 EURUSD at 1.42849 done (based on order #6)
2010.09.06 16:36:34 Core 1 2010.01.20 00:02:00 instant buy 3.40 EURUSD at 1.42849 (1.42833 / 1.42849 / 1.42833)
2010.09.06 16:36:34 Core 1 2010.01.19 17:37:04 Order 5 has been add successfully
2010.09.06 16:36:34 Core 1 2010.01.19 17:37:01 order performed buy 0.30 at 1.42562 [#5 buy 0.30 EURUSD at 1.42562]
2010.09.06 16:36:34 Core 1 2010.01.19 17:37:01 deal performed [#5 buy 0.30 EURUSD at 1.42562]
2010.09.06 16:36:34 Core 1 2010.01.19 17:37:01 deal #5 buy 0.30 EURUSD at 1.42562 done (based on order #5)
2010.09.06 16:36:33 Core 1 2010.01.19 17:37:01 instant buy 0.30 EURUSD at 1.42562 (1.42548 / 1.42562 / 1.42548)
2010.09.06 16:36:33 Core 1 2010.01.19 17:36:38 Order 2 has been remote successfully
2010.09.06 16:36:33 Core 1 2010.01.19 17:36:35 order performed sell 0.30 at 1.42537 [#4 sell 0.30 EURUSD at 1.42537]
2010.09.06 16:36:33 Core 1 2010.01.19 17:36:35 deal performed [#4 sell 0.30 EURUSD at 1.42537]
2010.09.06 16:36:33 Core 1 2010.01.19 17:36:35 deal #4 sell 0.30 EURUSD at 1.42537 done (based on order #4)
2010.09.06 16:36:33 Core 1 2010.01.19 17:36:35 instant sell 0.30 EURUSD at 1.42537 (1.42537 / 1.42551 / 1.42537)
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:38 Order 3 has been add successfully
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:35 order performed sell 3.40 at 1.43068 [#3 sell 3.40 EURUSD at 1.43068]
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:35 deal performed [#3 sell 3.40 EURUSD at 1.43068]
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:35 deal #3 sell 3.40 EURUSD at 1.43068 done (based on order #3)
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:35 instant sell 3.40 EURUSD at 1.43068 (1.43068 / 1.43080 / 1.43068)
2010.09.06 16:36:33 Core 1 2010.01.19 12:00:35 Current lot: 3.4 Limit lot: 15 position volume: 0.3
2010.09.06 16:36:33 Core 1 2010.01.18 01:58:16 Order 2 has been add successfully
2010.09.06 16:36:33 Core 1 2010.01.18 01:58:13 order performed buy 0.30 at 1.43364 [#2 buy 0.30 EURUSD at 1.43364]
2010.09.06 16:36:33 Core 1 2010.01.18 01:58:13 deal performed [#2 buy 0.30 EURUSD at 1.43364]
2010.09.06 16:36:33 Core 1 2010.01.18 01:58:13 deal #2 buy 0.30 EURUSD at 1.43364 done (based on order #2)
2010.09.06 16:36:32 Core 1 2010.01.18 01:58:13 instant buy 0.30 EURUSD at 1.43364 (1.43348 / 1.43364 / 1.43348)
2010.09.06 16:36:32 Core 1 2010.01.18 00:00:03 2 models have been created.

 Попробуем построить действия советника в хронологическом порядке:

  • BUY 0.3              +0.3
  • SELL 3.4             -3.1
  • SELL 0.3             -3.4
  • BUY 0.3              -3.1
  • BUY 3.4              +0.3
  • SELL 0.3              0.0

Как видно, итоговая позиция должна быть нетральная. Однако функция CPositionInfo:Volume возвращает неверное значение 0.3!!!

 

Делаете ли Вы предварительно вызов CPositionInfo::Select(const string symbol)? Имейте ввиду примечание для функции PositionSelect:

Функция PositionSelect() копирует данные о позиции в программное окружение, и последующие вызовы PositionGetDouble(), PositionGetInteger() и PositionGetString() возвращают ранее скопированные данные. Это означает, что самой позиции может уже и не быть (или же она изменилась по объему, направлению и т.д.), а данные этой позиции можно еще получать. Для гарантированного получения свежих данных о позиции рекомендуется вызывать функцию PositionSelect() непосредственно перед обращением за ними.


 
Rosh:

Делаете ли Вы предварительно вызов CPositionInfo::Select(const string symbol)? Имейте ввиду примечание для функции PositionSelect:

В том-то и дело, что именно так и делаю. Вот полная функция:

double mm::CheckLot(string symbol, double lot, ENUM_ORDER_TYPE op_type)
{
   ENUM_POSITION_TYPE position_type;
   double             position_volume;
   double             position_limit;
   double             lot_limit;
   m_position_info.Select(symbol);
   position_type=(ENUM_POSITION_TYPE)m_position_info.Type();
   position_volume=m_position_info.Volume();
   position_limit=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
   //if(m_position_info.Identifier()==0)position_volume=0.0;
   if(position_type==POSITION_TYPE_BUY){
      if(op_type==ORDER_TYPE_BUY)
         lot_limit=position_limit-position_volume;
      if(op_type==ORDER_TYPE_SELL)
         lot_limit=position_limit;
   }
   if(position_type==POSITION_TYPE_SELL){
      if(op_type==ORDER_TYPE_SELL)
         lot_limit=position_limit-position_volume;
      if(op_type==ORDER_TYPE_BUY)
         lot_limit=position_limit;
   }
   if(lot_limit<=0.0){
      Print("The Volume  limit is settled. Skip a signal:(");
      return(EMPTY_VALUE);
   }
   Print("Current lot: ", NormalizeDouble(lot,1), " Limit lot: ", lot_limit, " position volume: ", position_volume);
   if(lot>lot_limit)lot=lot_limit;
   return(lot);
}

 

 
C-4:

В том-то и дело, что именно так и делаю. Вот полная функция:

 

А может так?

   if (m_position_info.Select(symbol))
      position_volume=m_position_info.Volume();
 
Rosh:

А может так?

Ваш вариант заработал. Видимо, если позиции на текущий момент нет, то m_position_info.Select() не обновляет данные по объему позиции. Соответственно функция m_position_info.Volume() возвращает предыдущее значение объема. По логике, вызов m_position_info.Select(symbol) должен гарантированно обновлять самые последние данные по объему, не зависимо от того, удалось ли выделить позицию (если она есть Select()=true) или нет (позиция отсутствует Select()=false).
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций - Документация по MQL5
Причина обращения: