588 lines
		
	
	
		
			No EOL
		
	
	
		
			41 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			588 lines
		
	
	
		
			No EOL
		
	
	
		
			41 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
#include "Orders.mqh"
 | 
						|
 | 
						|
#ifdef __MQL5__
 | 
						|
  #ifdef __MT4ORDERS__
 | 
						|
    #define MACROS_HISTORY
 | 
						|
  #endif // #ifdef __MT4ORDERS__
 | 
						|
#else //#ifdef __MQL5__
 | 
						|
  #define MACROS_HISTORY
 | 
						|
#endif // #ifdef __MQL5__ #else
 | 
						|
 | 
						|
class SNAPSHOT : public ORDERS
 | 
						|
{
 | 
						|
private:
 | 
						|
  ulong TimeData;
 | 
						|
  int PrevHistoryTotal;
 | 
						|
 | 
						|
  int PrevPositionsTotal;
 | 
						|
  int PrevOrdersTotal;
 | 
						|
 | 
						|
  MAGIC_TYPE PrevHistoryMagic;
 | 
						|
  string PrevHistorySymb;
 | 
						|
  bool PrevHistoryCloseBy;
 | 
						|
  datetime PrevHistoryFrom;
 | 
						|
 | 
						|
#ifdef __MQL5__
 | 
						|
  #ifdef __MT4ORDERS__
 | 
						|
    // Взято из MT4Orders.mqh
 | 
						|
    static bool OrderVisible( void )
 | 
						|
    {
 | 
						|
      // Если позиция закрылась при живой частично исполненной отложке, что ее породила.
 | 
						|
      // А после оставшаяся часть отложки полностью исполнилась, но не успела исчезнуть.
 | 
						|
      // То будет видна и новая позиция (правильно) и не исчезнувшая отложка (неправильно).
 | 
						|
 | 
						|
      const ulong PositionID = ::OrderGetInteger(ORDER_POSITION_ID);
 | 
						|
      const ENUM_ORDER_TYPE Type = (ENUM_ORDER_TYPE)::OrderGetInteger(ORDER_TYPE);
 | 
						|
      ulong Ticket = 0;
 | 
						|
 | 
						|
      return(!((Type == ORDER_TYPE_CLOSE_BY) ||
 | 
						|
               (PositionID && // Partial-отложенник имеет ненулевой PositionID.
 | 
						|
                (Type <= ORDER_TYPE_SELL) && // Закрывающие маркет-ордера игнорируем
 | 
						|
                ((Ticket = ::OrderGetInteger(ORDER_TICKET)) != PositionID))) && // Открывающие частично исполненные маркет-ордера не игнорируем.
 | 
						|
             // Открывающий/доливающий позицию ордер может не успеть исчезнуть.
 | 
						|
             (!::PositionsTotal() || !(::PositionSelectByTicket(Ticket ? Ticket : ::OrderGetInteger(ORDER_TICKET)) &&
 | 
						|
  //                                     (::PositionGetInteger(POSITION_TYPE) == (::OrderGetInteger(ORDER_TYPE) & 1)) &&
 | 
						|
  //                                     (::PositionGetInteger(POSITION_TIME_MSC) >= ::OrderGetInteger(ORDER_TIME_SETUP_MSC)) &&
 | 
						|
                                       (::PositionGetDouble(POSITION_VOLUME) == ::OrderGetDouble(ORDER_VOLUME_INITIAL)))));
 | 
						|
    }
 | 
						|
 | 
						|
  #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
    void SetOrders( const MAGIC_TYPE &Magic, const string &Symb, const bool &AllSymbols,
 | 
						|
                    const TICKET_TYPE &SelectTicket, const int &SelectType )
 | 
						|
  #else // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
    void SetOrders( const MAGIC_TYPE &Magic, const string &Symb, const bool &AllSymbols )
 | 
						|
  #endif // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY #else
 | 
						|
    {
 | 
						|
      static const bool IsTester = ::MQLInfoInteger(MQL_TESTER);
 | 
						|
 | 
						|
      const int StartPos2 = this.AmountOrders;
 | 
						|
 | 
						|
      int PrevTotal = -1;
 | 
						|
      int Total = ::OrdersTotal(true);
 | 
						|
 | 
						|
      int Count = 0;
 | 
						|
/*
 | 
						|
      int Index[];
 | 
						|
      ::ArrayResize(Index, ArraySize(this.Orders));
 | 
						|
*/
 | 
						|
      while (Total && (PrevTotal != Total))
 | 
						|
      {
 | 
						|
        ulong PrevTicket = 0;
 | 
						|
 | 
						|
        PrevTotal = Total;
 | 
						|
 | 
						|
        this.AmountOrders = StartPos2;
 | 
						|
 | 
						|
        for (int i = 0; i < PrevTotal; i++)
 | 
						|
        {
 | 
						|
          const ulong Ticket = ::OrderGetTicket(i);
 | 
						|
 | 
						|
          if (!IsTester && (!Ticket || (Ticket == PrevTicket) || (PrevTotal != (Total = ::OrdersTotal(true)))))
 | 
						|
          {
 | 
						|
/*
 | 
						|
            ::Print("Ticket = " + (string)Ticket);
 | 
						|
            ::Print("PrevTicket = " + (string)PrevTicket);
 | 
						|
            ::Print("PrevTotal = " + (string)PrevTotal);
 | 
						|
            ::Print("Total = " + (string)Total);
 | 
						|
            ::Print("this.AmountOrders = " + (string)this.AmountOrders);
 | 
						|
            ::Print("i = " + (string)i);
 | 
						|
            ::Print("StartPos2 = " + (string)StartPos2);
 | 
						|
*/
 | 
						|
            PrevTotal = -1;
 | 
						|
            this.AmountOrders = StartPos2;
 | 
						|
 | 
						|
            break;
 | 
						|
          }
 | 
						|
          else if (((Magic == -1) || (::OrderGetInteger(ORDER_MAGIC) == Magic)) &&
 | 
						|
                   (IsTester || SNAPSHOT::OrderVisible()) &&
 | 
						|
                   (AllSymbols || (::OrderGetString(ORDER_SYMBOL) == _Symbol)) &&
 | 
						|
                   ::OrderSelect(INT_MIN, SELECT_BY_POS))
 | 
						|
          {
 | 
						|
/*
 | 
						|
            if ((this.AmountOrders >= ::ArraySize(this.Orders)) ||
 | 
						|
                ((this.AmountOrders > StartPos2) && (Ticket == this.Orders[StartPos2].GetTicket())))
 | 
						|
            {
 | 
						|
              ::Alert(__FILE__ + ": " + (string)__LINE__ + " - this.AmountOrders >= ::ArraySize(this.Orders)");
 | 
						|
              ::Print("this.AmountOrders = " + (string)this.AmountOrders);
 | 
						|
              ::Print("::ArraySize(this.Orders) = " + (string)::ArraySize(this.Orders));
 | 
						|
              ::Print("StartPos2 = " + (string)StartPos2);
 | 
						|
              ::Print("Ticket = " + (string)Ticket);
 | 
						|
              ::Print("Count = " + (string)Count);
 | 
						|
              ::Print("i = " + (string)i);
 | 
						|
 | 
						|
              const datetime tTimeCurrent = ::TimeCurrent();
 | 
						|
 | 
						|
              for (int j = 0; j < ::ArraySize(this.Orders); j++)
 | 
						|
                ::Print(::IntegerToString(j, 2, '0') + ": " + this.Orders[j].ToString(tTimeCurrent) +
 | 
						|
                        ", Index = " + (string)Index[j] + ", NowTicket = " + (string)::OrderGetTicket(Index[j]));
 | 
						|
            }
 | 
						|
 | 
						|
            Index[this.AmountOrders] = i;
 | 
						|
*/
 | 
						|
          #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
            this.Orders[this.AmountOrders++].Copy(true); // Чтобы уменьшить тормоза работы со строками.
 | 
						|
          #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
            this.Orders[this.AmountOrders++].Copy(); // Данные MT5-ордеров не используют историю торгов в MT4Orders.
 | 
						|
          #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
 | 
						|
 | 
						|
 | 
						|
          #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
            if (SelectTicket && (this.Orders[this.AmountOrders - 1].GetTicket() == SelectTicket) &&
 | 
						|
                                (this.Orders[this.AmountOrders - 1].GetType() == SelectType))
 | 
						|
              this.SelectIndex = this.AmountOrders - 1;
 | 
						|
          #endif // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
          }
 | 
						|
 | 
						|
          PrevTicket = Ticket;
 | 
						|
        }
 | 
						|
 | 
						|
        #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
          MT4ORDERS::ByPass.Waiting();
 | 
						|
        #endif // #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
 | 
						|
        if (!IsTester)
 | 
						|
        {
 | 
						|
          Total = ::OrdersTotal(true);
 | 
						|
 | 
						|
          Count++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      this.PrevOrdersTotal = Total;
 | 
						|
 | 
						|
      if (Count > 1)
 | 
						|
        ::Alert(__FILE__ + " " + (string)__LINE__ + ": Count = " + (string)Count);
 | 
						|
    }
 | 
						|
  #endif // #ifdef __MT4ORDERS__
 | 
						|
#endif // #ifdef __MQL5__
 | 
						|
 | 
						|
#ifdef MACROS_HISTORY
 | 
						|
 | 
						|
#ifdef __TRADESID__
 | 
						|
  // TicketOrder - CloseBy-ордер, PositionID - ID-сделки, для которой ищем противоположную.
 | 
						|
  static ulong GetDealCloseBy( const ulong TicketOrder, const ulong PositionID )
 | 
						|
  {
 | 
						|
    static TRADESID SnapTradesID;
 | 
						|
 | 
						|
    ulong Res = 0;
 | 
						|
    ulong Deals[];
 | 
						|
 | 
						|
    const ulong PositionByID = ::HistoryOrderGetInteger(TicketOrder,
 | 
						|
                                                        (::HistoryOrderGetInteger(TicketOrder, ORDER_POSITION_ID) == PositionID) ? ORDER_POSITION_BY_ID
 | 
						|
                                                                                                                                 : ORDER_POSITION_ID);
 | 
						|
 | 
						|
      for (uint i = SnapTradesID.GetDealsByID(PositionByID, Deals); (bool)i--;)
 | 
						|
        if (::HistoryDealGetInteger(Deals[i], DEAL_ORDER) == TicketOrder)
 | 
						|
        {
 | 
						|
          Res = Deals[i];
 | 
						|
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
    return(Res);
 | 
						|
  }
 | 
						|
 | 
						|
  // https://www.mql5.com/ru/forum/93352/page79#comment_54482424
 | 
						|
  // Возвращает позицию тикета в таблице исторических ордеров.
 | 
						|
  static int OrderSelectPos( const long Ticket = -1 )
 | 
						|
  {
 | 
						|
  #ifdef MT4ORDERS_ORDERS_SORT
 | 
						|
    #ifdef __MQL5__
 | 
						|
      #ifdef __VIRTUAL__
 | 
						|
        if (!VIRTUAL::GetHandle())
 | 
						|
      #endif // #ifdef __VIRTUAL__
 | 
						|
 | 
						|
      return(-1);
 | 
						|
    #endif // #ifdef __MQL5__
 | 
						|
  #else // #ifdef MT4ORDERS_ORDERS_SORT
 | 
						|
    #ifdef __VIRTUAL__
 | 
						|
      if (VIRTUAL::GetHandle())
 | 
						|
        return(-1);
 | 
						|
    #endif // #ifdef __VIRTUAL__
 | 
						|
  #endif // #ifdef MT4ORDERS_ORDERS_SORT #else
 | 
						|
 | 
						|
    int Pos = -1;
 | 
						|
 | 
						|
    if (::OrderSelect(Ticket, SELECT_BY_TICKET, MODE_HISTORY) && ::OrderCloseTime())
 | 
						|
    {
 | 
						|
      static int PrevHistoryTotal2 = 0;
 | 
						|
      static CHashMap<long, int> Tickets;
 | 
						|
 | 
						|
      const long SearchTicket = (::OrderType() <= OP_SELL) ? ::OrderTicket() : -::OrderTicket();
 | 
						|
      const int Total = ::OrdersHistoryTotal();
 | 
						|
 | 
						|
      while (PrevHistoryTotal2 < Total)
 | 
						|
      {
 | 
						|
        if (::OrderSelect(PrevHistoryTotal2, SELECT_BY_POS, MODE_HISTORY))
 | 
						|
        {
 | 
						|
          const long NewTicket = (::OrderType() <= OP_SELL) ? ::OrderTicket() : -::OrderTicket();
 | 
						|
 | 
						|
          if (NewTicket == SearchTicket)
 | 
						|
            Pos = PrevHistoryTotal2;
 | 
						|
 | 
						|
          Tickets.Add(NewTicket, PrevHistoryTotal2);
 | 
						|
        }
 | 
						|
 | 
						|
        PrevHistoryTotal2++;
 | 
						|
      }
 | 
						|
 | 
						|
      if ((Pos == -1) && !Tickets.TryGetValue(SearchTicket, Pos))
 | 
						|
        Pos = -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return(Pos);
 | 
						|
  }
 | 
						|
#endif // #ifdef __TRADESID__
 | 
						|
 | 
						|
  static int GetDealTimePos( const datetime SearchTime )
 | 
						|
  {
 | 
						|
    datetime LeftTime, RightTime, PosTime;
 | 
						|
    int Left, Right, Pos = 0;
 | 
						|
 | 
						|
    Left = 0;
 | 
						|
    Right = ::HistoryDealsTotal() - 1;
 | 
						|
 | 
						|
  #ifdef __MQL5__
 | 
						|
    LeftTime = (datetime)::HistoryDealGetInteger(::HistoryDealGetTicket(Left), DEAL_TIME);
 | 
						|
    RightTime = (datetime)::HistoryDealGetInteger(::HistoryDealGetTicket(Right), DEAL_TIME);
 | 
						|
  #else // #ifdef __MQL5__
 | 
						|
    LeftTime = ::OrderSelect(Left, SELECT_BY_POS, MODE_HISTORY) ? ::OrderCloseTime() : 0;
 | 
						|
    RightTime = ::OrderSelect(Left, SELECT_BY_POS, MODE_HISTORY) ? ::OrderCloseTime() : INT_MAX;
 | 
						|
  #endif // #ifdef __MQL5__ #else
 | 
						|
 | 
						|
    if (SearchTime >= RightTime)
 | 
						|
      Pos = Right;
 | 
						|
 | 
						|
    while ((LeftTime < SearchTime) && (SearchTime < RightTime))
 | 
						|
    {
 | 
						|
      Pos = (Left + Right) >> 1;
 | 
						|
    #ifdef __MQL5__
 | 
						|
      PosTime = (datetime)::HistoryDealGetInteger(::HistoryDealGetTicket(Pos), DEAL_TIME);
 | 
						|
    #else // #ifdef __MQL5__
 | 
						|
      PosTime = ::OrderSelect(Pos, SELECT_BY_POS, MODE_HISTORY) ? ::OrderCloseTime() : LeftTime;
 | 
						|
    #endif // #ifdef __MQL5__ #else
 | 
						|
 | 
						|
      if (Pos == Left)
 | 
						|
        break;
 | 
						|
 | 
						|
      if (SearchTime >= PosTime)
 | 
						|
      {
 | 
						|
        Left = Pos;
 | 
						|
        LeftTime = PosTime;
 | 
						|
      }
 | 
						|
      else // if (SearchTime < PosTime)
 | 
						|
      {
 | 
						|
        Right = Pos;
 | 
						|
        RightTime = PosTime;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return(Pos);
 | 
						|
  }
 | 
						|
 | 
						|
  static bool SetOrder( ORDER_BASE &Order, const bool &CloseBy )
 | 
						|
  {
 | 
						|
    bool Res = Order.Copy();
 | 
						|
 | 
						|
  #ifdef __TRADESID__
 | 
						|
    if (Res && !CloseBy)
 | 
						|
    {
 | 
						|
      const ulong TicketOrder = ::HistoryDealGetInteger(::OrderTicket(), DEAL_ORDER);
 | 
						|
      const ulong DealBy = (TicketOrder && ::HistoryOrderGetInteger(TicketOrder, ORDER_TYPE) == ORDER_TYPE_CLOSE_BY)
 | 
						|
                             ? SNAPSHOT::GetDealCloseBy(TicketOrder, ::OrderTicketID())
 | 
						|
                             : 0;
 | 
						|
 | 
						|
      if (DealBy)
 | 
						|
        if (Res = ::OrderSelect(DealBy, SELECT_BY_TICKET, MODE_HISTORY) && (Order.GetOpenTimeMsc() < ::OrderOpenTimeMsc()))
 | 
						|
        {
 | 
						|
          const ulong TicketOpen = ::HistoryDealGetInteger(::OrderTicketOpen(), DEAL_ORDER);
 | 
						|
          const ENUM_ORDER_TYPE Type = (ENUM_ORDER_TYPE)::HistoryOrderGetInteger(TicketOpen, ORDER_TYPE); // Может быть среди живых.
 | 
						|
          const ENUM_DEAL_REASON Reason = (Type <= ORDER_TYPE_SELL)
 | 
						|
                                            ? DEAL_REASON_CLIENT
 | 
						|
                                            : ((Type <= ORDER_TYPE_SELL_LIMIT) ? DEAL_REASON_TP : DEAL_REASON_SL);
 | 
						|
 | 
						|
          Order.Set(Order.GetTicket(),
 | 
						|
                    (ENUM_ORDER_TYPE)Order.GetType(),
 | 
						|
                    ::MathMax(::OrderLots(), Order.GetLots()),
 | 
						|
                    ::OrderSymbol(),
 | 
						|
                    Order.GetComment(),
 | 
						|
                    Order.GetOpenPrice(),
 | 
						|
                    Order.GetOpenTimeMsc(),
 | 
						|
                    (Reason == DEAL_REASON_SL) ? ::OrderOpenPriceRequest() : Order.GetStopLoss(),
 | 
						|
                    (Reason == DEAL_REASON_TP) ? ::OrderOpenPriceRequest() : Order.GetTakeProfit(),
 | 
						|
                    ::OrderOpenPrice(),
 | 
						|
                    ::OrderOpenTimeMsc(),
 | 
						|
                    Order.GetMagicNumber(),
 | 
						|
                    ::OrderProfit() + Order.GetProfit(),
 | 
						|
                    ::OrderCommission() + Order.GetCommission(),
 | 
						|
                    ::OrderSwap() + Order.GetSwap(),
 | 
						|
                    Order.GetOpenReason(),
 | 
						|
                    Reason,
 | 
						|
                    Order.GetOpenPriceRequest(),
 | 
						|
                    ::OrderOpenPriceRequest()
 | 
						|
                    );
 | 
						|
        }
 | 
						|
    }
 | 
						|
  #endif // #ifdef __TRADESID__
 | 
						|
 | 
						|
    return(Res);
 | 
						|
  }
 | 
						|
 | 
						|
  // Symb = "" - все символы.
 | 
						|
  void SetHistoryOrders( const MAGIC_TYPE &Magic, const bool &HistoryInit, string Symb = "",
 | 
						|
                         const bool CloseBy = true, const datetime From = 0 )
 | 
						|
  {
 | 
						|
    const bool AllSymbols = (Symb == "");
 | 
						|
 | 
						|
    if (!AllSymbols && (Symb == NULL))
 | 
						|
      Symb = _Symbol;
 | 
						|
 | 
						|
    const int Total = ::OrdersHistoryTotal();
 | 
						|
 | 
						|
    const bool ChangeFlag = this.IsChangeHistory(Magic, Symb, CloseBy, From);
 | 
						|
 | 
						|
    if (HistoryInit && ChangeFlag)
 | 
						|
    {
 | 
						|
    #ifdef __MQL5__
 | 
						|
      // undeclared identifier - #include <fxsaber\TradesID\TradesID.mqh> ?
 | 
						|
      this.PrevHistoryTotal = From ? SNAPSHOT::OrderSelectPos(::HistoryDealGetTicket(SNAPSHOT::GetDealTimePos(From))) : 0;
 | 
						|
    #else // #ifdef __MQL5__
 | 
						|
      this.PrevHistoryTotal = From ? SNAPSHOT::GetDealTimePos(From) : 0;
 | 
						|
    #endif // #ifdef __MQL5__ #else
 | 
						|
 | 
						|
      this.AmountHistoryOrders = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    for (int i = this.PrevHistoryTotal; i < Total; i++)
 | 
						|
      // ::Order... - ::
 | 
						|
      if (::OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (::OrderOpenTime() >= From) &&
 | 
						|
          ((::OrderType() >= OP_BALANCE)  ||
 | 
						|
           (((Magic == -1) || (::OrderMagicNumber() == Magic)) && (AllSymbols || (::OrderSymbol() == Symb)))))
 | 
						|
      {
 | 
						|
        ORDER_BASE Order;
 | 
						|
 | 
						|
        if (SNAPSHOT::SetOrder(Order, CloseBy))
 | 
						|
          this.AddHistoryOrder(Order);
 | 
						|
      }
 | 
						|
 | 
						|
    this.PrevHistoryTotal = Total;
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  #undef MACROS_HISTORY
 | 
						|
#endif // #ifdef MACROS_HISTORY
 | 
						|
 | 
						|
  bool IsChangeHistory( const MAGIC_TYPE &Magic, const string &Symb, const bool &CloseBy, const datetime &From )
 | 
						|
  {
 | 
						|
    const bool Res =  (Magic != this.PrevHistoryMagic) || (CloseBy != this.PrevHistoryCloseBy) ||
 | 
						|
                      (From != this.PrevHistoryFrom) || (Symb != this.PrevHistorySymb);
 | 
						|
    if (Res)
 | 
						|
    {
 | 
						|
      this.PrevHistoryMagic = Magic;
 | 
						|
      this.PrevHistoryCloseBy = CloseBy;
 | 
						|
      this.PrevHistoryFrom = From;
 | 
						|
      this.PrevHistorySymb = Symb;
 | 
						|
    }
 | 
						|
 | 
						|
    return(Res);
 | 
						|
  }
 | 
						|
 | 
						|
public:
 | 
						|
  SNAPSHOT() : ORDERS(0),
 | 
						|
               TimeData(ULONG_MAX >> 1), // Половина ULONG_MAX, чтобы первый вызов SnapshotLifeTime
 | 
						|
                                         // гарантированно дал большое время (при малых GetMicrosecondCount).
 | 
						|
               PrevHistoryTotal(0), PrevPositionsTotal(-1), PrevOrdersTotal(-1),
 | 
						|
               PrevHistoryMagic(INT_MAX), PrevHistorySymb(NULL), PrevHistoryCloseBy(false), PrevHistoryFrom(INT_MAX)
 | 
						|
  {
 | 
						|
    this.SetID(__FUNCTION__);
 | 
						|
  }
 | 
						|
 | 
						|
  // Symb = "" - все символы.
 | 
						|
  ulong Snapshot( const uint &RefreshTime, const MAGIC_TYPE &Magic,
 | 
						|
                  bool HistoryInit = false, string Symb = "", const bool CloseBy = true )
 | 
						|
  {
 | 
						|
    static const bool IsTester = ::MQLInfoInteger(MQL_TESTER);
 | 
						|
 | 
						|
    if (!IsTester &&
 | 
						|
      #ifdef __MQL5__
 | 
						|
        #ifdef __MT4ORDERS__
 | 
						|
          #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
            MT4ORDERS::ByPass.Waiting() &&
 | 
						|
          #endif // #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
          (this.PrevPositionsTotal == ::PositionsTotal()) && (this.PrevOrdersTotal == ::OrdersTotal(true)) &&
 | 
						|
        #endif // #ifdef __MT4ORDERS__
 | 
						|
      #else // #ifdef __MQL5__
 | 
						|
        (this.PrevOrdersTotal == ::OrdersTotal()) &&
 | 
						|
      #endif // #ifdef __MQL5__ #else
 | 
						|
        SNAPSHOT::SnapshotLifeTime() < ::MathMin(RefreshTime, ::TerminalInfoInteger(TERMINAL_PING_LAST) >> 1))
 | 
						|
      return(0);
 | 
						|
 | 
						|
    const bool AllSymbols = IsTester || (Symb == "");
 | 
						|
 | 
						|
    if (!AllSymbols && (Symb == NULL))
 | 
						|
      Symb = _Symbol;
 | 
						|
 | 
						|
#ifdef __MQL5__
 | 
						|
  #ifdef __MT4ORDERS__
 | 
						|
    int PrevTotal = -1;
 | 
						|
    int Total = 0;
 | 
						|
    ulong StartTime = 0;
 | 
						|
 | 
						|
    int Count = 0;
 | 
						|
 | 
						|
  #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
    const TICKET_TYPE SelectTicket = (this.SelectIndex == MAX_ORDERS - 1) ? 0 : this.Orders[this.SelectIndex].GetTicket();
 | 
						|
    const int SelectType = (this.SelectIndex == MAX_ORDERS - 1) ? 0 : this.Orders[this.SelectIndex].GetType();
 | 
						|
  #endif // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
 | 
						|
    while (PrevTotal != Total)
 | 
						|
    {
 | 
						|
    #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
      this.SetHistoryOrders(Magic, HistoryInit, Symb, CloseBy);
 | 
						|
      HistoryInit = false;
 | 
						|
 | 
						|
      #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
        MT4ORDERS::ByPass.Waiting();
 | 
						|
      #endif // #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
    #endif // #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
 | 
						|
      StartTime = ::GetMicrosecondCount();
 | 
						|
 | 
						|
      this.AmountOrders = 0;
 | 
						|
      ulong PrevTicket = 0;
 | 
						|
 | 
						|
      Total = ::PositionsTotal();
 | 
						|
      PrevTotal = Total;
 | 
						|
 | 
						|
      for (int i = 0; i < PrevTotal; i++)
 | 
						|
      {
 | 
						|
        const ulong Ticket = ::PositionGetTicket(i);
 | 
						|
 | 
						|
        if (!Ticket || (Ticket == PrevTicket) || (PrevTotal != (Total = ::PositionsTotal())))
 | 
						|
        {
 | 
						|
          PrevTotal = -1;
 | 
						|
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        else if (((Magic == -1) || (::PositionGetInteger(POSITION_MAGIC) == Magic)) &&
 | 
						|
                 (AllSymbols || (::PositionGetString(POSITION_SYMBOL) == Symb)) && ::OrderSelect(INT_MAX, SELECT_BY_POS))
 | 
						|
        {
 | 
						|
      #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
          this.Orders[this.AmountOrders++].Copy(true);
 | 
						|
      #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
          this.Orders[this.AmountOrders++].Copy();
 | 
						|
      #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
 | 
						|
 | 
						|
      #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
        if (SelectTicket && (this.Orders[this.AmountOrders - 1].GetTicket() == SelectTicket))
 | 
						|
          this.SelectIndex = this.AmountOrders - 1;
 | 
						|
      #endif // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
        }
 | 
						|
 | 
						|
        PrevTicket = Ticket;
 | 
						|
      }
 | 
						|
 | 
						|
    #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
      MT4ORDERS::ByPass.Waiting();
 | 
						|
    #endif // #ifdef MT4ORDERS_BYPASS_MAXTIME
 | 
						|
 | 
						|
      if ((PrevTotal == (Total = ::PositionsTotal())))
 | 
						|
      {
 | 
						|
      #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
        this.SetOrders(Magic, Symb, AllSymbols, SelectTicket, SelectType);
 | 
						|
      #else // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY
 | 
						|
        this.SetOrders(Magic, Symb, AllSymbols);
 | 
						|
      #endif // #ifdef VIRTUAL_ORDERSELECT_WITHOUT_COPY #else
 | 
						|
 | 
						|
        Total = ::PositionsTotal();
 | 
						|
      }
 | 
						|
 | 
						|
      Count++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Count > 1)
 | 
						|
      ::Alert(__FILE__ + " " + (string)__LINE__ + ": Count = " + (string)Count);
 | 
						|
 | 
						|
    this.CurrentTick.time = ::TimeCurrent(); // Для определения длительности жизни ордеров.
 | 
						|
 | 
						|
    this.PrevPositionsTotal = Total;
 | 
						|
 | 
						|
    this.TimeData = ::GetMicrosecondCount();
 | 
						|
 | 
						|
    return(Total ? this.TimeData - StartTime : 0);
 | 
						|
  #else // #ifdef __MT4ORDERS__
 | 
						|
    return(ULONG_MAX);
 | 
						|
  #endif // #ifdef __MT4ORDERS__ #else
 | 
						|
#else // #ifdef __MQL5__
 | 
						|
    int PrevTotal = -1;
 | 
						|
    int Total = 0;
 | 
						|
    ulong StartTime = 0;
 | 
						|
 | 
						|
    while (PrevTotal != Total)
 | 
						|
    {
 | 
						|
    #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
      this.SetHistoryOrders(Magic, HistoryInit);
 | 
						|
      HistoryInit = false;
 | 
						|
    #endif // #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
 | 
						|
      StartTime = ::GetMicrosecondCount();
 | 
						|
 | 
						|
      this.AmountOrders = 0;
 | 
						|
      int PrevTicket = 0;
 | 
						|
 | 
						|
      Total = ::OrdersTotal();
 | 
						|
      PrevTotal = Total;
 | 
						|
 | 
						|
      for (int i = 0; i < PrevTotal; i++)
 | 
						|
      {
 | 
						|
        if (!::OrderSelect(i, SELECT_BY_POS) || (::OrderTicket() == PrevTicket) || (PrevTotal != (Total = ::OrdersTotal())))
 | 
						|
        {
 | 
						|
          PrevTotal = -1;
 | 
						|
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        else if (((Magic == -1) || (::OrderMagicNumber() == Magic)) && (AllSymbols || (::OrderSymbol() == Symb)))
 | 
						|
          this.Orders[this.AmountOrders++].Copy();
 | 
						|
 | 
						|
        PrevTicket = ::OrderTicket();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    this.CurrentTick.time = ::TimeCurrent(); // Для определения длительности жизни ордеров.
 | 
						|
 | 
						|
    this.PrevOrdersTotal = Total;
 | 
						|
 | 
						|
    this.TimeData = ::GetMicrosecondCount();
 | 
						|
 | 
						|
    return(Total ? this.TimeData - StartTime : 0);
 | 
						|
#endif // #ifdef __MQL5__ #else
 | 
						|
  }
 | 
						|
 | 
						|
  ulong SnapshotLifeTime( void ) const
 | 
						|
  {
 | 
						|
    static const bool IsTester = ::MQLInfoInteger(MQL_TESTER);
 | 
						|
 | 
						|
    return(IsTester ? ULONG_MAX : (::GetMicrosecondCount() - this.TimeData)); // Обязуем любой вызов снепшота в Тестере делать полноценным.
 | 
						|
  }
 | 
						|
 | 
						|
  bool SnapshotHistory( const MAGIC_TYPE Magic = -1,
 | 
						|
                        const bool HistoryInit = false, const string Symb = NULL,
 | 
						|
                        const bool CloseBy = true, const datetime From = 0 )
 | 
						|
  {
 | 
						|
  #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
    return(false);
 | 
						|
  #else // #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
 | 
						|
 | 
						|
  #ifndef __TRADESID__
 | 
						|
    if (!CloseBy)
 | 
						|
      return(false);
 | 
						|
  #endif // #ifdef __TRADESID__ #else
 | 
						|
 | 
						|
    this.SetHistoryOrders(Magic, HistoryInit, Symb, CloseBy, From); // undeclared identifier - #include <MT4Orders.mqh> ?
 | 
						|
 | 
						|
 | 
						|
    return(true);
 | 
						|
  #endif // #ifndef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
 | 
						|
  }
 | 
						|
}; |