#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 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 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;