Article-15026-MQL5-Trade-Hi.../Deal.mqh

534 lines
65 KiB
MQL5

2026-03-23 12:53:11 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Deal.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 <Object.mqh>
#include <Canvas\Canvas.mqh>
enum ENUM_DEAL_SORT_MODE
{
SORT_MODE_DEAL_TICKET = 0, // 568< A@02=5=8O/A>@B8@>2:8 ?> B8:5BC A45;:8
SORT_MODE_DEAL_ORDER, // 568< A@02=5=8O/A>@B8@>2:8 ?> >@45@C, =0 >A=>20=85 :>B>@>3> 2K?>;=5=0 A45;:0
SORT_MODE_DEAL_TIME, // 568< A@02=5=8O/A>@B8@>2:8 ?> 2@5<5=8 A>25@H5=8O A45;:8
SORT_MODE_DEAL_TIME_MSC, // 568< A@02=5=8O/A>@B8@>2:8 ?> 2@5<5=8 A>25@H5=8O A45;:8 2 <8;;8A5:C=40E
SORT_MODE_DEAL_TYPE, // 568< A@02=5=8O/A>@B8@>2:8 ?> B8?C A45;:8
SORT_MODE_DEAL_ENTRY, // 568< A@02=5=8O/A>@B8@>2:8 ?> =0?@02;5=8N A45;:8
SORT_MODE_DEAL_MAGIC, // 568< A@02=5=8O/A>@B8@>2:8 ?> Magic number A45;:8
SORT_MODE_DEAL_REASON, // 568< A@02=5=8O/A>@B8@>2:8 ?> ?@8G8=5 8;8 8AB>G=8:C ?@>2545=8O A45;:8
SORT_MODE_DEAL_POSITION_ID, // 568< A@02=5=8O/A>@B8@>2:8 ?> 845=B8D8:0B>@C ?>78F88
SORT_MODE_DEAL_VOLUME, // 568< A@02=5=8O/A>@B8@>2:8 ?> >1J5<C A45;:8
SORT_MODE_DEAL_PRICE, // 568< A@02=5=8O/A>@B8@>2:8 ?> F5=5 A45;:8
SORT_MODE_DEAL_COMMISSION, // 568< A@02=5=8O/A>@B8@>2:8 ?> :><8AA88
SORT_MODE_DEAL_SWAP, // 568< A@02=5=8O/A>@B8@>2:8 ?> =0:>?;5==><C A2>?C ?@8 70:@KB88
SORT_MODE_DEAL_PROFIT, // 568< A@02=5=8O/A>@B8@>2:8 ?> D8=0=A>2><C @57C;LB0BC A45;:8
SORT_MODE_DEAL_FEE, // 568< A@02=5=8O/A>@B8@>2:8 ?> >?;0B5 70 ?@>2545=85 A45;:8
SORT_MODE_DEAL_SL, // 568< A@02=5=8O/A>@B8@>2:8 ?> C@>2=N Stop Loss
SORT_MODE_DEAL_TP, // 568< A@02=5=8O/A>@B8@>2:8 ?> C@>2=N Take Profit
SORT_MODE_DEAL_SYMBOL, // 568< A@02=5=8O/A>@B8@>2:8 ?> 8<5=8 A8<2>;0, ?> :>B>@><C ?@>872545=0 A45;:0
SORT_MODE_DEAL_COMMENT, // 568< A@02=5=8O/A>@B8@>2:8 ?> :><<5=B0@8N : A45;:5
SORT_MODE_DEAL_EXTERNAL_ID, // 568< A@02=5=8O/A>@B8@>2:8 ?> 845=B8D8:0B>@C A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5
};
//+------------------------------------------------------------------+
//| ;0AA A45;:8 |
//+------------------------------------------------------------------+
class CDeal : public CObject
{
private:
MqlTick m_tick; // !B@C:BC@0 B8:0 A45;:8
//--- 1J5:B CCanvas
CCanvas m_canvas; // 0=20A
long m_chart_id; // 45=B8D8:0B>@ 3@0D8:0
int m_width; // (8@8=0 :0=20A0
int m_height; // KA>B0 :0=20A0
string m_name; // <O 3@0D8G5A:>3> >1J5:B0
//--- !>740QB >1J5:B-<5B:C =0 3@0D8:5
bool CreateLabelObj(void);
//--- 8AC5B =0 E>;AB5 (1) <0A:C, (2) AB@5;:C Buy
void DrawArrowMaskBuy(const int shift_x, const int shift_y);
void DrawArrowBuy(const int shift_x, const int shift_y);
//--- 8AC5B =0 E>;AB5 (1) <0A:C, (2) AB@5;:C Sell
void DrawArrowMaskSell(const int shift_x, const int shift_y);
void DrawArrowSell(const int shift_x, const int shift_y);
//--- 8AC5B 2=5H=89 284 <5B:8
void DrawLabelView(void);
//--- >;CG05B (1) B8: A45;:8, (2) A?@54 <8=CB=>3> 10@0 A45;:8
bool GetDealTick(const int amount=20);
int GetSpreadM1(void);
//--- >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;
protected:
//--- &5;>G8A;5==K5 A2>9AB20
long m_ticket; // "8:5B A45;:8. #=8:0;L=>5 G8A;>, :>B>@>5 ?@8A208205BAO :064>9 A45;:5
long m_order; // @45@, =0 >A=>20=85 :>B>@>3> 2K?>;=5=0 A45;:0
datetime m_time; // @5<O A>25@H5=8O A45;:8
long m_time_msc; // @5<O A>25@H5=8O A45;:8 2 <8;;8A5:C=40E A 01.01.1970
ENUM_DEAL_TYPE m_type; // "8? A45;:8
ENUM_DEAL_ENTRY m_entry; // 0?@02;5=85 A45;:8  2E>4 2 @K=>:, 2KE>4 87 @K=:0 8;8 @072>@>B
long m_magic; // Magic number 4;O A45;:8 (A<>B@8 ORDER_MAGIC)
ENUM_DEAL_REASON m_reason; // @8G8=0 8;8 8AB>G=8: ?@>2545=8O A45;:8
long m_position_id; // 45=B8D8:0B>@ ?>78F88, 2 >B:@KB88, 87<5=5=88 8;8 70:@KB88 :>B>@>9 CG0AB2>20;0 MB0 A45;:0
//--- 5I5AB25==K5 A2>9AB20
double m_volume; // 1J5< A45;:8
double m_price; // &5=0 A45;:8
double m_commission; // ><8AA8O ?> A45;:5
double m_swap; // 0:>?;5==K9 A2>? ?@8 70:@KB88
double m_profit; // $8=0=A>2K9 @57C;LB0B A45;:8
double m_fee; // ?;0B0 70 ?@>2545=85 A45;:8, =0G8A;O5BAO A@07C ?>A;5 A>25@H5=8O A45;:8
double m_sl; // #@>25=L Stop Loss
double m_tp; // #@>25=L Take Profit
//--- !B@>:>2K5 A2>9AB20
string m_symbol; // <O A8<2>;0, ?> :>B>@><C ?@>872545=0 A45;:0
string m_comment; // ><<5=B0@89 : A45;:5
string m_external_id; // 45=B8D8:0B>@ A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5 (=0 18@65)
//--- >?>;=8B5;L=K5 A2>9AB20
int m_digits; // Digits A8<2>;0
double m_point; // Point A8<2>;0
double m_bid; // Bid ?@8 A>25@H5=88 A45;:8
double m_ask; // Ask ?@8 A>25@H5=88 A45;:8
int m_spread; // Spread ?@8 A>25@H5=88 A45;:8
color m_color_arrow; // &25B 7=0G:0 A45;:8
//--- 8AC5B AB@5;:C, A>>B25BAB2CNICN B8?C A45;:8. >65B 1KBL ?5@5>?@545;Q= 2 =0A;54C5<KE :;0AA0E
virtual void DrawArrow(void);
public:
//--- #AB0=>2:0 A2>9AB2
//--- &5;>G8A;5==K5 A2>9AB20
void SetTicket(const long ticket) { this.m_ticket=ticket; } // "8:5B
void SetOrder(const long order) { this.m_order=order; } // @45@
void SetTime(const datetime time) { this.m_time=time; } // @5<O
void SetTimeMsc(const long value) { this.m_time_msc=value; } // @5<O 2 <8;;8A5:C=40E
void SetTypeDeal(const ENUM_DEAL_TYPE type) { this.m_type=type; } // "8?
void SetEntry(const ENUM_DEAL_ENTRY entry) { this.m_entry=entry; } // 0?@02;5=85
void SetMagic(const long magic) { this.m_magic=magic; } // Magic number
void SetReason(const ENUM_DEAL_REASON reason) { this.m_reason=reason; } // @8G8=0 8;8 8AB>G=8: ?@>2545=8O A45;:8
void SetPositionID(const long id) { this.m_position_id=id; } // 45=B8D8:0B>@ ?>78F88
//--- 5I5AB25==K5 A2>9AB20
void SetVolume(const double volume) { this.m_volume=volume; } // 1J5<
void SetPrice(const double price) { this.m_price=price; } // &5=0
void SetCommission(const double value) { this.m_commission=value; } // ><8AA8O
void SetSwap(const double value) { this.m_swap=value; } // 0:>?;5==K9 A2>? ?@8 70:@KB88
void SetProfit(const double value) { this.m_profit=value; } // $8=0=A>2K9 @57C;LB0B
void SetFee(const double value) { this.m_fee=value; } // ?;0B0 70 ?@>2545=85 A45;:8
void SetSL(const double value) { this.m_sl=value; } // #@>25=L Stop Loss
void SetTP(const double value) { this.m_tp=value; } // #@>25=L Take Profit
//--- !B@>:>2K5 A2>9AB20
void SetSymbol(const string symbol) { this.m_symbol=symbol; } // <O A8<2>;0
void SetComment(const string comment) { this.m_comment=comment; } // ><<5=B0@89
void SetExternalID(const string ext_id) { this.m_external_id=ext_id; } // 45=B8D8:0B>@ A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5
//--- >;CG5=85 A2>9AB2
//--- &5;>G8A;5==K5 A2>9AB20
long Ticket(void) const { return(this.m_ticket); } // "8:5B
long Order(void) const { return(this.m_order); } // @45@
datetime Time(void) const { return(this.m_time); } // @5<O
long TimeMsc(void) const { return(this.m_time_msc); } // @5<O 2 <8;;8A5:C=40E
ENUM_DEAL_TYPE TypeDeal(void) const { return(this.m_type); } // "8?
ENUM_DEAL_ENTRY Entry(void) const { return(this.m_entry); } // 0?@02;5=85
long Magic(void) const { return(this.m_magic); } // Magic number
ENUM_DEAL_REASON Reason(void) const { return(this.m_reason); } // @8G8=0 8;8 8AB>G=8: ?@>2545=8O A45;:8
long PositionID(void) const { return(this.m_position_id); } // 45=B8D8:0B>@ ?>78F88
//--- 5I5AB25==K5 A2>9AB20
double Volume(void) const { return(this.m_volume); } // 1J5<
double Price(void) const { return(this.m_price); } // &5=0
double Commission(void) const { return(this.m_commission); } // ><8AA8O
double Swap(void) const { return(this.m_swap); } // 0:>?;5==K9 A2>? ?@8 70:@KB88
double Profit(void) const { return(this.m_profit); } // $8=0=A>2K9 @57C;LB0B
double Fee(void) const { return(this.m_fee); } // ?;0B0 70 ?@>2545=85 A45;:8
double SL(void) const { return(this.m_sl); } // #@>25=L Stop Loss
double TP(void) const { return(this.m_tp); } // #@>25=L Take Profit
double Bid(void) const { return(this.m_bid); } // Bid ?@8 A>25@H5=88 A45;:8
double Ask(void) const { return(this.m_ask); } // Ask ?@8 A>25@H5=88 A45;:8
int Spread(void) const { return(this.m_spread); } // Spread ?@8 A>25@H5=88 A45;:8
//--- !B@>:>2K5 A2>9AB20
string Symbol(void) const { return(this.m_symbol); } // <O A8<2>;0
string Comment(void) const { return(this.m_comment); } // ><<5=B0@89
string ExternalID(void) const { return(this.m_external_id); } // 45=B8D8:0B>@ A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5
//--- #AB0=02;8205B F25B 7=0G:0 A45;:8
void SetColorArrow(const color clr);
//--- (1) !:@K205B, (2) >B>1@0605B 7=0G>: A45;:8 =0 3@0D8:5
void HideArrow(const bool chart_redraw=false);
void ShowArrow(const bool chart_redraw=false);
//--- >72@0I05B >?8A0=85 (1) B8?0 A45;:8, (2) A?>A>10 87<5=5=8O ?>78F88, (3) ?@8G8=K ?@>2545=8O A45;:8
string TypeDescription(void) const;
string EntryDescription(void) const;
string ReasonDescription(void) const;
//--- >72@0I05B (1) :@0B:>5 >?8A0=85, (2) B5:AB 2A?;K20NI53> A>>1I5=8O A45;:8
string Description(void);
virtual string Tooltip(void);
//--- 0A?5G0BK205B 2 6C@=0; A2>9AB20 A45;:8
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>@K/45AB@C:B>@
CDeal(void) { this.m_ticket=0; }
CDeal(const ulong ticket);
~CDeal();
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CDeal::CDeal(const ulong ticket)
{
//--- !>E@0=5=85 A2>9AB2
//--- &5;>G8A;5==K5 A2>9AB20
this.m_ticket = (long)ticket; // "8:5B A45;:8
this.m_order = ::HistoryDealGetInteger(ticket, DEAL_ORDER); // @45@
this.m_time = (datetime)::HistoryDealGetInteger(ticket, DEAL_TIME); // @5<O A>25@H5=8O A45;:8
this.m_time_msc = ::HistoryDealGetInteger(ticket, DEAL_TIME_MSC); // @5<O A>25@H5=8O A45;:8 2 <8;;8A5:C=40E
this.m_type = (ENUM_DEAL_TYPE)::HistoryDealGetInteger(ticket, DEAL_TYPE); // "8?
this.m_entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY); // 0?@02;5=85
this.m_magic = ::HistoryDealGetInteger(ticket, DEAL_MAGIC); // Magic number
this.m_reason = (ENUM_DEAL_REASON)::HistoryDealGetInteger(ticket, DEAL_REASON); // @8G8=0 8;8 8AB>G=8: ?@>2545=8O A45;:8
this.m_position_id= ::HistoryDealGetInteger(ticket, DEAL_POSITION_ID); // 45=B8D8:0B>@ ?>78F88
//--- 5I5AB25==K5 A2>9AB20
this.m_volume = ::HistoryDealGetDouble(ticket, DEAL_VOLUME); // 1J5<
this.m_price = ::HistoryDealGetDouble(ticket, DEAL_PRICE); // &5=0
this.m_commission = ::HistoryDealGetDouble(ticket, DEAL_COMMISSION); // ><8AA8O
this.m_swap = ::HistoryDealGetDouble(ticket, DEAL_SWAP); // 0:>?;5==K9 A2>? ?@8 70:@KB88
this.m_profit = ::HistoryDealGetDouble(ticket, DEAL_PROFIT); // $8=0=A>2K9 @57C;LB0B
this.m_fee = ::HistoryDealGetDouble(ticket, DEAL_FEE); // ?;0B0 70 ?@>2545=85 A45;:8
this.m_sl = ::HistoryDealGetDouble(ticket, DEAL_SL); // #@>25=L Stop Loss
this.m_tp = ::HistoryDealGetDouble(ticket, DEAL_TP); // #@>25=L Take Profit
//--- !B@>:>2K5 A2>9AB20
this.m_symbol = ::HistoryDealGetString(ticket, DEAL_SYMBOL); // <O A8<2>;0
this.m_comment = ::HistoryDealGetString(ticket, DEAL_COMMENT); // ><<5=B0@89
this.m_external_id= ::HistoryDealGetString(ticket, DEAL_EXTERNAL_ID); // 45=B8D8:0B>@ A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5
//--- 0@0<5B@K >B>1@065=8O 3@0D8:8
this.m_chart_id = ::ChartID();
this.m_digits = (int)::SymbolInfoInteger(this.m_symbol, SYMBOL_DIGITS);
this.m_point = ::SymbolInfoDouble(this.m_symbol, SYMBOL_POINT);
this.m_width = 19;
this.m_height = 19;
this.m_name = "Deal#"+(string)this.m_ticket;
this.m_color_arrow= (this.TypeDeal()==DEAL_TYPE_BUY ? C'3,95,172' : this.TypeDeal()==DEAL_TYPE_SELL ? C'225,68,29' : C'180,180,180');
//--- 0@0<5B@K 4;O @0AGQB0 A?@540
this.m_spread = 0;
this.m_bid = 0;
this.m_ask = 0;
//--- !>740Q< 3@0D8G5A:CN <5B:C
this.CreateLabelObj();
//--- A;8 8AB>@8G5A:89 B8: 8 7=0G5=85 Point A8<2>;0 C40;>AL ?>;CG8BL
if(this.GetDealTick() && this.m_point!=0)
{
//--- 70?8H5< 7=0G5=8O F5= Bid 8 Ask 8 @0AAG8B05< 8 A>E@0=8< 7=0G5=85 A?@540
this.m_bid=this.m_tick.bid;
this.m_ask=this.m_tick.ask;
this.m_spread=int((this.m_ask-this.m_bid)/this.m_point);
}
//--- A;8 8AB>@8G5A:89 B8: ?>;CG8BL =5 C40;>AL, 2>7L<Q< 7=0G5=85 A?@540 <8=CB=>3> 10@0, =0 :>B>@>< 1K;0 A45;:0
else
this.m_spread=this.GetSpreadM1();
}
//+------------------------------------------------------------------+
//| 5AB@C:B>@ |
//+------------------------------------------------------------------+
CDeal::~CDeal()
{
if(::UninitializeReason()!=REASON_CHARTCHANGE)
this.m_canvas.Destroy();
}
//+------------------------------------------------------------------+
//| !@02=8205B 420 >1J5:B0 <564C A>1>9 ?> C:070==><C A2>9AB2C |
//+------------------------------------------------------------------+
int CDeal::Compare(const CObject *node,const int mode=0) const