CPositionInfo - информация актуальная или на момент входа в цикл?

 

Вводные параметры: есть несколько позиций, есть цикл обхода позиций.

Появились такие вопросы:

1. Все свойства позиций класса CPositionInfo, которые возвращают информацию через торговую функцию PositionGetDouble - они возвращают актуальную в данный момент информацию (читай самую свежую) или это информация на момент входа в цикл перебора позиций (читай с момента выделения позиции)? Вопрос больше вот по этим двум функциям:

PriceCurrent

Получает текущую цену по символу позиции

Profit

Получает размер текущей прибыли по позиции


//+------------------------------------------------------------------+
//| Get the property value "POSITION_PRICE_CURRENT"                  |
//+------------------------------------------------------------------+
double CPositionInfo::PriceCurrent(void) const
  {
   return(PositionGetDouble(POSITION_PRICE_CURRENT));
  }
//+------------------------------------------------------------------+
//| Get the property value "POSITION_PROFIT"                         |
//+------------------------------------------------------------------+
double CPositionInfo::Profit(void) const
  {
   return(PositionGetDouble(POSITION_PROFIT));
  }
2. ...
 
PositionGet возвращает всегда инфу на момент последнего вызова одной из четырех функций
PositionSelectByTicket
PositionGetSymbol
PositionSelect
PositionGetTicket

Это значит, что позиции может уже давно не существовать, а PositionGet будет хранить старую инфу.


Есть read-only внутренняя Position-структура, чтение полей которой происходит через штатные PositionGet-функции. Наверное, удобно было бы иметь _Position, по аналогии с _Symbol, _LastError и т.д.

 
Vladimir Karputov:

Вводные параметры: есть несколько позиций, есть цикл обхода позиций.

Появились такие вопросы:

1. Все свойства позиций класса CPositionInfo, которые возвращают информацию через торговую функцию PositionGetDouble - они возвращают актуальную в данный момент информацию (читай самую свежую) или это информация на момент входа в цикл перебора позиций (читай с момента выделения позиции)? Вопрос больше вот по этим двум функциям:

PriceCurrent

Получает текущую цену по символу позиции

Profit

Получает размер текущей прибыли по позиции

...

Проверочный код:

//+------------------------------------------------------------------+
//|                                      SleepPriceCurrentProfit.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
#property description "Все свойства позиций класса CPositionInfo, которые возвращают информацию через"
#property description "торговую функцию PositionGetDouble - они возвращают актуальную в данный момент"
#property description "информацию (читай самую свежую) или это информация на момент входа в цикл перебора позиций"
#property description "(читай с момента выделения позиции)?"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
bool           m_is_trade=true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(m_is_trade)
     {
      m_trade.Buy(1.0);
      m_is_trade=false;
     }
   else
     {
      for(int i=PositionsTotal()-1;i>=0;i--)
         if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
            if(m_position.Symbol()==Symbol())
              {
               string text="";
               text="cycle entry"+"\n"+"PriceCurrent: "+DoubleToString(m_position.PriceCurrent(),Digits())+"\n";
               Comment(text);
               Sleep(15000);
               text=text+"cycle sleep"+"\n"+"PriceCurrent: "+DoubleToString(m_position.PriceCurrent(),Digits())+"\n";
               Comment(text);
               Sleep(15000);
               if(m_position.SelectByIndex(i))
                 {
                  text=text+"reselect"+"\n"+"PriceCurrent: "+DoubleToString(m_position.PriceCurrent(),Digits());
                  Comment(text);
                  Sleep(15000);
                 }
              }
     }
  }
//+------------------------------------------------------------------+

Что он делает:

  • при входе в цикл формирует строку "cycle entry" - в ней цена возвращаемая из PriceCurrent и вывод на экран
  • далее пауза 15 секунд и формирование новой строки "cycle sleep" - в ней снова цена из PriceCurrent и вывод на экран
  • снова пауза 15 секунд и в этот раз делается повторный выбор позиции и формируется строка "reselect" и выводится на экран


В итоге, таки да: 

Для гарантированного получения свежих данных о позиции рекомендуется вызывать функцию PositionSelect() непосредственно перед обращением за ними.

В нашем случае для гарантированного получения свежих данных о позиции нужно использовать SelectByIndex непосредственно перед обращением за ними.

Файлы:
 

Лично я сделал свой объект CPositionInfo, по аналогии с объектом Стандартой Библиотеки. Как раз для избежания вот таких неоднозначностей. У меня - данные в этот объект заносятся через Select(), и валидны именно на этот момент. Если проходит какое-то время, данные могут стать невалидными - следует снова выполнить Select().

 
George Merts:

