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

258 lines
21 KiB
MQL5
Raw Permalink Normal View History

2026-03-23 13:19:06 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| PositionsControl.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 "Position.mqh"
#include "Select.mqh"
//+------------------------------------------------------------------+
//| ;0AA-:>;;5:F8O 8AB>@8G5A:8E ?>78F89 |
//+------------------------------------------------------------------+
class CPositionsControl : public CObject
{
private:
//--- >72@0I05B (1) B8? ?>78F88, (2) ?@8G8=C >B:@KB8O ?> B8?C A45;:8
ENUM_POSITION_TYPE PositionTypeByDeal(const CDeal *deal);
ENUM_POSITION_REASON PositionReasonByDeal(const CDeal *deal);
protected:
CPosition m_temp_pos; // @5<5==K9 >1J5:B ?>78F88 4;O ?>8A:0
CArrayObj m_list_pos; // !?8A>: ?>78F89
//--- >72@0I05B >1J5:B-?>78F8N 87 A?8A:0 ?> 845=B8D8:0B>@C
CPosition *GetPositionObjByID(const long id);
//--- >72@0I05B D;03 B>3>, GB> ?>78F8O @K=>G=0O
bool IsMarketPosition(const long id);
public:
//--- !>740QB 8 >1=>2;O5B A?8A>: ?>78F89. >65B 1KBL ?5@5>?@545;Q= 2 =0A;54C5<KE :;0AA0E
virtual bool Refresh(void);
//--- >72@0I05B (1) A?8A>:, (2) :>;8G5AB2> ?>78F89 2 A?8A:5
CArrayObj *GetPositionsList(void) { return &this.m_list_pos; }
int PositionsTotal(void) const { return this.m_list_pos.Total(); }
//--- 0A?5G0BK205B 2 6C@=0;5 A2>9AB20 2A5E ?>78F89 2 A?8A:5 8 8E A45;>:
void Print(void);
//--- >=AB@C:B>@/45AB@C:B>@
CPositionsControl(void);
~CPositionsControl();
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CPositionsControl::CPositionsControl(void)
{
this.m_list_pos.Sort(POSITION_PROP_TIME_CLOSE_MSC);
}
//+------------------------------------------------------------------+
//| 5AB@C:B>@ |
//+------------------------------------------------------------------+
CPositionsControl::~CPositionsControl()
{
this.m_list_pos.Shutdown();
}
//+------------------------------------------------------------------+
//| >72@0I05B >1J5:B-?>78F8N 87 A?8A:0 ?> 845=B8D8:0B>@C |
//+------------------------------------------------------------------+
CPosition *CPositionsControl::GetPositionObjByID(const long id)
{
//--- #AB0=02;8205< 2@5<5==><C >1J5:BC 845=B8D8:0B>@ ?>78F88, 0 A?8A:C - D;03 A>@B8@>2:8 ?> 845=B8D8:0B>@C ?>78F88
this.m_temp_pos.SetID(id);
this.m_list_pos.Sort(POSITION_PROP_IDENTIFIER);
//--- >;CG05< 87 A?8A:0 8=45:A >1J5:B0-?>78F88 A C:070==K< 845=B8D8:0B>@>< (;81> -1 ?@8 53> >BACBAB288)
//--- > ?>;CG5==><C 8=45:AC ?>;CG05< C:070B5;L =0 >1J5:B ?>78F8N 87 A?8A:0 (;81> NULL ?@8 7=0G5=88 8=45:A0 -1)
int index=this.m_list_pos.Search(&this.m_temp_pos);
CPosition *pos=this.m_list_pos.At(index);
//--- >72@0I05< A?8A:C D;03 A>@B8@>2:8 ?> 2@5<5=8 70:@KB8O ?>78F88 2 <8;;8A5:C=40E 8
//--- 2>72@0I05< C:070B5;L =0 >1J5:B-?>78F8N (;81> NULL ?@8 53> >BACBAB288)
this.m_list_pos.Sort(POSITION_PROP_TIME_CLOSE_MSC);
return pos;
}
//+------------------------------------------------------------------+
//| >72@0I05B D;03 B>3>, GB> ?>78F8O @K=>G=0O |
//+------------------------------------------------------------------+
bool CPositionsControl::IsMarketPosition(const long id)
{
//---  F8:;5 ?> A?8A:C 459AB2CNI8E ?>78F89 2 B5@<8=0;5
for(int i=::PositionsTotal()-1; i>=0; i--)
{
//--- ?>;CG05< B8:5B ?>78F88 ?> 8=45:AC F8:;0
ulong ticket=::PositionGetTicket(i);
//--- A;8 B8:5B ?>;CG5= 8 ?>78F8N <>6=> 2K1@0BL 8 5Q 845=B8D8:0B>@ @025= ?5@540==><C 2 <5B>4 -
//--- MB> 8A:><0O @K=>G=0O ?>78F8O, 2>72@0I05< true
if(ticket!=0 && ::PositionSelectByTicket(ticket) && ::PositionGetInteger(POSITION_IDENTIFIER)==id)
return true;
}
//--- 5B B0:>9 @K=>G=>9 ?>78F88 - 2>72@0I05< false
return false;
}
//+------------------------------------------------------------------+
//| >72@0I05B B8? ?>78F88 ?> B8?C A45;:8 |
//+------------------------------------------------------------------+
ENUM_POSITION_TYPE CPositionsControl::PositionTypeByDeal(const CDeal *deal)
{
if(deal==NULL)
return WRONG_VALUE;
switch(deal.TypeDeal())
{
case DEAL_TYPE_BUY : return POSITION_TYPE_BUY;
case DEAL_TYPE_SELL : return POSITION_TYPE_SELL;
default : return WRONG_VALUE;
}
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@8G8=C >B:@KB8O ?>78F88 ?> B8?C A45;:8 |
//+------------------------------------------------------------------+
ENUM_POSITION_REASON CPositionsControl::PositionReasonByDeal(const CDeal *deal)
{
if(deal==NULL)
return WRONG_VALUE;
switch(deal.Reason())
{
case DEAL_REASON_CLIENT : return POSITION_REASON_CLIENT;
case DEAL_REASON_MOBILE : return POSITION_REASON_MOBILE;
case DEAL_REASON_WEB : return POSITION_REASON_WEB;
case DEAL_REASON_EXPERT : return POSITION_REASON_EXPERT;
default : return WRONG_VALUE;
}
}
//+------------------------------------------------------------------+
//| !>740QB A?8A>: 8AB>@8G5A:8E ?>78F89 |
//+------------------------------------------------------------------+
bool CPositionsControl::Refresh(void)
{
//--- A;8 70?@>A8BL 8AB>@8N A45;>: 8 >@45@>2 =5 C40;>AL - 2>72@0I05< false
if(!::HistorySelect(0,::TimeCurrent()))
return false;
//--- !B028< A?8A:C ?>78F89 D;03 A>@B8@>2:8 ?> 2@5<5=8 2 <8;;8A5:C=40E
this.m_list_pos.Sort(POSITION_PROP_TIME_MSC);
//--- 1JO2;O5< ?5@5<5==CN @57C;LB0B0 8 C:070B5;L =0 >1J5:B ?>78F88
bool res=true;
CPosition *pos=NULL;
//---  F8:;5 ?> :>;8G5AB2C A45;>: 8AB>@88
int total=::HistoryDealsTotal();
for(int i=total-1; i>=0; i--)
{
//--- ?>;CG05< B8:5B >G5@54=>9 A45;:8 2 A?8A:5
ulong ticket=::HistoryDealGetTicket(i);
//--- A;8 B8:5B A45;:8 =5 ?>;CG5=, 8;8 MB> =5 >?5@0F8O ?>:C?:8/?@>4068 - 84Q< 40;LH5
ENUM_DEAL_TYPE deal_type=(ENUM_DEAL_TYPE)::HistoryDealGetInteger(ticket, DEAL_TYPE);
if(ticket==0 || (deal_type!=DEAL_TYPE_BUY && deal_type!=DEAL_TYPE_SELL))
continue;
//--- >;CG05< 87 A45;:8 7=0G5=85 845=B8D8:0B>@0 ?>78F88
long pos_id=::HistoryDealGetInteger(ticket, DEAL_POSITION_ID);
//--- A;8 MB> @K=>G=0O ?>78F8O - 84Q< 40;55
if(this.IsMarketPosition(pos_id))
continue;
//--- >;CG05< C:070B5;L =0 >1J5:B-?>78F8N 87 A?8A:0
pos=this.GetPositionObjByID(pos_id);
//--- A;8 ?>78F88 A B0:8< 845=B8D8:0B>@>< 2 A?8A:5 5IQ =5B
if(pos==NULL)
{
//--- !>740Q< =>2K9 >1J5:B ?>78F88 8, 5A;8 >1J5:B A>740BL =5 C40;>AL, 4>102;O5< : ?5@5<5==>9 res 7=0G5=85 false 8 84Q< 40;55
string pos_symbol=HistoryDealGetString(ticket, DEAL_SYMBOL);
pos=new CPosition(pos_id, pos_symbol);
if(pos==NULL)
{
res &=false;
continue;
}
//--- A;8 >1J5:B ?>78F88 =5 C40;>AL 4>1028BL 2 A?8A>: - 4>102;O5< : ?5@5<5==>9 res 7=0G5=85 false, C40;O5< >1J5:B ?>78F88 8 84Q< 40;55
if(!this.m_list_pos.InsertSort(pos))
{
res &=false;
delete pos;
continue;
}
}
//--- A;8 >1J5:B A45;:8 =5 C40;>AL 4>1028BL 2 A?8A>: A45;>: >1J5:B0 ?>78F88 - 4>102;O5< : ?5@5<5==>9 res 7=0G5=85 false 8 84Q< 40;55
CDeal *deal=pos.DealAdd(ticket);
if(deal==NULL)
{
res &=false;
continue;
}
//--- AQ CA?5H=>.
//---  7028A8<>AB8 >B B8?0 A45;:8 CAB0=02;8205< A2>9AB20 ?>78F88
if(deal.Entry()==DEAL_ENTRY_IN)
{
pos.SetTicket(deal.Order());
pos.SetMagic(deal.Magic());
pos.SetTime(deal.Time());
pos.SetTimeMsc(deal.TimeMsc());
ENUM_POSITION_TYPE type=this.PositionTypeByDeal(deal);
pos.SetTypePosition(type);
ENUM_POSITION_REASON reason=this.PositionReasonByDeal(deal);
pos.SetReason(reason);
pos.SetPriceOpen(deal.Price());
pos.SetVolume(deal.Volume());
}
if(deal.Entry()==DEAL_ENTRY_OUT || deal.Entry()==DEAL_ENTRY_OUT_BY)
{
pos.SetPriceCurrent(deal.Price());
pos.SetPriceClose(deal.Price());
pos.SetTimeClose(deal.Time());
pos.SetTimeCloseMsc(deal.TimeMsc());
}
if(deal.Entry()==DEAL_ENTRY_INOUT)
{
ENUM_POSITION_TYPE type=this.PositionTypeByDeal(deal);
pos.SetTypePosition(type);
pos.SetVolume(deal.Volume()-pos.Volume());
}
}
//--- A5 8AB>@8G5A:85 ?>78F88 A>740=K, 0 A>>B25BAB2CNI85 A45;:8 4>102;5=K 2 A?8A:8 A45;>: >1J5:B>2-?>78F89
//--- #AB0=02;8205< A?8A:C ?>78F89 D;03 A>@B8@>2:8 ?> 2@5<5=8 70:@KB8O 2 <8;;8A5:C=40E
this.m_list_pos.Sort(POSITION_PROP_TIME_CLOSE_MSC);
//---  F8:;5 ?> A>740==><C A?8A:C 70:@KBKE ?>78F89 CAB0=02;8205< :064>9 ?>78F88 7=0G5=8O Commissions 8 Fee
for(int i=0; i<this.m_list_pos.Total(); i++)
{
CPosition *pos=this.m_list_pos.At(i);
if(pos==NULL)
continue;
pos.SetCommissions();
pos.SetFee();
}
//--- >72@0I05< @57C;LB0B A>740=8O 8 4>102;5=8O ?>78F88 2 A?8A>:
return res;
}
//+------------------------------------------------------------------+
//| 0A?5G0BK205B 2 6C@=0;5 A2>9AB20 ?>78F89 8 8E A45;>: |
//+------------------------------------------------------------------+
void CPositionsControl::Print(void)
{
int total=this.m_list_pos.Total();
for(int i=0; i<total; i++)
{
CPosition *pos=this.m_list_pos.At(i);
if(pos==NULL)
continue;
pos.Print();
}
}
//+------------------------------------------------------------------+