Article-15346-MQL5-Trade-Mo.../Position.mqh

520 lines
68 KiB
MQL5
Raw Permalink Normal View History

2026-03-23 13:19:06 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| 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>
//--- 5@5G8A;5=85 F5;>G8A;5==KE A2>9AB2 ?>78F88
enum ENUM_POSITION_PROPERTY_INT
{
POSITION_PROP_TICKET = 0, // "8:5B ?>78F88
POSITION_PROP_TIME, // @5<O >B:@KB8O ?>78F88
POSITION_PROP_TIME_MSC, // @5<O >B:@KB8O ?>78F88 2 <8;;8A5:C=40E
POSITION_PROP_TIME_UPDATE, // @5<O 87<5=5=8O ?>78F88
POSITION_PROP_TIME_UPDATE_MSC, // @5<O 87<5=5=8O ?>78F88 2 <8;;8A5:C=40E
POSITION_PROP_TYPE, // "8? ?>78F88
POSITION_PROP_MAGIC, // Magic number ?>78F88
POSITION_PROP_IDENTIFIER, // 45=B8D8:0B>@ ?>78F88
POSITION_PROP_REASON, // @8G8=0 >B:@KB8O ?>78F88
POSITION_PROP_ACCOUNT_LOGIN, // ><5@ AGQB0
POSITION_PROP_TIME_CLOSE, // @5<O 70:@KB8O ?>78F88
POSITION_PROP_TIME_CLOSE_MSC, // @5<O 70:@KB8O ?>78F88 2 <8;;8A5:C=40E
};
//--- 5@5G8A;5=85 25I5AB25==KE A2>9AB2 ?>78F88
enum ENUM_POSITION_PROPERTY_DBL
{
POSITION_PROP_VOLUME = POSITION_PROP_TIME_CLOSE_MSC+1,// 1J5< ?>78F88
POSITION_PROP_PRICE_OPEN, // &5=0 ?>78F88
POSITION_PROP_SL, // Stop Loss 4;O >B:@KB>9 ?>78F88
POSITION_PROP_TP, // Take Profit 4;O >B:@KB>9 ?>78F88
POSITION_PROP_PRICE_CURRENT, // "5:CI0O F5=0 ?> A8<2>;C
POSITION_PROP_SWAP, // 0:>?;5==K9 A2>?
POSITION_PROP_PROFIT, // "5:CI0O ?@81K;L
POSITION_PROP_CONTRACT_SIZE, // 07<5@ B>@3>2>3> :>=B@0:B0 A8<2>;0
POSITION_PROP_PRICE_CLOSE, // &5=0 70:@KB8O ?>78F88
POSITION_PROP_COMMISSIONS, // 0:>?;5==0O :><8AA8O
POSITION_PROP_FEE, // 0:>?;5==0O >?;0B0 70 A45;:8
};
//--- 5@5G8A;5=85 AB@>:>2KE A2>9AB2 ?>78F88
enum ENUM_POSITION_PROPERTY_STR
{
POSITION_PROP_SYMBOL = POSITION_PROP_FEE+1,// !8<2>;, ?> :>B>@><C >B:@KB0 ?>78F8O
POSITION_PROP_COMMENT, // ><<5=B0@89 : ?>78F88
POSITION_PROP_EXTERNAL_ID, // 45=B8D8:0B>@ ?>78F88 2> 2=5H=59 A8AB5<5
POSITION_PROP_CURRENCY_PROFIT, // 0;NB0 ?@81K;8 A8<2>;0 ?>78F88
POSITION_PROP_ACCOUNT_CURRENCY, // 0;NB0 45?>78B0 0::0C=B0
POSITION_PROP_ACCOUNT_SERVER, // <O A5@25@0
};
//+------------------------------------------------------------------+
//| ;0AA ?>78F88 |
//+------------------------------------------------------------------+
class CPosition : public CObject
{
private:
long m_lprop[POSITION_PROP_TIME_CLOSE_MSC+1]; // 0AA82 4;O E@0=5=8O F5;>G8A;5==KE A2>9AB2
double m_dprop[POSITION_PROP_FEE-POSITION_PROP_TIME_CLOSE_MSC]; // 0AA82 4;O E@0=5=8O 25I5AB25==KE A2>9AB2
string m_sprop[POSITION_PROP_ACCOUNT_SERVER-POSITION_PROP_FEE]; // 0AA82 4;O E@0=5=8O AB@>:>2KE A2>9AB2
//--- >72@0I05B 8=45:A <0AA820, ?> :>B>@><C D0:B8G5A:8 @0A?>;>65=> (1) double-A2>9AB2> 8 (2) string-A2>9AB2> >@45@0
int IndexProp(ENUM_POSITION_PROPERTY_DBL property) const { return(int)property-POSITION_PROP_TIME_CLOSE_MSC-1;}
int IndexProp(ENUM_POSITION_PROPERTY_STR property) const { return(int)property-POSITION_PROP_FEE-1; }
protected:
CArrayObj m_list_deals; // !?8A>: A45;>: ?>78F88
CDeal m_temp_deal; // @5<5==K9 >1J5:B-A45;:0 4;O ?>8A:0 ?> A2>9AB2C 2 A?8A:5
//--- >72@0I05B 2@5<O A <8;;8A5:C=40<8
string TimeMscToString(const long time_msc,int flags=TIME_DATE|TIME_MINUTES|TIME_SECONDS) const;
//--- >?>;=8B5;L=K5 A2>9AB20
int m_profit_pt; // @81K;L 2 ?C=:B0E
int m_digits; // Digits A8<2>;0
double m_point; // =0G5=85 >4=>3> ?C=:B0 A8<2>;0
double m_tick_value; // 0AAG8B0==0O AB>8<>ABL B8:0
//--- >72@0I05B C:070B5;L =0 A45;:C (1) >B:@KB8O, (2) 70:@KB8O
CDeal *GetDealIn(void) const;
CDeal *GetDealOut(void) const;
public:
//--- >72@0I05B A?8A>: A45;>:
CArrayObj *GetListDeals(void) { return(&this.m_list_deals); }
//--- #AB0=>2:0 A2>9AB2
//--- #AB0=02;8205B (1) F5;>G8A;5==>5, (2) 25I5AB25==>5 8 (3) AB@>:>2>5 A2>9AB2>
void SetProperty(ENUM_POSITION_PROPERTY_INT property,long value) { this.m_lprop[property]=value; }
void SetProperty(ENUM_POSITION_PROPERTY_DBL property,double value) { this.m_dprop[this.IndexProp(property)]=value; }
void SetProperty(ENUM_POSITION_PROPERTY_STR property,string value) { this.m_sprop[this.IndexProp(property)]=value; }
//--- &5;>G8A;5==K5 A2>9AB20
void SetTicket(const long ticket) { this.SetProperty(POSITION_PROP_TICKET, ticket); } // "8:5B ?>78F88
void SetTime(const datetime time) { this.SetProperty(POSITION_PROP_TIME, time); } // @5<O >B:@KB8O ?>78F88
void SetTimeMsc(const long value) { this.SetProperty(POSITION_PROP_TIME_MSC, value); } // @5<O >B:@KB8O ?>78F88 2 <8;;8A5:C=40E A 01.01.1970
void SetTimeUpdate(const datetime time) { this.SetProperty(POSITION_PROP_TIME_UPDATE, time); } // @5<O 87<5=5=8O ?>78F88
void SetTimeUpdateMsc(const long value) { this.SetProperty(POSITION_PROP_TIME_UPDATE_MSC, value); } // @5<O 87<5=5=8O ?>78F88 2 <8;;8A5:C=40E A 01.01.1970
void SetTypePosition(const ENUM_POSITION_TYPE type) { this.SetProperty(POSITION_PROP_TYPE, type); } // "8? ?>78F88
void SetMagic(const long magic) { this.SetProperty(POSITION_PROP_MAGIC, magic); } // Magic number 4;O ?>78F88 (A<>B@8 ORDER_MAGIC)
void SetID(const long id) { this.SetProperty(POSITION_PROP_IDENTIFIER, id); } // 45=B8D8:0B>@ ?>78F88
void SetReason(const ENUM_POSITION_REASON reason) { this.SetProperty(POSITION_PROP_REASON, reason); } // @8G8=0 >B:@KB8O ?>78F88
void SetTimeClose(const datetime time) { this.SetProperty(POSITION_PROP_TIME_CLOSE, time); } // @5<O 70:@KB8O
void SetTimeCloseMsc(const long value) { this.SetProperty(POSITION_PROP_TIME_CLOSE_MSC, value); } // @5<O 70:@KB8O 2 <8;;8A5:C=40E
void SetAccountLogin(const long login) { this.SetProperty(POSITION_PROP_ACCOUNT_LOGIN, login); } // ><5@ AGQB0
//--- 5I5AB25==K5 A2>9AB20
void SetVolume(const double volume) { this.SetProperty(POSITION_PROP_VOLUME, volume); } // 1J5< ?>78F88
void SetPriceOpen(const double price) { this.SetProperty(POSITION_PROP_PRICE_OPEN, price); } // &5=0 ?>78F88
void SetSL(const double value) { this.SetProperty(POSITION_PROP_SL, value); } // #@>25=L Stop Loss 4;O >B:@KB>9 ?>78F88
void SetTP(const double value) { this.SetProperty(POSITION_PROP_TP, value); } // #@>25=L Take Profit 4;O >B:@KB>9 ?>78F88
void SetPriceCurrent(const double price) { this.SetProperty(POSITION_PROP_PRICE_CURRENT, price); } // "5:CI0O F5=0 ?> A8<2>;C
void SetSwap(const double value) { this.SetProperty(POSITION_PROP_SWAP, value); } // 0:>?;5==K9 A2>?
void SetProfit(const double value) { this.SetProperty(POSITION_PROP_PROFIT, value); } // "5:CI0O ?@81K;L
void SetPriceClose(const double price) { this.SetProperty(POSITION_PROP_PRICE_CLOSE, price); } // &5=0 70:@KB8O
void SetContractSize(const double value) { this.SetProperty(POSITION_PROP_CONTRACT_SIZE, value); } // 07<5@ B>@3>2>3> :>=B@0:B0 A8<2>;0
void SetCommissions(void); // !>2>:C?=0O :><8AA8O 2A5E A45;>:
void SetFee(void); // !>2>:C?=0O >?;0BC 70 ?@>2545=85 A45;>:
//--- !B@>:>2K5 A2>9AB20
void SetSymbol(const string symbol) { this.SetProperty(POSITION_PROP_SYMBOL, symbol); } // !8<2>;, ?> :>B>@><C >B:@KB0 ?>78F8O
void SetComment(const string comment) { this.SetProperty(POSITION_PROP_COMMENT, comment); } // ><<5=B0@89 : ?>78F88
void SetExternalID(const string ext_id) { this.SetProperty(POSITION_PROP_EXTERNAL_ID, ext_id); } // 45=B8D8:0B>@ ?>78F88 2> 2=5H=59 A8AB5<5 (=0 18@65)
void SetAccountServer(const string server) { this.SetProperty(POSITION_PROP_ACCOUNT_SERVER, server); } // <O A5@25@0
void SetAccountCurrency(const string currency) { this.SetProperty(POSITION_PROP_ACCOUNT_CURRENCY, currency); } // 0;NB0 45?>78B0 0::0C=B0
void SetCurrencyProfit(const string currency) { this.SetProperty(POSITION_PROP_CURRENCY_PROFIT, currency); } // 0;NB0 ?@81K;8 A8<2>;0 ?>78F88
//--- >;CG5=85 A2>9AB2
//--- >72@0I05B 87 <0AA820 A2>9AB2 (1) F5;>G8A;5==>5, (2) 25I5AB25==>5 8 (3) AB@>:>2>5 A2>9AB2>
long GetProperty(ENUM_POSITION_PROPERTY_INT property) const { return this.m_lprop[property]; }
double GetProperty(ENUM_POSITION_PROPERTY_DBL property) const { return this.m_dprop[this.IndexProp(property)]; }
string GetProperty(ENUM_POSITION_PROPERTY_STR property) const { return this.m_sprop[this.IndexProp(property)]; }
//--- &5;>G8A;5==K5 A2>9AB20
long Ticket(void) const { return this.GetProperty(POSITION_PROP_TICKET); } // "8:5B ?>78F88
datetime Time(void) const { return (datetime)this.GetProperty(POSITION_PROP_TIME); } // @5<O >B:@KB8O ?>78F88
long TimeMsc(void) const { return this.GetProperty(POSITION_PROP_TIME_MSC); } // @5<O >B:@KB8O ?>78F88 2 <8;;8A5:C=40E A 01.01.1970
datetime TimeUpdate(void) const { return (datetime)this.GetProperty(POSITION_PROP_TIME_UPDATE);} // @5<O 87<5=5=8O ?>78F88
long TimeUpdateMsc(void) const { return this.GetProperty(POSITION_PROP_TIME_UPDATE_MSC); } // @5<O 87<5=5=8O ?>78F88 2 <8;;8A5:C=40E A 01.01.1970
ENUM_POSITION_TYPE TypePosition(void) const { return (ENUM_POSITION_TYPE)this.GetProperty(POSITION_PROP_TYPE);}// "8? ?>78F88
long Magic(void) const { return this.GetProperty(POSITION_PROP_MAGIC); } // Magic number 4;O ?>78F88 (A<>B@8 ORDER_MAGIC)
long ID(void) const { return this.GetProperty(POSITION_PROP_IDENTIFIER); } // 45=B8D8:0B>@ ?>78F88
ENUM_POSITION_REASON Reason(void) const { return (ENUM_POSITION_REASON)this.GetProperty(POSITION_PROP_REASON);}// @8G8=0 >B:@KB8O ?>78F88
datetime TimeClose(void) const { return (datetime)this.GetProperty(POSITION_PROP_TIME_CLOSE); } // @5<O 70:@KB8O
long TimeCloseMsc(void) const { return this.GetProperty(POSITION_PROP_TIME_CLOSE_MSC); } // @5<O 70:@KB8O 2 <8;;8A5:C=40E
long AccountLogin(void) const { return this.GetProperty(POSITION_PROP_ACCOUNT_LOGIN); } // >38=
//--- 5I5AB25==K5 A2>9AB20
double Volume(void) const { return this.GetProperty(POSITION_PROP_VOLUME); } // 1J5< ?>78F88
double PriceOpen(void) const { return this.GetProperty(POSITION_PROP_PRICE_OPEN); } // &5=0 ?>78F88
double SL(void) const { return this.GetProperty(POSITION_PROP_SL); } // #@>25=L Stop Loss 4;O >B:@KB>9 ?>78F88
double TP(void) const { return this.GetProperty(POSITION_PROP_TP); } // #@>25=L Take Profit 4;O >B:@KB>9 ?>78F88
double PriceCurrent(void) const { return this.GetProperty(POSITION_PROP_PRICE_CURRENT); } // "5:CI0O F5=0 ?> A8<2>;C
double Swap(void) const { return this.GetProperty(POSITION_PROP_SWAP); } // 0:>?;5==K9 A2>?
double Profit(void) const { return this.GetProperty(POSITION_PROP_PROFIT); } // "5:CI0O ?@81K;L
double ContractSize(void) const { return this.GetProperty(POSITION_PROP_CONTRACT_SIZE); } // 07<5@ B>@3>2>3> :>=B@0:B0 A8<2>;0
double PriceClose(void) const { return this.GetProperty(POSITION_PROP_PRICE_CLOSE); } // &5=0 70:@KB8O
double Commissions(void) const { return this.GetProperty(POSITION_PROP_COMMISSIONS); } // !>2>:C?=0O :><8AA8O 2A5E A45;>:
double Fee(void) const { return this.GetProperty(POSITION_PROP_FEE); } // !>2>:C?=0O >?;0B0 70 ?@>2545=85 A45;>:
//--- !B@>:>2K5 A2>9AB20
string Symbol(void) const { return this.GetProperty(POSITION_PROP_SYMBOL); } // !8<2>;, ?> :>B>@><C >B:@KB0 ?>78F8O
string Comment(void) const { return this.GetProperty(POSITION_PROP_COMMENT); } // ><<5=B0@89 : ?>78F88
string ExternalID(void) const { return this.GetProperty(POSITION_PROP_EXTERNAL_ID); } // 45=B8D8:0B>@ ?>78F88 2> 2=5H=59 A8AB5<5 (=0 18@65)
string AccountServer(void) const { return this.GetProperty(POSITION_PROP_ACCOUNT_SERVER); } // <O A5@25@0
string AccountCurrency(void) const { return this.GetProperty(POSITION_PROP_ACCOUNT_CURRENCY); } // 0;NB0 45?>78B0 0::0C=B0
string CurrencyProfit(void) const { return this.GetProperty(POSITION_PROP_CURRENCY_PROFIT); } // 0;NB0 ?@81K;8 A8<2>;0 ?>78F88
//--- >?>;=8B5;L=K5 A2>9AB20
ulong DealIn(void) const; // "8:5B A45;:8 >B:@KB8O
ulong DealOut(void) const; // "8:5B A45;:8 70:@KB8O
int ProfitInPoints(void) const; // @81K;L 2 ?C=:B0E
int SpreadIn(void) const; // !?@54 ?@8 >B:@KB88
int SpreadOut(void) const; // !?@54 ?@8 70:@KB88
double SpreadOutCost(void) const; // !B>8<>ABL A?@540 ?@8 70:@KB88
double PriceOutAsk(void) const; // &5=0 Ask ?@8 70:@KB88
double PriceOutBid(void) const; // &5=0 Bid ?@8 70:@KB88
//--- >102;O5B A45;:C 2 A?8A>: A45;>:, 2>72@0I05B C:070B5;L
CDeal *DealAdd(const long ticket);
//--- >72@0I05B >?8A0=85 B8?0 ?>78F88
string TypeDescription(void) const;
//--- >72@0I05B >?8A0=85 2@5<5=8 8 F5=K >B:@KB8O ?>78F88
string TimePriceCloseDescription(void);
//--- >72@0I05B >?8A0=85 2@5<5=8 8 F5=K 70:@KB8O ?>78F88
string TimePriceOpenDescription(void);
//--- >72@0I05B >?8A0=85 ?>78F88
string Description(void);
//--- 0A?5G0BK205B 2 6C@=0;5 A2>9AB20 ?>78F88 8 5Q A45;>:
void Print(void);
//--- !@02=8205B 420 >1J5:B0 <564C A>1>9 ?> C:070==><C 2 mode A2>9AB2C
virtual int Compare(const CObject *node, const int mode=0) const;
//--- >=AB@C:B>@/45AB@C:B>@
CPosition(const long position_id, const string symbol);
CPosition(void){}
~CPosition();
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CPosition::CPosition(const long position_id, const string symbol)
{
this.m_list_deals.Sort(DEAL_PROP_TIME_MSC);
this.SetID(position_id);
this.SetSymbol(symbol);
this.SetAccountLogin(::AccountInfoInteger(ACCOUNT_LOGIN));
this.SetAccountServer(::AccountInfoString(ACCOUNT_SERVER));
this.SetAccountCurrency(::AccountInfoString(ACCOUNT_CURRENCY));
this.SetCurrencyProfit(::SymbolInfoString(this.Symbol(),SYMBOL_CURRENCY_PROFIT));
this.SetContractSize(::SymbolInfoDouble(this.Symbol(),SYMBOL_TRADE_CONTRACT_SIZE));
this.m_digits = (int)::SymbolInfoInteger(this.Symbol(),SYMBOL_DIGITS);
this.m_point = ::SymbolInfoDouble(this.Symbol(),SYMBOL_POINT);
this.m_tick_value = ::SymbolInfoDouble(this.Symbol(), SYMBOL_TRADE_TICK_VALUE);
}
//+------------------------------------------------------------------+
//| 5AB@C:B>@ |
//+------------------------------------------------------------------+
CPosition::~CPosition()
{
this.m_list_deals.Clear();
}
//+------------------------------------------------------------------+
//| !@02=8205B 420 >1J5:B0 <564C A>1>9 ?> C:070==><C A2>9AB2C |
//+------------------------------------------------------------------+
int CPosition::Compare(const CObject *node,const int mode=0) const
{
const CPosition *obj=node;
switch(mode)
{
case POSITION_PROP_TICKET : return(this.Ticket() > obj.Ticket() ? 1 : this.Ticket() < obj.Ticket() ? -1 : 0);
case POSITION_PROP_TIME : return(this.Time() > obj.Time() ? 1 : this.Time() < obj.Time() ? -1 : 0);
case POSITION_PROP_TIME_MSC : return(this.TimeMsc() > obj.TimeMsc() ? 1 : this.TimeMsc() < obj.TimeMsc() ? -1 : 0);
case POSITION_PROP_TIME_UPDATE : return(this.TimeUpdate() > obj.TimeUpdate() ? 1 : this.TimeUpdate() < obj.TimeUpdate() ? -1 : 0);
case POSITION_PROP_TIME_UPDATE_MSC : return(this.TimeUpdateMsc() > obj.TimeUpdateMsc() ? 1 : this.TimeUpdateMsc() < obj.TimeUpdateMsc() ? -1 : 0);
case POSITION_PROP_TYPE : return(this.TypePosition() > obj.TypePosition() ? 1 : this.TypePosition() < obj.TypePosition() ? -1 : 0);
case POSITION_PROP_MAGIC : return(this.Magic() > obj.Magic() ? 1 : this.Magic() < obj.Magic() ? -1 : 0);
case POSITION_PROP_IDENTIFIER : return(this.ID() > obj.ID() ? 1 : this.ID() < obj.ID() ? -1 : 0);
case POSITION_PROP_REASON : return(this.Reason() > obj.Reason() ? 1 : this.Reason() < obj.Reason() ? -1 : 0);
case POSITION_PROP_ACCOUNT_LOGIN : return(this.AccountLogin() > obj.AccountLogin() ? 1 : this.AccountLogin() < obj.AccountLogin() ? -1 : 0);
case POSITION_PROP_TIME_CLOSE : return(this.TimeClose() > obj.TimeClose() ? 1 : this.TimeClose() < obj.TimeClose() ? -1 : 0);
case POSITION_PROP_TIME_CLOSE_MSC : return(this.TimeCloseMsc() > obj.TimeCloseMsc() ? 1 : this.TimeCloseMsc() < obj.TimeCloseMsc() ? -1 : 0);
case POSITION_PROP_VOLUME : return(this.Volume() > obj.Volume() ? 1 : this.Volume() < obj.Volume() ? -1 : 0);
case POSITION_PROP_PRICE_OPEN : return(this.PriceOpen() > obj.PriceOpen() ? 1 : this.PriceOpen() < obj.PriceOpen() ? -1 : 0);
case POSITION_PROP_SL : return(this.SL() > obj.SL() ? 1 : this.SL() < obj.SL() ? -1 : 0);
case POSITION_PROP_TP : return(this.TP() > obj.TP() ? 1 : this.TP() < obj.TP() ? -1 : 0);
case POSITION_PROP_PRICE_CURRENT : return(this.PriceCurrent() > obj.PriceCurrent() ? 1 : this.PriceCurrent() < obj.PriceCurrent() ? -1 : 0);
case POSITION_PROP_SWAP : return(this.Swap() > obj.Swap() ? 1 : this.Swap() < obj.Swap() ? -1 : 0);
case POSITION_PROP_PROFIT : return(this.Profit() > obj.Profit() ? 1 : this.Profit() < obj.Profit() ? -1 : 0);
case POSITION_PROP_CONTRACT_SIZE : return(this.ContractSize() > obj.ContractSize() ? 1 : this.ContractSize() < obj.ContractSize() ? -1 : 0);
case POSITION_PROP_PRICE_CLOSE : return(this.PriceClose() > obj.PriceClose() ? 1 : this.PriceClose() < obj.PriceClose() ? -1 : 0);
case POSITION_PROP_COMMISSIONS : return(this.Commissions() > obj.Commissions() ? 1 : this.Commissions() < obj.Commissions() ? -1 : 0);
case POSITION_PROP_FEE : return(this.Fee() > obj.Fee() ? 1 : this.Fee() < obj.Fee() ? -1 : 0);
case POSITION_PROP_SYMBOL : return(this.Symbol() > obj.Symbol() ? 1 : this.Symbol() < obj.Symbol() ? -1 : 0);
case POSITION_PROP_COMMENT : return(this.Comment() > obj.Comment() ? 1 : this.Comment() < obj.Comment() ? -1 : 0);
case POSITION_PROP_EXTERNAL_ID : return(this.ExternalID() > obj.ExternalID() ? 1 : this.ExternalID() < obj.ExternalID() ? -1 : 0);
case POSITION_PROP_CURRENCY_PROFIT : return(this.CurrencyProfit() > obj.CurrencyProfit() ? 1 : this.CurrencyProfit() < obj.CurrencyProfit() ? -1 : 0);
case POSITION_PROP_ACCOUNT_CURRENCY : return(this.AccountCurrency() > obj.AccountCurrency() ? 1 : this.AccountCurrency() < obj.AccountCurrency() ? -1 : 0);
case POSITION_PROP_ACCOUNT_SERVER : return(this.AccountServer() > obj.AccountServer() ? 1 : this.AccountServer() < obj.AccountServer() ? -1 : 0);
default : return -1;
}
}
//+------------------------------------------------------------------+
//| >72@0I05B 2@5<O A <8;;8A5:C=40<8 |
//+------------------------------------------------------------------+
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'));
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L =0 A45;:C >B:@KB8O |
//+------------------------------------------------------------------+
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;
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L =0 A45;:C 70:@KB8O |
//+------------------------------------------------------------------+
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;
}
//+------------------------------------------------------------------+
//| >72@0I05B B8:5B A45;:8 >B:@KB8O |
//+------------------------------------------------------------------+
ulong CPosition::DealIn(void) const
{
CDeal *deal=this.GetDealIn();
return(deal!=NULL ? deal.Ticket() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B B8:5B A45;:8 70:@KB8O |
//+------------------------------------------------------------------+
ulong CPosition::DealOut(void) const
{
CDeal *deal=this.GetDealOut();
return(deal!=NULL ? deal.Ticket() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B A?@54 ?@8 >B:@KB88 |
//+------------------------------------------------------------------+
int CPosition::SpreadIn(void) const
{
CDeal *deal=this.GetDealIn();
return(deal!=NULL ? deal.Spread() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B A?@54 ?@8 70:@KB88 |
//+------------------------------------------------------------------+
int CPosition::SpreadOut(void) const
{
CDeal *deal=this.GetDealOut();
return(deal!=NULL ? deal.Spread() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B F5=C Ask ?@8 70:@KB88 |
//+------------------------------------------------------------------+
double CPosition::PriceOutAsk(void) const
{
CDeal *deal=this.GetDealOut();
return(deal!=NULL ? deal.Ask() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B F5=C Bid ?@8 70:@KB88 |
//+------------------------------------------------------------------+
double CPosition::PriceOutBid(void) const
{
CDeal *deal=this.GetDealOut();
return(deal!=NULL ? deal.Bid() : 0);
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@81K;L 2 ?C=:B0E |
//+------------------------------------------------------------------+
int CPosition::ProfitInPoints(void) const
{
//--- A;8 Point A8<2>;0 =5 ?>;CG5= @0=55, A>>1I05< >1 MB>< 8 2>72@0I05< 0
if(this.m_point==0)
{
::Print("The Point() value could not be retrieved.");
return 0;
}
//--- >;CG05< F5=K >B:@KB8O 8 70:@KB8O ?>78F88
double open =this.PriceOpen();
double close=this.PriceClose();
//--- A;8 F5=K ?>;CG8BL =5 C40;>AL - 2>72@0I05< 0
if(open==0 || close==0)
return 0;
//---  7028A8<>AB8 >B B8?0 ?>78F88 2>72@0I05< @0AAG8B0==>5 7=0G5=85 ?@81K;8 ?>78F88 2 ?C=:B0E
return (int)::round(this.TypePosition()==POSITION_TYPE_BUY ? (close-open)/this.m_point : (open-close)/this.m_point);
}
//+------------------------------------------------------------------+
//| >72@0I05B AB>8<>ABL A?@540 ?@8 70:@KB88 |
//+------------------------------------------------------------------+
double CPosition::SpreadOutCost(void) const
{
//--- >;CG05< A45;:C 70:@KB8O
CDeal *deal=this.GetDealOut();
if(deal==NULL)
return 0;
//--- >;CG05< ?@>D8B ?>78F88 8 ?@>D8B ?>78F88 2 ?C=:B0E
double profit=this.Profit();
int profit_pt=this.ProfitInPoints();
//--- A;8 ?@>D8B =C;52>9 - 2>72@0I05< AB>8<>ABL A?@540 ?> D>@<C;5 TickValue * Spread * Lots
if(profit==0)
return(this.m_tick_value * deal.Spread() * deal.Volume());
//--- 0AAG8BK205< 8 2>72@0I05< AB>8<>ABL A?@540 (?@>?>@F8O)
return(profit_pt>0 ? deal.Spread() * ::fabs(profit / profit_pt) : 0);
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B A>2>:C?=CN :><8AA8N 2A5E A45;>: |
//+------------------------------------------------------------------+
void CPosition::SetCommissions(void)
{
double res=0;
int total=this.m_list_deals.Total();
for(int i=0; i<total; i++)
{
CDeal *deal=this.m_list_deals.At(i);
res+=(deal!=NULL ? deal.Commission() : 0);
}
this.SetProperty(POSITION_PROP_COMMISSIONS, res);
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B A>2>:C?=CN >?;0BC 70 ?@>2545=85 A45;>: |
//+------------------------------------------------------------------+
void CPosition::SetFee(void)
{
double res=0;
int total=this.m_list_deals.Total();
for(int i=0; i<total; i++)
{
CDeal *deal=this.m_list_deals.At(i);
res+=(deal!=NULL ? deal.Fee() : 0);
}
this.SetProperty(POSITION_PROP_FEE, res);
}
//+------------------------------------------------------------------+
//| >102;O5B A45;:C 2 A?8A>: A45;>: |
//+------------------------------------------------------------------+
CDeal *CPosition::DealAdd(const long ticket)
{
//--- #AB0=02;8205< 2@5<5==><C >1J5:BC B8:5B 8A:><>9 A45;:8 8 CAB0=02;8205< D;03 A>@B8@>2:8 A?8A:0 A45;>: ?> B8:5BC
this.m_temp_deal.SetTicket(ticket);
this.m_list_deals.Sort(DEAL_PROP_TICKET);
//--- 0?8AK205< @57C;LB0B ?@>25@:8 ?@8ACBAB28O 2 A?8A:5 A45;:8 A B0:8< B8:5B><
bool exist=(this.m_list_deals.Search(&this.m_temp_deal)!=WRONG_VALUE);
//--- >72@0I05< 4;O A?8A:0 A>@B8@>2:C ?> 2@5<5=8 2 <8;;8A5:C=40E
this.m_list_deals.Sort(DEAL_PROP_TIME_MSC);
//--- A;8 A45;:0 A B0:8< B8:5B>< C65 5ABL 2 A?8A:5 - 2>72@0I05< NULL
if(exist)
return NULL;
//--- !>740Q< =>2K9 >1J5:B-A45;:C
CDeal *deal=new CDeal(ticket);
if(deal==NULL)
return NULL;
//--- >102;O5< A>740==K9 >1J5:B 2 A?8A>: 2 ?>@O4:5 A>@B8@>2:8 ?> 2@5<5=8 2 <8;;8A5:C=40E
//--- A;8 A45;:C 4>1028BL 2 A?8A>: =5 C40;>AL - C40;O5< >1J5:B A45;:8 8 2>72@0I05< NULL
if(!this.m_list_deals.InsertSort(deal))
{
delete deal;
return NULL;
}
//--- A;8 MB> A45;:0 70:@KB8O ?>78F88 - 70?8AK205< 2 7=0G5=85 ?@81K;8 ?>78F88 ?@81K;L 8 A2>? 87 A2>9AB2 A45;:8
if(deal.Entry()==DEAL_ENTRY_OUT || deal.Entry()==DEAL_ENTRY_OUT_BY)
{
this.SetProfit(deal.Profit());
this.SetSwap(deal.Swap());
}
//--- >72@0I05< C:070B5;L =0 A>740==K9 >1J5:B-A45;:C
return deal;
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 B8?0 ?>78F88 |
//+------------------------------------------------------------------+
string CPosition::TypeDescription(void) const
{
return(this.TypePosition()==POSITION_TYPE_BUY ? "Buy" : this.TypePosition()==POSITION_TYPE_SELL ? "Sell" : "Unknown::"+(string)this.TypePosition());
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 2@5<5=8 8 F5=K >B:@KB8O ?>78F88 |
//+------------------------------------------------------------------+
string CPosition::TimePriceOpenDescription(void)
{
return(::StringFormat("Opened %s [%.*f]", this.TimeMscToString(this.TimeMsc()),this.m_digits, this.PriceOpen()));
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 2@5<5=8 8 F5=K 70:@KB8O ?>78F88 |
//+------------------------------------------------------------------+
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()));
}
//+------------------------------------------------------------------+
//| >72@0I05B :@0B:>5 >?8A0=85 ?>78F88 |
//+------------------------------------------------------------------+
string CPosition::Description(void)
{
return(::StringFormat("%I64d (%s): %s %.2f %s #%I64d, Magic %I64d", this.AccountLogin(), this.AccountServer(),
this.Symbol(), this.Volume(), this.TypeDescription(), this.ID(), this.Magic()));
}
//+------------------------------------------------------------------+
//| 0A?5G0BK205B 2 6C@=0;5 A2>9AB20 ?>78F88 8 5Q A45;>: |
//+------------------------------------------------------------------+
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();
}
}
//+------------------------------------------------------------------+