Hedging. Работа с историей. Расчёт прибыли/убытков ПОЗИЦИИ в пунктах.

Задача: на Hedge счёте по истории СДЕЛОК собрать ПОЗИЦИИ и определить прибыль/убыток в пунктах.

Если сильно упростить задачу, то всё сводится к тому, что нужно от цены закрытия позиции отнять цену открытия позиции (пока не смотрим на полученный знак результата: «+» или «-» и на тип позиции: Buy или Sell). А вот в реальных условиях возникают нюансы.

  1. Вариант из двух шагов: шаг первый — открыли позицию, шаг второй — закрыли позицию — это самый идеальный вариант, но бывает и больше шагов. Пример: открыли Buy объёмом 0.05, выполнили частичное закрытие объёмом 0.03 (при этом осталась позиция Buy объёмом 0.02) и потом только окончательно закрыли позицию объёмом 0.02.
  2. В запрошенную историю (HistorySelect) могут попасть неполные части позиций:

    Пояснения: от позиции #1 в запрашиваемый период вошли только часть сделок — значит реконструировать позицию #1 не выйдет. Аналогичная ситуация с позицией #4 — это текущая позиция, которая ещё не закрыта и, значит, невозможно посчитать её ИТОГОВЫЙ финансовый результат.
    fgfg
  3. Оставлю место, может ещё есть нюансы.

Идеальный вариант: открытых позиций нет, а по запрашиваемому интервалу торговой истории можно полностью восстановить ПОЗИЦИИ. Вот распечатка торговой истории сделок

  1. Открыта позиция Buy объёмом 0.03 ( 119707903 ).
  2. Открыта позиция Sell объёмом 0.02 ( 119708383 ).
  3. Позиция 119707903 закрыта встречной позицией 119708383 (в итоге осталась позиция Buy ( 119707903 ) объёмом 0.01).
  4. Открыта позиция Sell объёмом 0.05 ( 119708643 ).
  5. Позиция 119707903 закрыта встречной позицией 119708643 (в итоге осталась позиция Sell ( 119708643 ) объёмом 0.04).
  6. Окончательное закрытие позиции Sell ( 119708643 ) объёмом 0.04).

Такая распечатка получена при помощи скрипта, в котором указывается с какого момента запрашивать историю

Думаю лучшим способом будет такой вариант: один проход по полученному списку сделок. В процесс прохода сделки сортировать по POSITION_ID. В итоге должно выйти несколько объектов — позиций, в каждом из которых содержаться ЕГО сделки:

Осталось придумать, как лучше провернуть (обернуть) это.

Было ранее (скрипт «HistorySelect.mq5» из поста #1) давал такую распечатку:

и сейчас реконструкция даёт такую распечатку:

Нужно проверить распечатки. Если всё верно подготовлю код.

Скрипт «Reconstruction of positions.mq5» реконструирования позиции (пока просто группировка сделок в позиции, без учета целостности — смотреть рисунок из самого первого поста).

CMyPosition(void);
//— методы доступа к защищённым данным
void >const long value) < m_pos_ >long >void ) const < return (m_pos_id); >
>;
//+——————————————————————+
//| Класс — сделка |
//+——————————————————————+
class CMyDeal : public CObject
private :
long m_deal_entry; // направление сделки – вход в рынок, выход из рынка или разворот
long m_deal_type; // тип сделки
double m_deal_price; // цена сделки
double m_deal_volume; // объём сделки
long m_deal_ >// идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка
double m_deal_profit; // финансовый результат сделки
public :
CMyDeal( void );

CMyDeal( void );
//— методы доступа к защищённым данным
void Entry_deal( const long value) < m_deal_entry=value; >
long Entry_deal( void ) const

void Type_deal( const long value) < m_deal_type=value; >
long Type_deal( void ) const

void Price_deal( const double value) < m_deal_price=value; >
double Price_deal( void ) const

void Volume_deal( const double value) < m_deal_volume=value; >
double Volume_deal( void ) const

void >const long value) < m_deal_ >long >void ) const