Лично я сделал свой объект CPositionInfo, по аналогии с объектом Стандартой Библиотеки. Как раз для избежания вот таких неоднозначностей. У меня - данные в этот объект заносятся через Select(), и валидны именно на этот момент. Если проходит какое-то время, данные могут стать невалидными - следует снова выполнить Select().


Здесь неоднозначностей нет, это скорее пример который ВИЗУАЛЬНО раскрывает смысл строк из справки (например из PositionSelect:

Примечание

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

)

 

Есть замечатальная must-read статья "Ордерa, позиции и сделки в MetaTrader 5". Там есть, в том числе, и про кэш позиций .


PositionSelect и PositionGetSymbol

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

После выполнения любой из этих функций кэш позиций содержит данные только об одной позиции, если функция выполнена успешно. В противном случае в кэше позиций ничего нет. Результат выполнения функции PositionsTotal() не зависит от заполненности кэша позиций - она всегда возвращает реальное количество открытых позиций в базе терминала по всем символам.
 
George Merts:

Лично я сделал свой объект CPositionInfo, по аналогии с объектом Стандартой Библиотеки. Как раз для избежания вот таких неоднозначностей. У меня - данные в этот объект заносятся через Select(), и валидны именно на этот момент. Если проходит какое-то время, данные могут стать невалидными - следует снова выполнить Select().


CPositionInfo реагирует на любые 

 
fxsaber:

CPositionInfo реагирует на любые 


Вызванные ВНЕ класса.

Потому, что выдаёт информацию из кэша, который заполняется вышеназванными функциями.
 
Класс CPositionInfo коварен по своей сути. Если бы он назывался СPositionCash, было бы наверно получше, ведь он представляет не позицию, а кэш позиций терминала.

У меня в программе было два экземпляра CPositionInfo для двух инструментов. В результате программа не работала. Часа два ушло на разбирательство с отладчиком. Вызов CPositionInfo::Select() из одного экземпляра нейтрализует другие экземляры, так что они все представляют информацию о позиции по одинаковому инструменту, который указан в последнем по времени вызове CPositionInfo::Select(). Поэтому экземпляры CPositionInfo не имеют смысла. В документации класса CPositionInfo об этом ни гу-гу. Очень расстраивает такая ситуация.

Есть ли списочек, какие ещё must-read статьи нужно прочитать, чтобы не попадать в такие ловушки?
 
rel18:
Класс CPositionInfo коварен по своей сути. Если бы он назывался СPositionCash, было бы наверно получше, ведь он представляет не позицию, а кэш позиций терминала.

У меня в программе было два экземпляра CPositionInfo для двух инструментов. В результате программа не работала. Часа два ушло на разбирательство с отладчиком. Вызов CPositionInfo::Select() из одного экземпляра нейтрализует другие экземляры, так что они все представляют информацию о позиции по одинаковому инструменту, который указан в последнем по времени вызове CPositionInfo::Select(). Поэтому экземпляры CPositionInfo не имеют смысла. В документации класса CPositionInfo об этом ни гу-гу. Очень расстраивает такая ситуация.

Есть ли списочек, какие ещё must-read статьи нужно прочитать, чтобы не попадать в такие ловушки?

Стандартная библиотека почти вся такая, с ловушками особенностями.

Пользуйтесь проверенными библиотеками из кодобазы или проверяйте все досконально сами.

 
rel18:
...Есть ли списочек, какие ещё must-read статьи нужно прочитать, чтобы не попадать в такие ловушки?

Пост выше прочитайте пож-ста.

Класс CPositionInfo коварен по своей сути. Если бы он назывался СPositionCash, было бы наверно получше, ведь он представляет не позицию, а кэш позиций терминала. 

У меня в программе было два экземпляра CPositionInfo для двух инструментов. В результате программа не работала. Часа два ушло на разбирательство с отладчиком. Вызов CPositionInfo::Select() из одного экземпляра нейтрализует другие экземляры, так что они все представляют информацию о позиции по одинаковому инструменту, который указан в последнем по времени вызове CPositionInfo::Select(). Поэтому экземпляры CPositionInfo не имеют смысла. В документации класса CPositionInfo об этом ни гу-гу. Очень расстраивает такая ситуация.

Ещё как гу-гу. Написано же на великом могучем в Документации:

Класс CPositionInfo

Класс CPositionInfo является классом для упрощенного доступа к свойствам открытой рыночной позиции.

Описание

Класс CPositionInfo обеспечивает доступ к свойствам открытой рыночной позиции.

И само название класса. Это не CPosition. А именно CPositionInfo.