Adwizard/Virtual/VirtualOrder.mqh

637 lines
49 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| VirtualOrder.mqh |
//| Copyright 2019-2025, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019-2025, Yuriy Bykov"
#property link "https://www.mql5.com/ru/users/antekov"
#property version "1.09"
#include <Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| @5420@8B5;L=K5 >?@545;5=8O :;0AA>2 |
//+------------------------------------------------------------------+
class CVirtualOrder;
class CVirtualReceiver;
class CVirtualStrategy;
#include "../Utils/SymbolsMonitor.mqh"
#include "VirtualReceiver.mqh"
#include "VirtualStrategy.mqh"
// !B@C:BC@0 4;O GB5=8O/70?8A8 87 
// >A=>2=KE A2>9AB2 28@BC0;L=>3> >@45@0/?>78F88
struct VirtualOrderStruct {
string strategyHash;
int strategyIndex;
ulong ticket;
string symbol;
double lot;
ENUM_ORDER_TYPE type;
datetime openTime;
double openPrice;
double stopLoss;
double takeProfit;
datetime closeTime;
double closePrice;
datetime expiration;
string comment;
double point;
};
//+------------------------------------------------------------------+
//| ;0AA 28@BC0;L=KE >@45@>2 8 ?>78F89 |
//+------------------------------------------------------------------+
class CVirtualOrder {
private:
//--- !B0B8G5A:85 ?>;O
static ulong s_count; // !GQBG8: 2A5E A>740==KE >1J5:B>2 CVirtualOrder
static ulong s_ticket;
CSymbolInfo *m_symbolInfo; // 1J5:B 4;O ?>;CG5=8O A2>9AB2 A8<2>;>2
//--- !2O70==K5 >1J5:BK ?>;CG0B5;O 8 AB@0B5388
CSymbolsMonitor *m_symbols;
CVirtualReceiver *m_receiver;
CVirtualStrategy *m_strategy;
//--- !2>9AB20 >@45@0 (?>78F88)
ulong m_id; // ID
ulong m_ticket; // "8:5B
string m_symbol; // !8<2>;
double m_lot; // 1J5<
ENUM_ORDER_TYPE m_type; // "8?
double m_openPrice; // &5=0 >B:@KB8O
double m_stopLoss; // #@>25=L StopLoss
double m_takeProfit; // #@>25=L TakeProfit
string m_comment; // ><<5=B0@89
datetime m_expiration; // @5<O 8AB5G5=8O
datetime m_openTime; // @5<O >B:@KB8O
//--- !2>9AB20 70:@KB>3> >@45@0 (?>78F88)
double m_closePrice; // &5=0 70:@KB8O
datetime m_closeTime; // @5<O 70:@KB8O
string m_closeReason; // @8G8=0 70:@KB8O
double m_point; // 5;8G8=0 ?C=:B0
bool m_isStopLoss; // @87=0: A@010BK20=8O StopLoss
bool m_isTakeProfit; // @87=0: A@010BK20=8O TakeProfit
bool m_isExpired; // @87=0: 8AB5G5=8O 2@5<5=8
//--- '0AB=K5 <5B>4K
bool CheckClose(); // @>25@:0 CA;>289 70:@KB8O
bool CheckTrigger(); // @>25@:0 A@010BK20=8O >B;>65==>3> >@45@0
public:
CVirtualOrder(
CVirtualStrategy *p_strategy
); // >=AB@C:B>@
~CVirtualOrder() {
if(!!m_symbolInfo) delete m_symbolInfo;
}
//--- 5B>4K ?@>25@:8 A>AB>O=8O ?>78F88 (>@45@0)
bool IsOpen() { // @45@ >B:@KB?
return(this.m_openTime > 0 && this.m_closeTime == 0);
};
bool IsClosed() { // @45@ 70:@KB?
return(this.m_openTime > 0 && this.m_closeTime > 0);
};
bool IsMarketOrder() { // -B> @K=>G=0O ?>78F8O?
return IsOpen() && (m_type == ORDER_TYPE_BUY || m_type == ORDER_TYPE_SELL);
}
bool IsPendingOrder() {// -B> >B;>65==K9 >@45@?
return IsOpen() && (m_type == ORDER_TYPE_BUY_LIMIT
|| m_type == ORDER_TYPE_BUY_STOP
|| m_type == ORDER_TYPE_SELL_LIMIT
|| m_type == ORDER_TYPE_SELL_STOP);
}
bool IsBuyOrder() { // -B> >B:@KB0O ?>78F8O BUY?
return IsOpen() && (m_type == ORDER_TYPE_BUY
|| m_type == ORDER_TYPE_BUY_LIMIT
|| m_type == ORDER_TYPE_BUY_STOP);
}
bool IsSellOrder() { // -B> >B:@KB0O ?>78F8O SELL?
return IsOpen() && (m_type == ORDER_TYPE_SELL
|| m_type == ORDER_TYPE_SELL_LIMIT
|| m_type == ORDER_TYPE_SELL_STOP);
}
bool IsStopOrder() { // -B> >B;>65==K9 STOP->@45@?
return IsOpen() && (m_type == ORDER_TYPE_BUY_STOP || m_type == ORDER_TYPE_SELL_STOP);
}
bool IsLimitOrder() { // -B> >B;>65==K9 LIMIT->@45@?
return IsOpen() && (m_type == ORDER_TYPE_BUY_LIMIT || m_type == ORDER_TYPE_SELL_LIMIT);
}
//--- 5B>4K ?>;CG5=8O A2>9AB2 ?>78F88 (>@45@0)
ulong Id() { // ID
return m_id;
}
ulong Ticket() { // "8:5B
return m_ticket;
}
CStrategy *Strategy() {
return m_strategy;
}
ENUM_ORDER_TYPE Type() {
return m_type;
}
string TypeName() {
string s = StringSubstr(EnumToString(m_type), 11);
StringReplace(s, "_", " ");
return s;
}
double Lot() {
return m_lot;
}
double Volume() { // 1J5< A =0?@02;5=85<
return IsBuyOrder() ? m_lot : (IsSellOrder() ? -m_lot : 0);
}
double Profit(); // "5:CI0O ?@81K;L
double ClosedProfit();
string Symbol() { // !8<2>;
return m_symbol;
}
double OpenPrice() {
return m_openPrice;
}
datetime OpenTime() {
return m_openTime;
}
double ClosePrice() {
return m_closePrice;
}
datetime CloseTime() {
return m_closeTime;
}
double FittedBalance() {
return m_strategy.FittedBalance();
}
double StopLoss() {
return m_stopLoss;
}
void StopLoss(double value) {
m_stopLoss = value;
}
double TakeProfit() {
return m_takeProfit;
}
void TakeProfit(double value) {
m_takeProfit = value;
}
//--- 5B>4K >1@01>B:8 ?>78F89 (>@45@>2)
bool CVirtualOrder::Open(string symbol,
ENUM_ORDER_TYPE type,
double lot,
double price,
double sl = 0,
double tp = 0,
string comment = "",
datetime expiration = 0,
bool inPoints = false); // B:@KB85 ?>78F88 (>@45@0)
void Expiration(datetime p_expiration) {
if(IsOpen()) {
m_expiration = p_expiration;
}
}
void Tick(); // 1@01>B:0 B8:0 4;O ?>78F88 (>@45@0)
void Close(); // 0:@KB85 ?>78F88 (>@45@0)
void Clear() {
m_lot = 0;
}
virtual void Load(const VirtualOrderStruct &o); // 03@C7:0 A>AB>O=8O
virtual void Save(VirtualOrderStruct &o); // !>E@0=5=85 A>AB>O=8O
static void Reset() {
s_count = 0;
}
// ABL ;8 >B:@KBK5 @K=>G=K5 28@BC0;L=K5 ?>78F88?
static bool HasMarket(CVirtualOrder* &p_orders[]);
string operator~(); // @5>1@07>20=85 >1J5:B0 2 AB@>:C
};
// =8F80;870F8O AB0B8G5A:8E ?>;59 :;0AA0
ulong CVirtualOrder::s_count = 0;
ulong CVirtualOrder::s_ticket = 0;
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CVirtualOrder::CVirtualOrder(CVirtualStrategy *p_strategy) :
// !?8A>: 8=8F80;870F88
m_id(++s_count), // >2K9 845=B8D8:0B>@ = AGQBG8: >1J5:B>2 + 1
m_ticket(0),
m_receiver(CVirtualReceiver::Instance()),
m_strategy(p_strategy),
m_symbol(""),
m_lot(0),
m_type(-1),
m_openPrice(0),
m_stopLoss(0),
m_takeProfit(0),
m_openTime(0),
m_comment(""),
m_expiration(0),
m_closePrice(0),
m_closeTime(0),
m_closeReason(""),
m_point(0) {
PrintFormat(__FUNCTION__ + "#%d | CREATED VirtualOrder", m_id);
m_symbolInfo = NULL;
m_symbols = CSymbolsMonitor::Instance();
}
//+------------------------------------------------------------------+
//| B:@KB85 28@BC0;L=>9 ?>78F88 (>@45@0) |
//+------------------------------------------------------------------+
bool CVirtualOrder::Open(string symbol, // !8<2>;
ENUM_ORDER_TYPE type, // "8? (BUY 8;8 SELL)
double lot, // 1JQ<
double price = 0, // &5=0 >B:@KB8O
double sl = 0, // #@>25=L StopLoss (F5=0 8;8 ?C=:BK)
double tp = 0, // #@>25=L TakeProfit (F5=0 8;8 ?C=:BK)
string comment = "", // ><<5=B0@89
datetime expiration = 0, // @5<O 8AB5G5=8O
bool inPoints = false // #@>2=8 SL 8 TP 7040=K 2 ?C=:B0E?
) {
if(IsOpen()) { // A;8 ?>78F8O C65 >B:@KB0, B> =8G53> =5 45;05<
PrintFormat(__FUNCTION__ "#%d | ERROR: Order is opened already!", m_id);
return false;
}
// >;CG05< >B <>=8B>@0 A8<2>;>2 C:070B5;L =0 8=D>@<0F8>==K9 >1J5:B 4;O =C6=>3> A8<2>;0
m_symbolInfo = m_symbols[symbol];
if(!!m_symbolInfo) {
//m_symbolInfo.RefreshRates(); // 1=>2;O5< 8=D>@<0F8N > B5:CI8E F5=0E
// =8F80;878@C5< A2>9AB20 ?>78F88
m_ticket = ++s_ticket;
m_openPrice = price;
m_symbol = symbol;
m_lot = lot;
m_openTime = TimeCurrent();
m_closeTime = 0;
m_type = type;
m_comment = comment;
m_expiration = expiration;
// B:@K205<0O ?>78F8O (>@45@) =5 O2;O5BAO 70:@KB>9 ?> SL, TP 8;8 8AB5G5=8N
m_isStopLoss = false;
m_isTakeProfit = false;
m_isExpired = false;
m_point = m_symbolInfo.Point();
double bid = m_symbolInfo.Bid();
double ask = m_symbolInfo.Ask();
double spread = ((ask - bid) / m_point);
//m_symbolInfo.Spread();
//  7028A8<>AB8 >B =0?@02;5=8O CAB0=02;8205< F5=C >B:@KB8O 8 C@>2=8 SL 8 TP.
// A;8 SL 8 TP 7040=K 2 ?C=:B0E, B> ?@5420@8B5;L=> 2KG8A;O5< 8E F5=>2K5 C@>2=8
// >B=>A8B5;L=> F5=K >B:@KB8O
if(IsBuyOrder()) {
if(type == ORDER_TYPE_BUY) {
m_openPrice = ask;
}
m_stopLoss = (sl > 0 ? (inPoints ? m_openPrice - sl * m_point - spread * m_point : sl) : 0);
m_takeProfit = (tp > 0 ? (inPoints ? m_openPrice + tp * m_point : tp) : 0);
} else if(IsSellOrder()) {
if(type == ORDER_TYPE_SELL) {
m_openPrice = bid;
}
m_stopLoss = (sl > 0 ? (inPoints ? m_openPrice + sl * m_point : sl) : 0);
m_takeProfit = (tp > 0 ? (inPoints ? m_openPrice - tp * m_point - spread * m_point : tp) : 0);
}
// ?>25I05< ?>;CG0B5;L 8 AB@0B538N, GB> ?>78F8O (>@45@) >B:@KB0
m_receiver.OnOpen(&this);
m_strategy.OnOpen(&this);
PrintFormat(__FUNCTION__"#%d | OPEN %s: %s %s %.2f | Price=%.5f | SL=%.5f | TP=%.5f | %s | %s",
m_id, (IsMarketOrder() ? "Market" : "Pending"), StringSubstr(EnumToString(type), 11),
m_symbol, m_lot, m_openPrice, m_stopLoss, m_takeProfit, m_comment,
(m_expiration ? TimeToString(m_expiration) : "-"));
return true;
} else {
PrintFormat(__FUNCTION__"#%d | ERROR: Can't find symbol %s for "
"OPEN %s: %s %s %.2f | Price=%.5f | SL=%.5f | TP=%.5f | %s | %s",
m_id, m_symbol, (IsMarketOrder() ? "Market" : "Pending"), StringSubstr(EnumToString(type), 11),
m_symbol, m_lot, m_openPrice, m_stopLoss, m_takeProfit, m_comment,
(m_expiration ? TimeToString(m_expiration) : "-"));
return false;
}
}
//+------------------------------------------------------------------+
//| 0:@KB85 ?>78F88 |
//+------------------------------------------------------------------+
void CVirtualOrder::Close() {
if(IsOpen()) { // A;8 ?>78F8O >B:@KB0
// ?@545;O5< ?@8G8=C 70:@KB8O 4;O 2K2>40 2 ;>3
string closeReason = "";
if(m_isStopLoss) {
closeReason += "[SL]";
} else if(m_isTakeProfit) {
closeReason += "[TP]";
} else if(m_isExpired) {
closeReason += "[EX]";
} else {
closeReason += "[CL]";
}
PrintFormat(__FUNCTION__ + "#%d | CLOSE %s: %s %s %.2f | Profit=%.2f %s | %s",
m_id, (IsMarketOrder() ? "Market" : "Pending"), StringSubstr(EnumToString(m_type), 11),
m_symbol, m_lot, Profit(), closeReason, m_comment);
m_closeTime = TimeCurrent(); // @5<O 70:@KB8O ?>78F88
// 0?><8=05< F5=C 70:@KB8O 2 7028A8<>AB8 >B B8?0
if(m_type == ORDER_TYPE_BUY) {
m_closePrice = m_symbolInfo.Bid();
} else if(m_type == ORDER_TYPE_SELL) {
m_closePrice = m_symbolInfo.Ask();
} else {
m_closePrice = 0;
}
// ?>25I05< ?>;CG0B5;L 8 AB@0B538N, GB> ?>78F8O (>@45@) 70:@KB0
m_receiver.OnClose(&this);
m_strategy.OnClose(&this);
}
}
//+------------------------------------------------------------------+
//| 0AG5B B5:CI59 ?@81K;8 ?>78F88 |
//+------------------------------------------------------------------+
double CVirtualOrder::Profit() {
double profit = 0;
if(IsMarketOrder()) { // A;8 MB> >B:@KB0O @K=>G=0O 28@BC0;L=0O ?>78F8O
//m_symbolInfo.Name(m_symbol); // K18@05< =C6=K9 A8<2>;
//m_symbolInfo.RefreshRates(); // 1=>2;O5< 8=D>@<0F8N > B5:CI8E F5=0E
// "5:CI0O F5=0, ?> :>B>@>9 <>6=> 70:@KBL ?>78F8N
double closePrice = (m_type == ORDER_TYPE_BUY) ? m_symbolInfo.Bid() : m_symbolInfo.Ask();
// @81K;L 2 2845 @07=>AB8 F5= >B:@KB8O 8 70:@KB8O
if(m_type == ORDER_TYPE_BUY) {
profit = closePrice - m_openPrice;
} else {
profit = m_openPrice - closePrice;
}
if(m_point > 1e-10) { // A;8 8725AB5= @07<5@ ?C=:B0, B>
// 5@5AG8BK205< ?@81K;L 87 @07=>AB8 F5= 2 45=56=>5 2K@065=85 4;O >1JQ<0 2 1 ;>B
if(profit > 0) {
profit = profit / m_point * m_symbolInfo.TickValueProfit();
} else {
profit = profit / m_point * m_symbolInfo.TickValueLoss();
}
} else {
PrintFormat(__FUNCTION__ + "#%d | ERROR: Point for %s is undefined", m_id, m_symbol);
m_point = m_symbolInfo.Point();
}
// 5@5AG8BK205< ?@81K;L 4;O >1JQ<0 ?>78F88
profit *= m_lot;
}
return profit;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double CVirtualOrder::ClosedProfit() {
double profit = 0;
if(IsClosed()) {
// A;8 MB> >B:@KB0O @K=>G=0O 28@BC0;L=0O ?>78F8O
//s_symbolInfo.Name(m_symbol); // K18@05< =C6=K9 A8<2>;
//s_symbolInfo.RefreshRates(); // 1=>2;O5< 8=D>@<0F8N > B5:CI8E F5=0E
// "5:CI0O F5=0, ?> :>B>@>9 <>6=> 70:@KBL ?>78F8N
double closePrice = m_closePrice;
// @81K;L 2 2845 @07=>AB8 F5= >B:@KB8O 8 70:@KB8O
if(m_type == ORDER_TYPE_BUY) {
profit = closePrice - m_openPrice;
} else if(m_type == ORDER_TYPE_SELL) {
profit = m_openPrice - closePrice;
}
if(m_point > 1e-10) { // A;8 8725AB5= @07<5@ ?C=:B0, B>
// 5@5AG8BK205< ?@81K;L 87 @07=>AB8 F5= 2 45=56=>5 2K@065=85 4;O >1JQ<0 2 1 ;>B
if(profit > 0) {
profit = profit / m_point * m_symbolInfo.TickValueProfit();
} else {
profit = profit / m_point * m_symbolInfo.TickValueLoss();
}
} else {
PrintFormat(__FUNCTION__ + "#%d | ERROR: Point for %s is undefined", m_id, m_symbol);
m_point = m_symbolInfo.Point();
}
// 5@5AG8BK205< ?@81K;L 4;O >1JQ<0 ?>78F88
profit *= m_lot;
}
return profit;
}
//+------------------------------------------------------------------+
//| @>25@:0 =5>1E>48<>AB8 70:@KB8O ?> SL, TP 8;8 EX |
//+------------------------------------------------------------------+
bool CVirtualOrder::CheckClose() {
if(IsMarketOrder()) { // A;8 MB> >B:@KB0O @K=>G=0O 28@BC0;L=0O ?>78F8O, B>
//s_symbolInfo.Name(m_symbol); // K18@05< =C6=K9 A8<2>;
//s_symbolInfo.RefreshRates(); // 1=>2;O5< 8=D>@<0F8N > B5:CI8E F5=0E
// "5:CI0O F5=0, ?> :>B>@>9 <>6=> 70:@KBL ?>78F8N
double closePrice = (m_type == ORDER_TYPE_BUY) ? m_symbolInfo.Bid() : m_symbolInfo.Ask();
//double spread = m_symbolInfo.Spread();
//double lastHigh = iHigh(m_symbol, PERIOD_M1, 1);
//double lastLow = iLow(m_symbol, PERIOD_M1, 1) + spread;
bool res = false;
// @>25@O5<, GB> F5=0 4>AB83;0 SL 8;8 TP
if(m_type == ORDER_TYPE_BUY) {
m_isStopLoss = (m_stopLoss > 0 && closePrice <= m_stopLoss);
m_isTakeProfit = (m_takeProfit > 0 && (closePrice >= m_takeProfit
//|| lastHigh >= m_takeProfit
));
} else if(m_type == ORDER_TYPE_SELL) {
m_isStopLoss = (m_stopLoss > 0 && closePrice >= m_stopLoss);
m_isTakeProfit = (m_takeProfit > 0 && (closePrice <= m_takeProfit
// || lastLow <= m_takeProfit
));
}
// K; ;8 4>AB83=CB SL 8;8 TP?
res = (m_isStopLoss || m_isTakeProfit);
if(res) {
PrintFormat(__FUNCTION__ + "#%d | %s REACHED at %.5f: %.5f | %.5f, Profit=%.2f | %s",
m_id, (m_isStopLoss ? "SL" : "TP"), closePrice, m_stopLoss, m_takeProfit,
Profit(), m_comment);
return true;
}
} else if(IsPendingOrder()) { // A;8 MB> 28@BC0;L=K9 >B;>65==K9 >@45@
// @>25@O5<, 1K;> ;8 4>AB83=CB> 2@5<O 8AB5G5=8O, 5A;8 >=> 7040=>
if(m_expiration > 0 && m_expiration < TimeCurrent()) {
m_isExpired = true;
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| 1@01>B:0 B8:0 >4=>3> 28@BC0;L=>3> >@45@0 (?>78F88) |
//+------------------------------------------------------------------+
void CVirtualOrder::Tick() {
if(IsOpen()) { // A;8 MB> >B:@KB0O 28@BC0;L=0O ?>78F8O 8;8 >@45@
if(CheckClose()) { // @>25@O5<, 4>AB83=CBK ;8 C@>2=8 SL 8;8 TP 8;8 2@5<O 8AB5G5=8O
Close(); // 0:@K205< ?@8 4>AB865=88
} else if (IsPendingOrder()) { // A;8 MB> >B;>65==K9 >@45@
CheckTrigger(); // @>25@O5< 53> A@010BK20=85
}
}
}
//+------------------------------------------------------------------+
//| @>25@:0 A@010BK20=8O >B;>65==>3> >@45@0 |
//+------------------------------------------------------------------+
bool CVirtualOrder::CheckTrigger() {
if(IsPendingOrder()) {
//m_symbolInfo.Name(m_symbol); // K18@05< =C6=K9 A8<2>;
//m_symbolInfo.RefreshRates(); // 1=>2;O5< 8=D>@<0F8N > B5:CI8E F5=0E
double bid = m_symbolInfo.Bid();
double ask = m_symbolInfo.Ask();
double spread = ((ask - bid) / m_point);
double price = (IsBuyOrder()) ? ask : bid;
// A;8 F5=0 4>H;0 4> C@>2=59 >B:@KB8O, B> ?@52@0I05< >@45@ 2 ?>78F8N
if(false
|| (m_type == ORDER_TYPE_BUY_LIMIT && price <= m_openPrice)
|| (m_type == ORDER_TYPE_BUY_STOP && price >= m_openPrice)
) {
PrintFormat(__FUNCTION__"#%d | OPEN %s at %.5f -> BUY at %.5f (Spread: %.0f)",
m_id, StringSubstr(EnumToString(m_type), 11), m_openPrice, price, spread);
m_type = ORDER_TYPE_BUY;
} else if(false
|| (m_type == ORDER_TYPE_SELL_LIMIT && price >= m_openPrice)
|| (m_type == ORDER_TYPE_SELL_STOP && price <= m_openPrice)
) {
PrintFormat(__FUNCTION__"#%d | OPEN %s at %.5f -> SELL at %.5f (Spread: %.0f)",
m_id, StringSubstr(EnumToString(m_type), 11), m_openPrice, price, spread);
m_type = ORDER_TYPE_SELL;
}
// A;8 >@45@ ?@52@0B8;AO 2 ?>78F8N
if(IsMarketOrder()) {
m_openPrice = price; // 0?><8=05< F5=C >B:@KB8O
// ?>25I05< ?>;CG0B5;L 8 AB@0B538N, GB> >B:@KB0 ?>78F8O
m_receiver.OnOpen(&this);
m_strategy.OnOpen(&this);
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| !>E@0=5=85 A>AB>O=8O |
//+------------------------------------------------------------------+
void CVirtualOrder::Save(VirtualOrderStruct &o) {
o.ticket = m_ticket;
o.symbol = m_symbol;
o.lot = m_lot;
o.type = m_type;
o.openPrice = m_openPrice;
o.stopLoss = m_stopLoss;
o.takeProfit = m_takeProfit;
o.openTime = m_openTime;
o.closePrice = m_closePrice;
o.closeTime = m_closeTime;
o.expiration = m_expiration;
o.comment = m_comment;
o.point = m_point;
}
//+------------------------------------------------------------------+
//| 03@C7:0 A>AB>O=8O |
//+------------------------------------------------------------------+
void CVirtualOrder::Load(const VirtualOrderStruct &o) {
m_ticket = o.ticket;
m_symbol = o.symbol;
m_lot = o.lot;
m_type = o.type;
m_openPrice = o.openPrice;
m_stopLoss = o.stopLoss;
m_takeProfit = o.takeProfit;
m_openTime = o.openTime;
m_closePrice = o.closePrice;
m_closeTime = o.closeTime;
m_expiration = o.expiration;
m_comment = o.comment;
m_point = o.point;
PrintFormat(__FUNCTION__" | %s", ~this);
s_ticket = MathMax(s_ticket, m_ticket);
m_symbolInfo = m_symbols[m_symbol];
// ?>25I05< ?>;CG0B5;L 8 AB@0B538N, GB> ?>78F8O (>@45@) >B:@KB0
if(IsOpen()) {
m_receiver.OnOpen(&this);
m_strategy.OnOpen(&this);
} else {
m_receiver.OnClose(&this);
m_strategy.OnClose(&this);
}
}
//+------------------------------------------------------------------+
//| ABL ;8 >B:@KBK5 @K=>G=K5 28@BC0;L=K5 ?>78F88? |
//+------------------------------------------------------------------+
bool CVirtualOrder::HasMarket(CVirtualOrder *&p_orders[]) {
FOREACH(p_orders) if (p_orders[i].IsMarketOrder()) return true;
return false;
}
//+------------------------------------------------------------------+
//| @5>1@07>20=85 >1J5:B0 2 AB@>:C |
//+------------------------------------------------------------------+
string CVirtualOrder::operator~() {
if(IsOpen()) {
return StringFormat("#%d %s %s %.2f in %s at %.5f (%.5f, %.5f). %s, %f",
m_id, TypeName(), m_symbol, m_lot,
TimeToString(m_openTime), m_openPrice,
m_stopLoss, m_takeProfit,
TimeToString(m_closeTime), m_closePrice);
} else {
return StringFormat("#%d --- ", m_id);
}
}
//+------------------------------------------------------------------+