//+------------------------------------------------------------------+ //| 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 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=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