CMyDeal( void )
>
//+——————————————————————+
//| Script program start function |
//+——————————————————————+
void OnStart ()
//—
if ( AccountInfoInteger ( ACCOUNT_MARGIN_MODE )!= ACCOUNT_MARGIN_MODE_RETAIL_HEDGING )
Print ( «This script can be started only on a hedge; Этот скрипт можно запускать только на хедж» );
return ;
>
Print_IDs();
>
//+——————————————————————+
//| List all positions and deals |
//+——————————————————————+
void Print_ >void )
CArrayObj arr_positions; // объкт динамического массива указателей

//— запрашиваем историю сделок и ордеров за указанный период серверного времени
HistorySelect (start, TimeCurrent ()+ 86400 );
uint total = HistoryDealsTotal (); // количество сделок в истории
ulong ticket = 0 ; // тикет сделки в истории
long magic = 0 ;
long type = 0 ; // тип сделки
long deal_ >0 ; // идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка
double volume = 0.0 ; // объём сделки
double profit = 0.0 ; // финансовый результат сделки
double price = 0.0 ; // цена сделки
string symbol = NULL ; // имя символа, по которому произведена сделка
long entry = 0 ; // направление сделки – вход в рынок, выход из рынка или разворот
//— for all deals
for ( uint i= 0 ;i //— try to get deals ticket
if ((ticket= HistoryDealGetTicket (i))> 0 )
//— get deals properties
magic = HistoryDealGetInteger (ticket, DEAL_MAGIC );
type = HistoryDealGetInteger (ticket, DEAL_TYPE );
deal_ >HistoryDealGetInteger (ticket, DEAL_POSITION_ID );
volume = HistoryDealGetDouble (ticket, DEAL_VOLUME );
profit = HistoryDealGetDouble (ticket, DEAL_PROFIT );
price = HistoryDealGetDouble (ticket, DEAL_PRICE );
symbol = HistoryDealGetString (ticket, DEAL_SYMBOL );
entry = HistoryDealGetInteger (ticket, DEAL_ENTRY );
if (symbol== Symbol () /*&& magic==m_magic*/ )
bool find= false ;
for ( int j= 0 ;j //— объявим указатель на объект класса CMyPosition и присвоим ему элемент из указанной позиции массива
CMyPosition *my_position=arr_positions.At(j);

if (my_position== NULL )
//— ошибка чтения из массива
Print ( «Get element error (\»arr_positions\»)» );
return ;
>
if (my_position. > find= true ;
//— объявим указатель на объект класса CMyDeal и присвоим ему вновь созданный объект класса CMyDeal
CMyDeal *my_deal= new CMyDeal;
if (my_deal== NULL )
//— ошибка создания
Print ( «Object create error (\»my_deal\»)» );
return ;
>
my_deal.Entry_deal(entry);
my_deal.Type_deal(type);
my_deal.Price_deal(price);
my_deal.Volume_deal(volume);
my_deal.ID_deal(deal_id);
my_deal.Profit_deal(profit);

my_position.Add(my_deal);
>
>
if (!find)
//— объявим указатель на объект класса CMyPosition и присвоим ему вновь созданный объект класса CMyPosition
CMyPosition *my_position= new CMyPosition;
if (my_position== NULL )
//— ошибка создания
Print ( «Object create error (\»arr_positions\»)» );
return ;
>
my_position.ID(deal_id);
//— объявим указатель на объект класса CMyDeal и присвоим ему вновь созданный объект класса CMyDeal
CMyDeal *my_deal= new CMyDeal;
if (my_deal== NULL )
//— ошибка создания
Print ( «Object create error (\»my_deal\»)» );
return ;
>
my_deal.Entry_deal(entry);
my_deal.Type_deal(type);
my_deal.Price_deal(price);
my_deal.Volume_deal(volume);
my_deal.ID_deal(deal_id);
my_deal.Profit_deal(profit);

Теперь нужно вводить проверки целостности позиций.

Источник: www.mql5.com

Related posts