Virtual_by_fxsaber/Include/fxsaber/Virtual/Multi_Orders.mqh

405 lines
No EOL
21 KiB
MQL5

#ifndef MAX_ORDERS
#define DELETE_MACRO_MAX_ORDERS
#define MAX_ORDERS 200
#endif // #ifndef MAX_ORDERS
#include "Orders.mqh"
class MULTI_ORDERS : public ORDERS
{
private:
static long PrevTimeMsc;
bool SwapTime1( void )
{
MULTI_ORDERS::PrevTimeMsc = this.SelectOrders.CurrentTick.time_msc;
this.SelectOrders.CurrentTick.time_msc = this.CurrentTick.time_msc;
return(true);
}
bool SwapTime2( void )
{
this.SelectOrders.CurrentTick.time_msc = MULTI_ORDERS::PrevTimeMsc;
return(true);
}
template <typename T>
static T SwapTime( const bool, const T Res, const bool )
{
return(Res);
}
void SetMaxTime( const MqlTick &Tick )
{
if (Tick.time_msc > this.CurrentTick.time_msc)
this.CurrentTick = Tick;
return;
}
int CorrectTicksTime( MqlTick &Ticks[] )
{
const int Amount = ::MathMin(this.Size, ::ArraySize(Ticks));
for (uint i = Amount; (bool)i--;)
this.SetMaxTime(Ticks[i]);
return(Amount);
}
void CalcOrders( ORDERS* &pOrders )
{
for (int i = 0; i < pOrders.AmountOrders; i++) // Не обратный - специально.
this.OrdersCounter[this.AmountOrders++].Set(pOrders, i);
return;
}
// virtual bool SelectByPos( const uint Index ) override
virtual bool SelectByPos( const int Index ) override
{
// const bool Res = /*(Index >= 0) && */(Index < (uint)this.AmountOrders) && this.OrdersCounter[Index].Select(this.SelectOrders);
const bool Res = (Index >= 0) && (Index < this.AmountOrders) && this.OrdersCounter[Index].Select(this.SelectOrders);
if (Res)
{
this.SelectOrder = this.SelectOrders.SelectOrder;
#ifdef VIRTUAL_ALTERNATIVE
this.SelectTick = this.SelectOrders.SelectTick;
#endif // #ifdef VIRTUAL_ALTERNATIVE
}
return(Res);
}
bool CheckChanges()
{
if (this.SelectOrders.IsAmountChanged())
this.CalcOrders();
if (this.SelectOrders.AmountHistoryOrders)
this.SelectOrders.MoveHistory(this);
return(true);
}
void Stop( ORDERS* &pOrders )
{
pOrders.Stop();
if (pOrders.AmountHistoryOrders)
pOrders.MoveHistory(this);
return;
}
protected:
const int Size;
ORDERS* MonoOrders[];
ORDERS* SelectOrders;
struct ORDERS_COUNTER
{
ORDERS* Orders;
int Pos;
void Set( ORDERS* pOrders, const int iPos )
{
this.Orders = pOrders;
this.Pos = iPos;
return;
}
bool Select( ORDERS* &pOrders ) const
{
const bool Res = this.Orders.SelectByPos(this.Pos);
if (Res)
pOrders = this.Orders;
return(Res);
}
} OrdersCounter[MAX_ORDERS];
bool GetOrders( const string &sSymb )
{
bool Res = (this.SelectOrders.SymbolOrders == sSymb);
for (uint i = this.Size; !Res && (bool)i--;)
if ((this.MonoOrders[i] != this.SelectOrders) && (this.MonoOrders[i].SymbolOrders == sSymb))
{
this.SelectOrders = this.MonoOrders[i];
Res = true;
}
return(Res);
}
bool GetOrders( const long &Ticket )
{
bool Res = this.SelectOrders.SelectByTicketTrades(Ticket);
if (!Res)
for (uint i = this.Size; !Res && (bool)i--;)
if (this.MonoOrders[i].SelectByTicketTrades(Ticket))
{
this.SelectOrders = this.MonoOrders[i];
Res = true;
}
return(Res);
}
void CalcOrders( void )
{
this.AmountOrders = 0;
for (uint i = this.Size; (bool)i--;)
this.CalcOrders(this.MonoOrders[i]);
return;
}
virtual bool SelectByTicketTrades( const long &Ticket ) override
{
const bool Res = this.GetOrders(Ticket);
if (Res)
{
this.SelectOrder = this.SelectOrders.SelectOrder;
#ifdef VIRTUAL_ALTERNATIVE
this.SelectTick = this.SelectOrders.SelectTick;
#endif // #ifdef VIRTUAL_ALTERNATIVE
}
return(Res);
}
public:
template <typename T>
MULTI_ORDERS( const int iHandle, const datetime StartTime, const T &sSymbols[] ) :
ORDERS(iHandle, StartTime), Size(::ArraySize(sSymbols))
{
for (uint i = ::ArrayResize(this.MonoOrders, this.Size); (bool)i--;)
this.MonoOrders[i] = new ORDERS(-(int)i, StartTime, sSymbols[i]);
this.SelectOrders = this.MonoOrders[0];
}
~MULTI_ORDERS()
{
for (uint i = this.Size; (bool)i--;)
delete this.MonoOrders[i];
this.AmountOrders = 0;
}
virtual void MultiTick( const MqlTick &Ticks[] ) override
{
bool Flag = false;
for (uint i = ::ArraySize(Ticks); (bool)i--;)
{
Flag |= this.MonoOrders[i].TickCalc(Ticks[i], this);
this.SetMaxTime(Ticks[i]);
}
if (Flag)
this.CalcOrders();
return;
}
virtual void MultiTick( void ) override
{
bool Flag = false;
for (uint i = this.Size; (bool)i--;)
{
Flag |= this.MonoOrders[i].TickCalc(this);
this.SetMaxTime(this.MonoOrders[i].CurrentTick);
}
if (Flag)
this.CalcOrders();
return;
}
virtual void MultiTick( const uint &Index, const MqlTick &Tick ) override
{
this.SelectOrders = this.MonoOrders[Index];
if (this.SelectOrders.TickCalc(Tick, this))
this.CalcOrders();
this.CurrentTick = Tick;
return;
}
virtual void MultiTick( const uint &Index ) override
{
this.SelectOrders = this.MonoOrders[Index];
if (this.SelectOrders.TickCalc(this))
this.CalcOrders();
this.CurrentTick = this.SelectOrders.CurrentTick;
return;
}
virtual bool SymbolInfoTick( const string &Symb, MqlTick &Tick ) override
{
return(this.GetOrders(Symb) && this.SelectOrders.SymbolInfoTick(Symb, Tick));
}
virtual double SymbolInfoDouble( const string &Symb, const ENUM_SYMBOL_INFO_DOUBLE Property ) override
{
return(this.GetOrders(Symb) ? this.SelectOrders.SymbolInfoDouble(Symb, Property) : 0);
}
virtual bool SymbolInfoDouble( const string &Symb, const ENUM_SYMBOL_INFO_DOUBLE Property, double &Value ) override
{
return(this.GetOrders(Symb) && this.SelectOrders.SymbolInfoDouble(Symb, Property, Value));
}
virtual long SymbolInfoInteger( const string &Symb, const ENUM_SYMBOL_INFO_INTEGER Property ) override
{
return(this.GetOrders(Symb) ? this.SelectOrders.SymbolInfoInteger(Symb, Property) : 0);
}
virtual bool SymbolInfoInteger( const string &Symb, const ENUM_SYMBOL_INFO_INTEGER Property, long &Value ) override
{
return(this.GetOrders(Symb) && this.SelectOrders.SymbolInfoInteger(Symb, Property, Value));
}
#define SWAPTIME(A) MULTI_ORDERS::SwapTime(this.SwapTime2(), A, this.SwapTime1())
virtual TICKET_TYPE OrderSend( const string &Symb, const int &Type, const double &dVolume, const double &Price,
const int &SlipPage, const double &SL, const double &TP,
const string &comment, const MAGIC_TYPE &magic, const datetime &dExpiration ) override
{
const TICKET_TYPE Res = this.GetOrders(Symb)
? SWAPTIME(this.SelectOrders.OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP,
comment, magic, dExpiration))
: -1;
if (Res != -1)
this.CheckChanges();
return(Res);
}
virtual bool OrderClose( const long Ticket, const double &dLots, const double &Price ) override
{
return(this.GetOrders(Ticket) && SWAPTIME(this.SelectOrders.OrderClose(Ticket, dLots, Price)) &&
this.CheckChanges());
}
virtual bool OrderDelete( const long Ticket ) override
{
return(this.GetOrders(Ticket) && SWAPTIME(this.SelectOrders.OrderDelete(Ticket)) &&
this.CheckChanges());
}
virtual bool OrderModify( const long Ticket, const double &Price, const double &SL, const double &TP, const datetime &Expiration ) override
{
return(this.GetOrders(Ticket) && SWAPTIME(this.SelectOrders.OrderModify(Ticket, Price, SL, TP, Expiration)) &&
this.CheckChanges());
}
virtual bool OrderCloseBy( const long Ticket, const long Opposite ) override
{
return(this.GetOrders(Ticket) && SWAPTIME(this.SelectOrders.OrderCloseBy(Ticket, Opposite)) &&
this.CheckChanges());
}
#undef SWAPTIME
virtual string OrderSymbol( void ) const override
{
return(this.SelectOrder.GetCloseTimeMsc() ? this.SelectOrder.GetSymbol()
: this.MonoOrders[this.SelectOrder.SymbolID].SymbolOrders);
}
double SumBalance( void ) const
{
double Sum = 0;
for (uint i = this.Size; (bool)i--;)
Sum += this.MonoOrders[i].Balance;
return(Sum);
}
double SumEquity( void ) const
{
double Sum = 0;
for (uint i = this.Size; (bool)i--;)
Sum += this.MonoOrders[i].AccountEquity();
return(Sum);
}
virtual double AccountBalance( void ) const override
{
return(::NormalizeDouble(this.Balance + this.SumBalance(), SYMBOL_BASE::DigitsCurrency));
}
virtual double AccountEquity( void ) override
{
return(::NormalizeDouble(this.Balance + this.SumEquity(), SYMBOL_BASE::DigitsCurrency));
}
virtual double AccountProfit( void ) override
{
return(::NormalizeDouble(this.SumEquity() - this.SumBalance(), SYMBOL_BASE::DigitsCurrency));
}
virtual bool Stop( void ) override
{
for (uint i = this.Size; (bool)i--;)
this.Stop(this.MonoOrders[i]);
this.CalcOrders();
return(true);
}
virtual int GetAmountSymbols( void ) const override
{
return(this.Size);
}
virtual int GetSymbols( string &Symbols[] ) const override
{
for (uint i = ::ArrayResize(Symbols, this.Size); (bool)i--;)
Symbols[i] = this.MonoOrders[i].SymbolOrders;
return(this.Size);
}
virtual string GetSymbolByIndex( const int &Index ) const override
{
return(((Index >= 0) && (Index < this.Size)) ? this.MonoOrders[Index].SymbolOrders : NULL);
}
virtual ORDERS* GetSubOrders( const int &Index ) override
{
return(((Index >= 0) && (Index < this.Size)) ? this.MonoOrders[Index] : NULL);
}
};
static long MULTI_ORDERS::PrevTimeMsc = 0;