Article-15026-MQL5-Trade-Hi.../Position.mqh
2026-03-23 12:53:11 +07:00

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();
}
}
//+------------------------------------------------------------------+