Adwizard/Virtual/VirtualReceiver.mqh

234 lines
20 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| VirtualReceiver.mqh |
//| Copyright 2022-2025, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022-2025, Yuriy Bykov"
#property link "https://www.mql5.com/ru/users/antekov"
#property version "1.04"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CVirtualSymbolReceiver;
class CVirtualInterface;
#include "../Utils/Macros.mqh"
#include "../Base/Receiver.mqh"
#include "VirtualOrder.mqh"
#include "VirtualSymbolReceiver.mqh"
#include "VirtualInterface.mqh"
//+------------------------------------------------------------------+
//| ;0AA ?5@52>40 >B:@KBKE >1J5<>2 2 @K=>G=K5 ?>78F88 (?>;CG0B5;L) |
//+------------------------------------------------------------------+
class CVirtualReceiver : public CReceiver {
protected:
// !B0B8G5A:89 C:070B5;L =0 548=AB25==K9 M:75<?;O@ 40==>3> :;0AA0
static CVirtualReceiver *s_instance;
CVirtualOrder *m_orders[]; // 0AA82 28@BC0;L=KE ?>78F89
CVirtualSymbolReceiver
*m_symbolReceivers[]; // 0AA82 ?>;CG0B5;59 4;O >B45;L=KE A8<2>;>2
CVirtualInterface
*m_interface; // 1J5:B 8=B5@D59A0 4;O ?>:070 A>AB>O=8O ?>;L7>20B5;N
//--- '0AB=K5 <5B>4K
CVirtualReceiver(); // 0:@KBK9 :>=AB@C:B>@
bool IsTradeAllowed(); // ">@3>2;O 4>ABC?=0?
public:
static datetime s_lastChangeTime; // @5<O ?>A;54=59 CA?5H=>9 :>@@5:F88
~CVirtualReceiver(); // 5AB@C:B>@
//--- !B0B8G5A:85 <5B>4K
static
CVirtualReceiver *Instance(ulong p_magic = 0); // !8=3;B>= - A>740=85 8 ?>;CG5=85 548=AB25==>3> M:75<?;O@0
static void Get(CVirtualStrategy *strategy,
CVirtualOrder *&orders[],
int n); // K45;5=85 AB@0B5388 =5>1E>48<>3> :>;8G5AB20 28@BC0;L=KE ?>78F89
//--- C1;8G=K5 <5B>4K
virtual void Changed() override;
void OnOpen(CVirtualOrder *p_order); // 1@01>B:0 >B:@KB8O 28@BC0;L=>9 ?>78F88
void OnClose(CVirtualOrder *p_order); // 1@01>B:0 70:@KB8O 28@BC0;L=>9 ?>78F88
void Tick(); // 1@01>B:0 B8:0 4;O <0AA820 28@BC0;L=KE >@45@>2 (?>78F89)
virtual bool Correct() override; // >@@5:B8@>2:0 >B:@KBKE >1JQ<>2
// ?5@0B>@ ?>;CG5=8O >1J5:B0 A8<2>;L=>3> ?>;CG0B5;O
CVirtualSymbolReceiver* operator[](const string symbol);
CVirtualOrder* Order(int i);
int OrdersTotal();
};
// =8F80;870F8O AB0B8G5A:>3> C:070B5;O =0 548=AB25==K9 M:75<?;O@ 40==>3> :;0AA0
CVirtualReceiver *CVirtualReceiver::s_instance = NULL;
datetime CVirtualReceiver::s_lastChangeTime = 0;
//+------------------------------------------------------------------+
//| 0:@KBK9 :>=AB@C:B>@ |
//+------------------------------------------------------------------+
CVirtualReceiver::CVirtualReceiver() :
m_interface(CVirtualInterface::Instance()) {
CVirtualOrder::Reset();
}
//+------------------------------------------------------------------+
//| ">@3>2;O 4>ABC?=0? |
//+------------------------------------------------------------------+
bool CVirtualReceiver::IsTradeAllowed() {
return (true
&& MQLInfoInteger(MQL_TRADE_ALLOWED)
&& TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)
&& AccountInfoInteger(ACCOUNT_TRADE_EXPERT)
&& AccountInfoInteger(ACCOUNT_TRADE_ALLOWED)
&& TerminalInfoInteger(TERMINAL_CONNECTED)
);
}
//+------------------------------------------------------------------+
//| 5AB@C:B>@ |
//+------------------------------------------------------------------+
CVirtualReceiver::~CVirtualReceiver() {
FOREACH(m_orders) delete m_orders[i]; // #40;O5< 28@BC0;L=K5 ?>78F88
FOREACH(m_symbolReceivers) delete m_symbolReceivers[i]; // #40;O5< A8<2>;L=K5 ?>;CG0B5;8
}
//+------------------------------------------------------------------+
//| !8=3;B>= - A>740=85 8 ?>;CG5=85 548=AB25==>3> M:75<?;O@0 |
//+------------------------------------------------------------------+
CVirtualReceiver* CVirtualReceiver::Instance(ulong p_magic = 0) {
if(!s_instance) {
s_instance = new CVirtualReceiver();
}
if(s_magic == 0 && p_magic != 0) {
s_magic = p_magic;
}
return s_instance;
}
//+------------------------------------------------------------------+
//| K45;5=85 AB@0B5388 =5>1E>48<>3> :>;8G5AB20 28@BC0;L=KE ?>78F89 |
//+------------------------------------------------------------------+
static void CVirtualReceiver::Get(CVirtualStrategy *strategy, // !B@0B538O
CVirtualOrder *&orders[], // 0AA82 ?>78F89 AB@0B5388
int n // "@51C5<>5 :>;8G5AB2>
) {
CVirtualReceiver *self = Instance(); // !8=3;B>= ?>;CG0B5;O
CVirtualInterface *draw = CVirtualInterface::Instance();
ArrayResize(orders, n); // 0AH8@O5< <0AA82 28@BC0;L=KE ?>78F89
FOREACH(orders) {
orders[i] = new CVirtualOrder(strategy); // 0?>;=O5< <0AA82 =>2K<8 >1J5:B0<8
APPEND(self.m_orders, orders[i]);
draw.Add(orders[i]); // 538AB@8@C5< A>740==CN 28@BC0;L=CN ?>78F8N
}
PrintFormat(__FUNCTION__ + " | OK, Strategy orders: %d from %d total",
ArraySize(orders),
ArraySize(self.m_orders));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CVirtualReceiver::Changed() {
m_isChanged = true;
FOREACH(m_symbolReceivers) m_symbolReceivers[i].Changed();
}
//+------------------------------------------------------------------+
//| 1@01>B:0 >B:@KB8O 28@BC0;L=>9 ?>78F88 |
//+------------------------------------------------------------------+
void CVirtualReceiver::OnOpen(CVirtualOrder *p_order) {
m_interface.Changed(p_order);
if(p_order.IsPendingOrder()) { // A;8 MB> 28@BC0;L=K9 >B;>65==K9 >@45@,
return; // B> =8G53> =5 45;05<
}
CVirtualSymbolReceiver* symbolReceiver = this[p_order.Symbol()];
PrintFormat(__FUNCTION__"#%s | OPEN VirtualOrder #%d", p_order.Symbol(), p_order.Id());
symbolReceiver.Open(p_order); // ?>25I05< A8<2>;L=K9 ?>;CG0B5;L > =>2>9 ?>78F88
m_isChanged = true; // 0?><=8<, GB> 87<5=5=8O 5ABL
}
//+------------------------------------------------------------------+
//| 1@01>B:0 70:@KB8O 28@BC0;L=>9 ?>78F88 |
//+------------------------------------------------------------------+
void CVirtualReceiver::OnClose(CVirtualOrder *p_order) {
m_interface.Changed(p_order);
CVirtualSymbolReceiver* symbolReceiver = this[p_order.Symbol()];
if(!!symbolReceiver) {
PrintFormat(__FUNCTION__"#%s | CLOSE VirtualOrder #%d", p_order.Symbol(), p_order.Id());
symbolReceiver.Close(p_order); // ?>25I05< A8<2>;L=K9 ?>;CG0B5;L > 70:@KB88 ?>78F88
m_isChanged = true; // 0?><=8<, GB> 87<5=5=8O 5ABL
}
}
//+------------------------------------------------------------------+
//| 1@01>B:0 B8:0 4;O <0AA820 28@BC0;L=KE >@45@>2 (?>78F89) |
//+------------------------------------------------------------------+
void CVirtualReceiver::Tick() {
FOREACH(m_orders) m_orders[i].Tick();
}
//+------------------------------------------------------------------+
//| >@@5:B8@>2:0 >B:@KBKE >1J5<>2 |
//+------------------------------------------------------------------+
bool CVirtualReceiver::Correct() {
bool res = true;
if(m_isChanged && IsTradeAllowed()) {
// A;8 5ABL 87<5=5=8O, B> 2K7K205< :>@@5:B8@>2:C ?>;CG0B5;59 >B45;L=KE A8<2>;>2
FOREACH(m_symbolReceivers) res &= m_symbolReceivers[i].Correct();
if(res) {
m_isChanged = false; // !1@0AK205< D;03 87<5=5=89
s_lastChangeTime = TimeCurrent(); // 0?><8=05< 2@5<O ?>A;54=59 CA?5H=>9 :>@@5:F88
}
}
return res;
}
//+------------------------------------------------------------------+
//| ?5@0B>@ ?>;CG5=8O >1J5:B0 A8<2>;L=>3> ?>;CG0B5;O |
//+------------------------------------------------------------------+
CVirtualSymbolReceiver* CVirtualReceiver::operator[](const string symbol) {
CVirtualSymbolReceiver* symbolReceiver = NULL;
// I5< 8=D>@<0F8>==K9 >1J5:B 4;O 40==>3> A8<2>;0 2 <0AA825
int i;
FIND(m_symbolReceivers, symbol, i);
// A;8 =0H;8, B> 2>72@0I05< 53>
if(i != -1) {
symbolReceiver = m_symbolReceivers[i];
} else {
// =0G5 A>740Q< =>2K9 8=D>@<0F8>==K9 >1J5:B
// A;8 =5 =0H;8, B> A>7405< =>2>3> ?>;CG0B5;O 4;O 40==>3> A8<2>;0
symbolReceiver = new CVirtualSymbolReceiver(symbol);
// 8 4>102;O5< 53> 2 <0AA82 A8<2>;L=KE ?>;CG0B5;59
APPEND(m_symbolReceivers, symbolReceiver);
}
return symbolReceiver;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CVirtualOrder* CVirtualReceiver::Order(int i) {
return m_orders[i];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CVirtualReceiver::OrdersTotal() {
return ArraySize(m_orders);
}
//+------------------------------------------------------------------+