609 lines
68 KiB
MQL5
609 lines
68 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Position.mqh |
|
|
//| Copyright 2024, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
|
|
#include "Deal.mqh"
|
|
#include <Arrays\ArrayObj.mqh>
|
|
|
|
enum ENUM_POSITION_SORT_MODE
|
|
{
|
|
SORT_MODE_POSITION_TICKET = 0, // Режим сравнения/сортировки по тикету позиции
|
|
SORT_MODE_POSITION_TIME, // Режим сравнения/сортировки по времени открытия позиции
|
|
SORT_MODE_POSITION_TIME_MSC, // Режим сравнения/сортировки по времени открытия позиции в миллисекундах
|
|
SORT_MODE_POSITION_TIME_UPDATE, // Режим сравнения/сортировки по времени изменения позиции
|
|
SORT_MODE_POSITION_TIME_UPDATE_MSC, // Режим сравнения/сортировки по времени изменения позиции в миллисекундах
|
|
SORT_MODE_POSITION_TYPE, // Режим сравнения/сортировки по типу позиции
|
|
SORT_MODE_POSITION_MAGIC, // Режим сравнения/сортировки по Magic number позиции
|
|
SORT_MODE_POSITION_IDENTIFIER, // Режим сравнения/сортировки по идентификатору позиции
|
|
SORT_MODE_POSITION_REASON, // Режим сравнения/сортировки по причине открытия позиции
|
|
SORT_MODE_POSITION_VOLUME, // Режим сравнения/сортировки по объему позиции
|
|
SORT_MODE_POSITION_PRICE_OPEN, // Режим сравнения/сортировки по цене позиции
|
|
SORT_MODE_POSITION_SL, // Режим сравнения/сортировки по уровню Stop Loss для открытой позиции
|
|
SORT_MODE_POSITION_TP, // Режим сравнения/сортировки по уровню Take Profit для открытой позиции
|
|
SORT_MODE_POSITION_PRICE_CURRENT, // Режим сравнения/сортировки по текущей цене по символу
|
|
SORT_MODE_POSITION_SWAP, // Режим сравнения/сортировки по накопленному свопу
|
|
SORT_MODE_POSITION_PROFIT, // Режим сравнения/сортировки по текущей прибыли
|
|
SORT_MODE_POSITION_SYMBOL, // Режим сравнения/сортировки по символу, по которому открыта позиция
|
|
SORT_MODE_POSITION_COMMENT, // Режим сравнения/сортировки по комментарию к позиции
|
|
SORT_MODE_POSITION_EXTERNAL_ID, // Режим сравнения/сортировки по идентификатору позиции во внешней системе
|
|
SORT_MODE_POSITION_TIME_CLOSE, // Режим сравнения/сортировки по времени открытия позиции
|
|
SORT_MODE_POSITION_TIME_CLOSE_MSC, // Режим сравнения/сортировки по времени открытия позиции в миллисекундах
|
|
SORT_MODE_POSITION_PRICE_CLOSE, // Режим сравнения/сортировки по цене позиции
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Класс позиции |
|
|
//+------------------------------------------------------------------+
|
|
class CPosition : public CObject
|
|
{
|
|
private:
|
|
|
|
protected:
|
|
CArrayObj m_list_deals; // Список сделок позиции
|
|
CDeal m_temp_deal; // Временный объект-сделка для поиска по свойству в списке
|
|
|
|
//--- Возвращает время с миллисекундами
|
|
string TimeMscToString(const long time_msc,int flags=TIME_DATE|TIME_MINUTES|TIME_SECONDS) const;
|
|
|
|
//--- Целочисленные свойства
|
|
long m_ticket; // Тикет позиции
|
|
datetime m_time; // Время открытия позиции
|
|
long m_time_msc; // Время открытия позиции в миллисекундах с 01.01.1970
|
|
datetime m_time_update; // Время изменения позиции
|
|
long m_time_update_msc; // Время изменения позиции в миллисекундах с 01.01.1970
|
|
ENUM_POSITION_TYPE m_type; // Тип позиции
|
|
long m_magic; // Magic number для позиции (смотри ORDER_MAGIC)
|
|
long m_identifier; // Идентификатор позиции
|
|
ENUM_POSITION_REASON m_reason; // Причина открытия позиции
|
|
|
|
//--- Вещественные свойства
|
|
double m_volume; // Объем позиции
|
|
double m_price_open; // Цена позиции
|
|
double m_sl; // Уровень Stop Loss для открытой позиции
|
|
double m_tp; // Уровень Take Profit для открытой позиции
|
|
double m_price_current; // Текущая цена по символу
|
|
double m_swap; // Накопленный своп
|
|
double m_profit; // Текущая прибыль
|
|
|
|
//--- Строковые свойства
|
|
string m_symbol; // Символ, по которому открыта позиция
|
|
string m_comment; // Комментарий к позиции
|
|
string m_external_id; // Идентификатор позиции во внешней системе (на бирже)
|
|
|
|
//--- Дополнительные свойства
|
|
long m_chart_id; // Идентификатор графика
|
|
int m_profit_pt; // Прибыль в пунктах
|
|
int m_digits; // Digits символа
|
|
double m_point; // Значение одного пункта символа
|
|
double m_contract_size; // Размер торгового контракта символа
|
|
string m_currency_profit; // Валюта прибыли символа
|
|
string m_account_currency; // Валюта депозита
|
|
|
|
string m_line_name; // Имя графического объекта-линии
|
|
color m_line_color; // Цвет соединительной линии
|
|
|
|
//---Создаёт линию, соединяющую сделки открытия-закрытия
|
|
virtual bool CreateLine(void);
|
|
|
|
//--- Возвращает указатель на сделку (1) открытия, (2) закрытия
|
|
CDeal *GetDealIn(void) const;
|
|
CDeal *GetDealOut(void) const;
|
|
|
|
//--- (1) Скрывает, (2) отображает значки сделок на графике
|
|
void HideDeals(const bool chart_redraw=false);
|
|
void ShowDeals(const bool chart_redraw=false);
|
|
|
|
//--- (1) Скрывает, (2) отображает соединительную линию между значками сделок
|
|
void HideLine(const bool chart_redraw=false);
|
|
void ShowLine(const bool chart_redraw=false);
|
|
|
|
public:
|
|
//--- Установка свойств
|
|
//--- Целочисленные свойства
|
|
void SetTicket(const long ticket) { this.m_ticket=ticket; } // Тикет позиции
|
|
void SetTime(const datetime time) { this.m_time=time; } // Время открытия позиции
|
|
void SetTimeMsc(const long value) { this.m_time_msc=value; } // Время открытия позиции в миллисекундах с 01.01.1970
|
|
void SetTimeUpdate(const datetime time) { this.m_time_update=time; } // Время изменения позиции
|
|
void SetTimeUpdateMsc(const long value) { this.m_time_update_msc=value; } // Время изменения позиции в миллисекундах с 01.01.1970
|
|
void SetTypePosition(const ENUM_POSITION_TYPE type) { this.m_type=type; } // Тип позиции
|
|
void SetMagic(const long magic) { this.m_magic=magic; } // Magic number для позиции (смотри ORDER_MAGIC)
|
|
void SetID(const long id) { this.m_identifier=id; } // Идентификатор позиции
|
|
void SetReason(const ENUM_POSITION_REASON reason) { this.m_reason=reason; } // Причина открытия позиции
|
|
|
|
//--- Вещественные свойства
|
|
void SetVolume(const double volume) { this.m_volume=volume; } // Объем позиции
|
|
void SetPriceOpen(const double price) { this.m_price_open=price; } // Цена позиции
|
|
void SetSL(const double value) { this.m_sl=value; } // Уровень Stop Loss для открытой позиции
|
|
void SetTP(const double value) { this.m_tp=value; } // Уровень Take Profit для открытой позиции
|
|
void SetPriceCurrent(const double price) { this.m_price_current=price; } // Текущая цена по символу
|
|
void SetSwap(const double value) { this.m_swap=value; } // Накопленный своп
|
|
void SetProfit(const double value) { this.m_profit=value; } // Текущая прибыль
|
|
|
|
//--- Строковые свойства
|
|
void SetSymbol(const string symbol) { this.m_symbol=symbol; } // Символ, по которому открыта позиция
|
|
void SetComment(const string comment) { this.m_comment=comment; } // Комментарий к позиции
|
|
void SetExternalID(const string ext_id) { this.m_external_id=ext_id; } // Идентификатор позиции во внешней системе (на бирже)
|
|
|
|
|
|
//--- Получение свойств
|
|
//--- Целочисленные свойства
|
|
long Ticket(void) const { return(this.m_ticket); } // Тикет позиции
|
|
datetime Time(void) const { return(this.m_time); } // Время открытия позиции
|
|
long TimeMsc(void) const { return(this.m_time_msc); } // Время открытия позиции в миллисекундах с 01.01.1970
|
|
datetime TimeUpdate(void) const { return(this.m_time_update); } // Время изменения позиции
|
|
long TimeUpdateMsc(void) const { return(this.m_time_update_msc);} // Время изменения позиции в миллисекундах с 01.01.1970
|
|
ENUM_POSITION_TYPE TypePosition(void) const { return(this.m_type); } // Тип позиции
|
|
long Magic(void) const { return(this.m_magic); } // Magic number для позиции (смотри ORDER_MAGIC)
|
|
long ID(void) const { return(this.m_identifier); } // Идентификатор позиции
|
|
ENUM_POSITION_REASON Reason(void) const { return(this.m_reason); } // Причина открытия позиции
|
|
|
|
//--- Вещественные свойства
|
|
double Volume(void) const { return(this.m_volume); } // Объем позиции
|
|
double PriceOpen(void) const { return(this.m_price_open); } // Цена позиции
|
|
double SL(void) const { return(this.m_sl); } // Уровень Stop Loss для открытой позиции
|
|
double TP(void) const { return(this.m_tp); } // Уровень Take Profit для открытой позиции
|
|
double PriceCurrent(void) const { return(this.m_price_current); } // Текущая цена по символу
|
|
double Swap(void) const { return(this.m_swap); } // Накопленный своп
|
|
double Profit(void) const { return(this.m_profit); } // Текущая прибыль
|
|
|
|
//--- Строковые свойства
|
|
string Symbol(void) const { return(this.m_symbol); } // Символ, по которому открыта позиция
|
|
string Comment(void) const { return(this.m_comment); } // Комментарий к позиции
|
|
string ExternalID(void) const { return(this.m_external_id); } // Идентификатор позиции во внешней системе (на бирже)
|
|
|
|
//--- Дополнительные свойства
|
|
ulong DealIn(void) const; // Тикет сделки открытия
|
|
ulong DealOut(void) const; // Тикет сделки закрытия
|
|
datetime TimeClose(void) const; // Время закрытия
|
|
long TimeCloseMsc(void) const; // Время закрытия в миллисекундах
|
|
int ProfitInPoints(void) const; // Прибыль в пунктах
|
|
double PriceClose(void) const; // Цена закрытия
|
|
|
|
//--- Добавляет сделку в список сделок, возвращает указатель
|
|
CDeal *DealAdd(const long ticket);
|
|
|
|
//--- Устанавливает цвет (1) соединительной линии, (2) сделок Buy и Sell
|
|
void SetLineColor(const color clr=C'225,68,29');
|
|
void SetDealsColor(const color clr_deal_buy=C'3,95,172', const color clr_deal_sell=C'225,68,29');
|
|
|
|
//--- Возвращает описание типа позиции
|
|
string TypeDescription(void) const;
|
|
|
|
//--- Возвращает описание времени и цены открытия позиции
|
|
string TimePriceCloseDescription(void);
|
|
|
|
//--- Возвращает описание времени и цены закрытия позиции
|
|
string TimePriceOpenDescription(void);
|
|
|
|
//--- Возвращает краткое описание позиции
|
|
string Description(void);
|
|
|
|
//--- Возвращает текст всплывающего сообщения позиции
|
|
virtual string Tooltip(void);
|
|
|
|
//--- Распечатывает в журнале свойства позиции и её сделок
|
|
void Print(void);
|
|
|
|
//--- (1) Скрывает, (2) отображает графическое представление позиции на графике
|
|
void Hide(const bool chart_redraw=false);
|
|
void Show(const bool chart_redraw=false);
|
|
|
|
//--- Сравнивает два объекта между собой по указанному в mode свойству
|
|
virtual int Compare(const CObject *node, const int mode=0) const;
|
|
|
|
//--- Конструктор/деструктор
|
|
CPosition(const long position_id, const string symbol);
|
|
CPosition(void) { this.m_symbol=::Symbol(); }
|
|
~CPosition();
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Конструктор |
|
|
//+------------------------------------------------------------------+
|
|
CPosition::CPosition(const long position_id, const string symbol)
|
|
{
|
|
this.m_list_deals.Sort(SORT_MODE_DEAL_TIME_MSC);
|
|
this.m_identifier = position_id;
|
|
this.m_account_currency = ::AccountInfoString(ACCOUNT_CURRENCY);
|
|
this.m_symbol = (symbol==NULL ? ::Symbol() : symbol);
|
|
this.m_digits = (int)::SymbolInfoInteger(this.m_symbol,SYMBOL_DIGITS);
|
|
this.m_point = ::SymbolInfoDouble(this.m_symbol,SYMBOL_POINT);
|
|
this.m_contract_size = ::SymbolInfoDouble(this.m_symbol,SYMBOL_TRADE_CONTRACT_SIZE);
|
|
this.m_currency_profit = ::SymbolInfoString(this.m_symbol,SYMBOL_CURRENCY_PROFIT);
|
|
this.m_chart_id = ::ChartID();
|
|
this.m_line_name = "line#"+(string)this.m_identifier;
|
|
this.m_line_color = C'225,68,29';
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Деструктор |
|
|
//+------------------------------------------------------------------+
|
|
CPosition::~CPosition()
|
|
{
|
|
::ObjectsDeleteAll(this.m_chart_id, this.m_line_name);
|
|
this.m_list_deals.Clear();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сравнивает два объекта между собой по указанному свойству |
|
|
//+------------------------------------------------------------------+
|
|
int CPosition::Compare(const CObject *node,const int mode=0) const
|
|
{
|
|
const CPosition *obj=node;
|
|
switch(mode)
|
|
{
|
|
case SORT_MODE_POSITION_TICKET : return(this.Ticket() > obj.Ticket() ? 1 : this.Ticket() < obj.Ticket() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME : return(this.Time() > obj.Time() ? 1 : this.Time() < obj.Time() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME_MSC : return(this.TimeMsc() > obj.TimeMsc() ? 1 : this.TimeMsc() < obj.TimeMsc() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME_UPDATE : return(this.TimeUpdate() > obj.TimeUpdate() ? 1 : this.TimeUpdate() < obj.TimeUpdate() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME_UPDATE_MSC: return(this.TimeUpdateMsc() > obj.TimeUpdateMsc() ? 1 : this.TimeUpdateMsc() < obj.TimeUpdateMsc() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TYPE : return(this.TypePosition() > obj.TypePosition() ? 1 : this.TypePosition() < obj.TypePosition() ? -1 : 0);
|
|
case SORT_MODE_POSITION_MAGIC : return(this.Magic() > obj.Magic() ? 1 : this.Magic() < obj.Magic() ? -1 : 0);
|
|
case SORT_MODE_POSITION_IDENTIFIER : return(this.ID() > obj.ID() ? 1 : this.ID() < obj.ID() ? -1 : 0);
|
|
case SORT_MODE_POSITION_REASON : return(this.Reason() > obj.Reason() ? 1 : this.Reason() < obj.Reason() ? -1 : 0);
|
|
case SORT_MODE_POSITION_VOLUME : return(this.Volume() > obj.Volume() ? 1 : this.Volume() < obj.Volume() ? -1 : 0);
|
|
case SORT_MODE_POSITION_PRICE_OPEN : return(this.PriceOpen() > obj.PriceOpen() ? 1 : this.PriceOpen() < obj.PriceOpen() ? -1 : 0);
|
|
case SORT_MODE_POSITION_SL : return(this.SL() > obj.SL() ? 1 : this.SL() < obj.SL() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TP : return(this.TP() > obj.TP() ? 1 : this.TP() < obj.TP() ? -1 : 0);
|
|
case SORT_MODE_POSITION_PRICE_CURRENT : return(this.PriceCurrent() > obj.PriceCurrent() ? 1 : this.PriceCurrent() < obj.PriceCurrent() ? -1 : 0);
|
|
case SORT_MODE_POSITION_SWAP : return(this.Swap() > obj.Swap() ? 1 : this.Swap() < obj.Swap() ? -1 : 0);
|
|
case SORT_MODE_POSITION_PROFIT : return(this.Profit() > obj.Profit() ? 1 : this.Profit() < obj.Profit() ? -1 : 0);
|
|
case SORT_MODE_POSITION_SYMBOL : return(this.Symbol() > obj.Symbol() ? 1 : this.Symbol() < obj.Symbol() ? -1 : 0);
|
|
case SORT_MODE_POSITION_COMMENT : return(this.Comment() > obj.Comment() ? 1 : this.Comment() < obj.Comment() ? -1 : 0);
|
|
case SORT_MODE_POSITION_EXTERNAL_ID : return(this.ExternalID() > obj.ExternalID() ? 1 : this.ExternalID() < obj.ExternalID() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME_CLOSE : return(this.TimeClose() > obj.TimeClose() ? 1 : this.TimeClose() < obj.TimeClose() ? -1 : 0);
|
|
case SORT_MODE_POSITION_TIME_CLOSE_MSC : return(this.TimeCloseMsc() > obj.TimeCloseMsc() ? 1 : this.TimeCloseMsc() < obj.TimeCloseMsc() ? -1 : 0);
|
|
case SORT_MODE_POSITION_PRICE_CLOSE : return(this.PriceClose() > obj.PriceClose() ? 1 : this.PriceClose() < obj.PriceClose() ? -1 : 0);
|
|
default : return -1;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает время с миллисекундами |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::TimeMscToString(const long time_msc, int flags=TIME_DATE|TIME_MINUTES|TIME_SECONDS) const
|
|
{
|
|
return(::TimeToString(time_msc/1000, flags) + "." + ::IntegerToString(time_msc %1000, 3, '0'));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает указатель на сделку открытия |
|
|
//+------------------------------------------------------------------+
|
|
CDeal *CPosition::GetDealIn(void) const
|
|
{
|
|
int total=this.m_list_deals.Total();
|
|
for(int i=0; i<total; i++)
|
|
{
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
if(deal.Entry()==DEAL_ENTRY_IN)
|
|
return deal;
|
|
}
|
|
return NULL;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает указатель на сделку закрытия |
|
|
//+------------------------------------------------------------------+
|
|
CDeal *CPosition::GetDealOut(void) const
|
|
{
|
|
for(int i=this.m_list_deals.Total()-1; i>=0; i--)
|
|
{
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
if(deal.Entry()==DEAL_ENTRY_OUT || deal.Entry()==DEAL_ENTRY_OUT_BY)
|
|
return deal;
|
|
}
|
|
return NULL;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает тикет сделки открытия |
|
|
//+------------------------------------------------------------------+
|
|
ulong CPosition::DealIn(void) const
|
|
{
|
|
CDeal *deal=this.GetDealIn();
|
|
return(deal!=NULL ? deal.Ticket() : 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает тикет сделки закрытия |
|
|
//+------------------------------------------------------------------+
|
|
ulong CPosition::DealOut(void) const
|
|
{
|
|
CDeal *deal=this.GetDealOut();
|
|
return(deal!=NULL ? deal.Ticket() : 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает время закрытия |
|
|
//+------------------------------------------------------------------+
|
|
datetime CPosition::TimeClose(void) const
|
|
{
|
|
CDeal *deal=this.GetDealOut();
|
|
return(deal!=NULL ? deal.Time() : 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает время закрытия в миллисекундах |
|
|
//+------------------------------------------------------------------+
|
|
long CPosition::TimeCloseMsc(void) const
|
|
{
|
|
CDeal *deal=this.GetDealOut();
|
|
return(deal!=NULL ? deal.TimeMsc() : 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает цену закрытия |
|
|
//+------------------------------------------------------------------+
|
|
double CPosition::PriceClose(void) const
|
|
{
|
|
CDeal *deal=this.GetDealOut();
|
|
return(deal!=NULL ? deal.Price() : 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает прибыль в пунктах |
|
|
//+------------------------------------------------------------------+
|
|
int CPosition::ProfitInPoints(void) const
|
|
{
|
|
//--- Если Point символа не получен ранее, сообщаем об этом и возвращаем 0
|
|
if(this.m_point==0)
|
|
{
|
|
::Print("The Point() value could not be retrieved.");
|
|
return 0;
|
|
}
|
|
//--- Получаем цены открытия и закрытия позиции
|
|
double open =this.PriceOpen();
|
|
double close=this.PriceClose();
|
|
|
|
//--- Если цены получить не удалось - возвращаем 0
|
|
if(open==0 || close==0)
|
|
return 0;
|
|
|
|
//--- В зависимости от типа позиции возвращаем рассчитанное значение прибыли позиции в пунктах
|
|
return int(this.TypePosition()==POSITION_TYPE_BUY ? (close-open)/this.m_point : (open-close)/this.m_point);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет сделку в список сделок |
|
|
//+------------------------------------------------------------------+
|
|
CDeal *CPosition::DealAdd(const long ticket)
|
|
{
|
|
//--- Устанавливаем временному объекту тикет искомой сделки и устанавливаем флаг сортировки списка сделок по тикету
|
|
this.m_temp_deal.SetTicket(ticket);
|
|
this.m_list_deals.Sort(SORT_MODE_DEAL_TICKET);
|
|
|
|
//--- Записываем результат проверки присутствия в списке сделки с таким тикетом
|
|
bool added=(this.m_list_deals.Search(&this.m_temp_deal)!=WRONG_VALUE);
|
|
|
|
//--- Устанавливаем списку флаг сортировки по времени в миллисекундах
|
|
this.m_list_deals.Sort(SORT_MODE_DEAL_TIME_MSC);
|
|
|
|
//--- Если сделка с таким тикетом уже есть в списке - возвращаем NULL
|
|
if(added)
|
|
return NULL;
|
|
|
|
//--- Создаём новый объект-сделку
|
|
CDeal *deal=new CDeal(ticket);
|
|
if(deal==NULL)
|
|
return NULL;
|
|
|
|
//--- Добавляем созданный объект в список в порядке сортировки по времени в миллисекундах
|
|
//--- Если сделку добавить в список не удалось - удаляем объект сделки и возвращаем NULL
|
|
if(!this.m_list_deals.InsertSort(deal))
|
|
{
|
|
delete deal;
|
|
return NULL;
|
|
}
|
|
|
|
//--- Если это сделка закрытия позиции - записываем в значение прибыли позиции прибыль из свойств сделки и
|
|
//--- создаём соединительную линию между значками сделок открытия-закрытия позиции
|
|
if(deal.Entry()==DEAL_ENTRY_OUT || deal.Entry()==DEAL_ENTRY_OUT_BY)
|
|
{
|
|
this.SetProfit(deal.Profit());
|
|
this.CreateLine();
|
|
}
|
|
|
|
//--- Возвращаем указатель на созданный объект-сделку
|
|
return deal;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает описание типа позиции |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::TypeDescription(void) const
|
|
{
|
|
return(this.m_type==POSITION_TYPE_BUY ? "Buy" : this.m_type==POSITION_TYPE_SELL ? "Sell" : "Unknown::"+(string)this.m_type);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает описание времени и цены открытия позиции |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::TimePriceOpenDescription(void)
|
|
{
|
|
return(::StringFormat("Opened %s [%.*f]", this.TimeMscToString(this.TimeMsc()),this.m_digits, this.PriceOpen()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает описание времени и цены закрытия позиции |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::TimePriceCloseDescription(void)
|
|
{
|
|
if(this.TimeCloseMsc()==0)
|
|
return "Not closed yet";
|
|
return(::StringFormat("Closed %s [%.*f]", this.TimeMscToString(this.TimeCloseMsc()),this.m_digits, this.PriceClose()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает краткое описание позиции |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::Description(void)
|
|
{
|
|
return(::StringFormat("Position %s %.2f %s #%I64d, Magic %I64d",
|
|
this.Symbol(), this.Volume(), this.TypeDescription(), this.ID(), this.Magic()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает текст всплывающего сообщения позиции |
|
|
//+------------------------------------------------------------------+
|
|
string CPosition::Tooltip(void)
|
|
{
|
|
//--- Получаем указатели на сделки открытия и закрытия
|
|
CDeal *deal_in =this.GetDealIn();
|
|
CDeal *deal_out=this.GetDealOut();
|
|
|
|
//--- Если сделки не получены - возвращаем пустую строку
|
|
if(deal_in==NULL || deal_out==NULL)
|
|
return NULL;
|
|
|
|
//--- Получаем общие для двух сделок комиссию, своп и оплату за сделку
|
|
double commission=deal_in.Commission()+deal_out.Commission();
|
|
double swap=deal_in.Swap()+deal_out.Swap();
|
|
double fee=deal_in.Fee()+deal_out.Fee();
|
|
|
|
//--- Получаем итоговый профит позиции и значения спреда при открытии и закрытии
|
|
double profit=deal_out.Profit();
|
|
int spread_in=deal_in.Spread();
|
|
int spread_out=deal_out.Spread();
|
|
|
|
//--- Если причина закрытия позиции StopLoss, TakeProfit или StopOut - установим в переменную описание причины
|
|
string reason=(deal_out.Reason()==DEAL_REASON_SL || deal_out.Reason()==DEAL_REASON_TP || deal_out.Reason()==DEAL_REASON_SO ? deal_out.ReasonDescription() : "");
|
|
|
|
//--- Создаём и возвращаем строку всплывающей подсказки
|
|
return(::StringFormat("%s\nCommission %.2f, Swap %.2f, Fee %.2f\nSpread In/Out %d/%d, Profit %+.2f %s (%d points)\nResult: %s %+.2f %s",
|
|
this.Description(), commission, swap, fee, spread_in, spread_out, profit,this.m_currency_profit,
|
|
this.ProfitInPoints(), reason, profit+commission+fee+swap, this.m_currency_profit));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Отображает значки сделок на графике |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::ShowDeals(const bool chart_redraw=false)
|
|
{
|
|
for(int i=this.m_list_deals.Total()-1; i>=0; i--)
|
|
{
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
deal.ShowArrow();
|
|
}
|
|
if(chart_redraw)
|
|
::ChartRedraw(this.m_chart_id);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Скрывает значки сделок на графике |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::HideDeals(const bool chart_redraw=false)
|
|
{
|
|
for(int i=this.m_list_deals.Total()-1; i>=0; i--)
|
|
{
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
deal.HideArrow();
|
|
}
|
|
if(chart_redraw)
|
|
::ChartRedraw(this.m_chart_id);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт линию, соединяющую сделки открытия-закрытия |
|
|
//+------------------------------------------------------------------+
|
|
bool CPosition::CreateLine(void)
|
|
{
|
|
//--- Если графический объект-линию создать не удалось - сообщаем об это в журнал и возвращаем false
|
|
::ResetLastError();
|
|
if(!::ObjectCreate(this.m_chart_id, this.m_line_name, OBJ_TREND, 0, 0, 0, 0, 0))
|
|
{
|
|
::Print("ObjectCreate() failed. Error ", ::GetLastError());
|
|
return false;
|
|
}
|
|
//--- Скрываем линию
|
|
this.HideLine();
|
|
|
|
//--- Устанавливаем для линии рисование точками, устанавливаем цвет и возвращаем true
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_STYLE, STYLE_DOT);
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_COLOR, this.m_line_color);
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Отображает соединительную линию между значками сделок |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::ShowLine(const bool chart_redraw=false)
|
|
{
|
|
//--- Получаем указатели на сделки открытия и закрытия
|
|
CDeal *deal_in= this.GetDealIn();
|
|
CDeal *deal_out=this.GetDealOut();
|
|
|
|
//--- Если сделки не получены - уходим
|
|
if(deal_in==NULL || deal_out==NULL)
|
|
return;
|
|
|
|
//--- Устанавливаем для линии начальные и конечные время и цену из свойств сделок и текст всплывающей подсказки
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_TIME, 0, deal_in.Time());
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_TIME, 1, deal_out.Time());
|
|
::ObjectSetDouble(this.m_chart_id, this.m_line_name, OBJPROP_PRICE, 0, deal_in.Price());
|
|
::ObjectSetDouble(this.m_chart_id, this.m_line_name, OBJPROP_PRICE, 1, deal_out.Price());
|
|
::ObjectSetString(this.m_chart_id, this.m_line_name, OBJPROP_TOOLTIP, this.Tooltip());
|
|
|
|
//--- Показываем линию на графике и, если установлен флаг, обновляем график
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS);
|
|
if(chart_redraw)
|
|
::ChartRedraw(this.m_chart_id);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Скрывает соединительную линию между значками сделок |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::HideLine(const bool chart_redraw=false)
|
|
{
|
|
::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS);
|
|
if(chart_redraw)
|
|
::ChartRedraw(this.m_chart_id);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Устанавливает цвет соединительной линии |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::SetLineColor(const color clr=C'225,68,29')
|
|
{
|
|
if(::ObjectSetInteger(this.m_chart_id, this.m_line_name, OBJPROP_COLOR, clr))
|
|
this.m_line_color=clr;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Устанавливает цвет сделок Buy и Sell |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::SetDealsColor(const color clr_deal_buy=C'3,95,172', const color clr_deal_sell=C'225,68,29')
|
|
{
|
|
//--- В цикле по списку сделок
|
|
int total=this.m_list_deals.Total();
|
|
for(int i=0; i<total; i++)
|
|
{
|
|
//--- получаем очередной объект-сделку
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
//--- Если тип сделки Buy - устанавливаем в объект цвет для сделки Buy
|
|
if(deal.TypeDeal()==DEAL_TYPE_BUY)
|
|
deal.SetColorArrow(clr_deal_buy);
|
|
//--- Если тип сделки Sell - устанавливаем в объект цвет для сделки Sell
|
|
if(deal.TypeDeal()==DEAL_TYPE_SELL)
|
|
deal.SetColorArrow(clr_deal_sell);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Отображает графическое представление позиции на графике |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::Show(const bool chart_redraw=false)
|
|
{
|
|
this.ShowDeals(false);
|
|
this.ShowLine(chart_redraw);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Скрывает графическое представление позиции на графике |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::Hide(const bool chart_redraw=false)
|
|
{
|
|
this.HideLine(false);
|
|
this.HideDeals(chart_redraw);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Распечатывает в журнале свойства позиции и её сделок |
|
|
//+------------------------------------------------------------------+
|
|
void CPosition::Print(void)
|
|
{
|
|
::PrintFormat("%s\n-%s\n-%s", this.Description(), this.TimePriceOpenDescription(), this.TimePriceCloseDescription());
|
|
for(int i=0; i<this.m_list_deals.Total(); i++)
|
|
{
|
|
CDeal *deal=this.m_list_deals.At(i);
|
|
if(deal==NULL)
|
|
continue;
|
|
deal.Print();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|