262 lines
		
	
	
		
			No EOL
		
	
	
		
			6.9 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			No EOL
		
	
	
		
			6.9 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
#include "Virtual.mqh"
 | 
						|
 | 
						|
struct MT4ORDER
 | 
						|
{
 | 
						|
  datetime OpenTime;
 | 
						|
  double OpenPrice;
 | 
						|
  double TP;
 | 
						|
  double Lots;
 | 
						|
 | 
						|
  MT4ORDER( void ) : Lots(0), TP(0)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  void Set( void )
 | 
						|
  {
 | 
						|
    this.OpenTime = OrderOpenTime();
 | 
						|
    this.OpenPrice = OrderOpenPrice();
 | 
						|
    this.TP = OrderTakeProfit();
 | 
						|
    this.Lots = OrderLots();
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  bool operator !=( const MT4ORDER &MT4Order ) const
 | 
						|
  {
 | 
						|
    return((this.OpenPrice != MT4Order.OpenPrice) || (this.TP != MT4Order.TP));
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class ISTIME
 | 
						|
{
 | 
						|
public:
 | 
						|
  static bool IsTime( const datetime time )
 | 
						|
  {
 | 
						|
    return(true);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class SYNC
 | 
						|
{
 | 
						|
private:
 | 
						|
  template <typename T>
 | 
						|
  static double GetNettingPosition( const string &Symb, const bool FlagTime = true )
 | 
						|
  {
 | 
						|
    double Res = 0;
 | 
						|
 | 
						|
  #ifdef __MQL5__
 | 
						|
    if (!VIRTUAL::GetHandle())
 | 
						|
      for (int i = ::PositionsTotal() - 1; i >= 0; i--)
 | 
						|
      {
 | 
						|
        if (::PositionGetTicket(i) && (!FlagTime || T::IsTime(::PositionGetInteger(POSITION_TIME))))
 | 
						|
        {
 | 
						|
          if (::PositionGetInteger(POSITION_TYPE))
 | 
						|
            Res -= ::PositionGetDouble(POSITION_VOLUME);
 | 
						|
          else
 | 
						|
            Res += ::PositionGetDouble(POSITION_VOLUME);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    else
 | 
						|
  #endif // #ifdef __MQL5__
 | 
						|
  {
 | 
						|
    T Tmp; // https://www.mql5.com/ru/forum/170953/page33#comment_20228971
 | 
						|
 | 
						|
    for (int i = OrdersTotal() - 1; i >= 0; i--)
 | 
						|
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!FlagTime || Tmp.IsTime(OrderOpenTime()))/* && (OrderSymbol() == Symb)*/)
 | 
						|
//      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!FlagTime || T::IsTime(OrderOpenTime()))/* && (OrderSymbol() == Symb)*/)
 | 
						|
      {
 | 
						|
        if (OrderType())
 | 
						|
          Res -= OrderLots();
 | 
						|
        else
 | 
						|
          Res += OrderLots();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
    return(Res);
 | 
						|
  }
 | 
						|
 | 
						|
  static int OrderScan( const int Type )
 | 
						|
  {
 | 
						|
    int Res = -1;
 | 
						|
 | 
						|
    for (int i = OrdersTotal() - 1; i >= 0; i--)
 | 
						|
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type)/* && (OrderSymbol() == _Symbol)*/)
 | 
						|
      {
 | 
						|
        Res = Type;
 | 
						|
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
    return(Res);
 | 
						|
  }
 | 
						|
 | 
						|
  static void CloseBy( void )
 | 
						|
  {
 | 
						|
    if (SYNC::OrderScan(OP_SELL) == OP_SELL)
 | 
						|
    {
 | 
						|
      const TICKET_TYPE SellTicket = OrderTicket();
 | 
						|
 | 
						|
      if (SYNC::OrderScan(OP_BUY) == OP_BUY)
 | 
						|
        OrderCloseBy(OrderTicket(), SellTicket);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  static void NewOrderSend( const string &Symb, const int &Type, double dLots,
 | 
						|
                            const double &Price, const int Slip, const double SL, const double TP )
 | 
						|
  {
 | 
						|
    while (dLots && (SYNC::OrderScan(1 - Type) == 1 - Type))
 | 
						|
    {
 | 
						|
      const double SelectLots = OrderLots();
 | 
						|
      const bool Flag = (SelectLots >= dLots);
 | 
						|
 | 
						|
      const double CloseLots =  Flag ? dLots : SelectLots;
 | 
						|
 | 
						|
      if (OrderClose(OrderTicket(), CloseLots, Price, Slip))
 | 
						|
      {
 | 
						|
      #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
        if (!VIRTUAL::GetHandle() && VIRTUAL::SnapshotIsActive())
 | 
						|
          VIRTUAL::Snapshot();
 | 
						|
      #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
 | 
						|
        dLots = Flag ? 0 : ::NormalizeDouble(dLots - CloseLots, 8);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (dLots)
 | 
						|
    {
 | 
						|
      OrderSend(Symb, Type, dLots, Price, Slip, SL, TP);
 | 
						|
 | 
						|
    #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
      if (!VIRTUAL::GetHandle() && VIRTUAL::SnapshotIsActive())
 | 
						|
        VIRTUAL::Snapshot();
 | 
						|
    #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
public:
 | 
						|
  template <typename T>
 | 
						|
  static void Positions( const int Handle = 0, const bool Reverse = false )
 | 
						|
  {
 | 
						|
    const int PrevHandle = VIRTUAL::GetHandle();
 | 
						|
 | 
						|
    if (Handle != PrevHandle)
 | 
						|
    {
 | 
						|
      const double PrevLots = SYNC::GetNettingPosition<T>(_Symbol);
 | 
						|
 | 
						|
      if (VIRTUAL::SelectByHandle(Handle))
 | 
						|
      {
 | 
						|
        const double NewLots = SYNC::GetNettingPosition<ISTIME>(_Symbol, false);
 | 
						|
        const double AddLots = ::NormalizeDouble(PrevLots - (Reverse ? -NewLots : NewLots), 8);
 | 
						|
 | 
						|
        if (AddLots)
 | 
						|
        {
 | 
						|
          const int TypeBuy = Reverse ? OP_SELL : OP_BUY;
 | 
						|
          const int Type = (AddLots > 0) ? TypeBuy : 1 - TypeBuy;
 | 
						|
          const double Price = ::SymbolInfoDouble(_Symbol, Type ? SYMBOL_BID : SYMBOL_ASK);
 | 
						|
 | 
						|
          SYNC::NewOrderSend(_Symbol, Type, ::MathAbs(AddLots), Price, 100, 0, 0);
 | 
						|
/*
 | 
						|
          OrderSend(_Symbol, Type, ::MathAbs(AddLots), Price, 100, 0, 0);
 | 
						|
 | 
						|
          // https://www.mql5.com/ru/forum/283611/page3#comment_9038400
 | 
						|
          if (!VIRTUAL::IsNetting())
 | 
						|
            SYNC::CloseBy(); */
 | 
						|
        }
 | 
						|
 | 
						|
        VIRTUAL::SelectByHandle(PrevHandle);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  static void NewOrderSend( const int Type, const MT4ORDER &NewLimit )
 | 
						|
  {
 | 
						|
    MT4ORDER CurrentLimit;
 | 
						|
 | 
						|
    if ((SYNC::OrderScan(Type) == Type))
 | 
						|
      CurrentLimit.Set();
 | 
						|
 | 
						|
    if (CurrentLimit.Lots != NewLimit.Lots)
 | 
						|
    {
 | 
						|
      if (CurrentLimit.Lots)
 | 
						|
        OrderDelete(OrderTicket());
 | 
						|
 | 
						|
      if (NewLimit.Lots)
 | 
						|
        OrderSend(_Symbol, Type, NewLimit.Lots, NewLimit.OpenPrice, 100, 0, NewLimit.TP);
 | 
						|
 | 
						|
    #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
      if (!VIRTUAL::GetHandle() && VIRTUAL::SnapshotIsActive())
 | 
						|
        VIRTUAL::Snapshot();
 | 
						|
    #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
    }
 | 
						|
    else if (CurrentLimit.Lots && (CurrentLimit != NewLimit))
 | 
						|
    {
 | 
						|
      OrderModify(OrderTicket(), NewLimit.OpenPrice, 0, NewLimit.TP, 0);
 | 
						|
 | 
						|
    #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
      if (!VIRTUAL::GetHandle() && VIRTUAL::SnapshotIsActive())
 | 
						|
        VIRTUAL::Snapshot();
 | 
						|
    #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename T>
 | 
						|
  static void Limits( datetime CurrentTime, const int Handle = 0 )
 | 
						|
  {
 | 
						|
    static double PrevMarketLots = 0;
 | 
						|
    static double PrevLimitLots = 0;
 | 
						|
 | 
						|
    const int PrevHandle = VIRTUAL::GetHandle();
 | 
						|
 | 
						|
    if (Handle != PrevHandle)
 | 
						|
    {
 | 
						|
      MT4ORDER BuyLimit;
 | 
						|
      MT4ORDER SellLimit;
 | 
						|
      MT4ORDER Buy;
 | 
						|
      MT4ORDER Sell;
 | 
						|
 | 
						|
      if ((SYNC::OrderScan(OP_BUYLIMIT) == OP_BUYLIMIT))
 | 
						|
        BuyLimit.Set();
 | 
						|
 | 
						|
      if (SYNC::OrderScan(OP_SELLLIMIT) == OP_SELLLIMIT)
 | 
						|
        SellLimit.Set();
 | 
						|
 | 
						|
      if ((SYNC::OrderScan(OP_BUY) == OP_BUY))
 | 
						|
        Buy.Set();
 | 
						|
      else if (SYNC::OrderScan(OP_SELL) == OP_SELL)
 | 
						|
        Sell.Set();
 | 
						|
 | 
						|
      if (BuyLimit.Lots && !T::IsTime(CurrentTime))
 | 
						|
        BuyLimit.Lots = Sell.Lots;
 | 
						|
 | 
						|
      if (BuyLimit.Lots && !T::IsTime(Sell.OpenTime))
 | 
						|
        BuyLimit.Lots -= Sell.Lots;
 | 
						|
 | 
						|
      if (SellLimit.Lots && !T::IsTime(CurrentTime))
 | 
						|
        SellLimit.Lots = Buy.Lots;
 | 
						|
 | 
						|
      if (SellLimit.Lots && !T::IsTime(Buy.OpenTime))
 | 
						|
        SellLimit.Lots -= Buy.Lots;
 | 
						|
 | 
						|
      BuyLimit.Lots = ::NormalizeDouble(BuyLimit.Lots, 8);
 | 
						|
      SellLimit.Lots = ::NormalizeDouble(SellLimit.Lots, 8);
 | 
						|
 | 
						|
      if (VIRTUAL::SelectByHandle(Handle))
 | 
						|
      {
 | 
						|
        SYNC::NewOrderSend(OP_BUYLIMIT, BuyLimit);
 | 
						|
        SYNC::NewOrderSend(OP_SELLLIMIT, SellLimit);
 | 
						|
      }
 | 
						|
 | 
						|
      VIRTUAL::SelectByHandle(PrevHandle);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
  }
 | 
						|
}; |