405 lines
		
	
	
		
			No EOL
		
	
	
		
			21 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			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; |