forked from antekov/Adwizard
		
	
		
			
				
	
	
		
			233 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			233 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
//+------------------------------------------------------------------+
 | 
						|
//|                                              VirtualReceiver.mqh |
 | 
						|
//|                                 Copyright 2022-2025, Yuriy Bykov |
 | 
						|
//|                            https://www.mql5.com/ru/users/antekov |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
#property copyright "Copyright 2022-2025, Yuriy Bykov"
 | 
						|
#property link      "https://www.mql5.com/ru/users/antekov"
 | 
						|
#property version   "1.04"
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
class CVirtualSymbolReceiver;
 | 
						|
class CVirtualInterface;
 | 
						|
 | 
						|
#include "../Utils/Macros.mqh"
 | 
						|
#include "../Base/Receiver.mqh"
 | 
						|
#include "VirtualOrder.mqh"
 | 
						|
#include "VirtualSymbolReceiver.mqh"
 | 
						|
#include "VirtualInterface.mqh"
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Класс перевода открытых объемов в рыночные позиции (получатель)  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
class CVirtualReceiver : public CReceiver {
 | 
						|
protected:
 | 
						|
// Статический указатель на единственный экземпляр данного класса
 | 
						|
   static   CVirtualReceiver *s_instance;
 | 
						|
 | 
						|
   CVirtualOrder     *m_orders[];         // Массив виртуальных позиций
 | 
						|
 | 
						|
   CVirtualSymbolReceiver
 | 
						|
   *m_symbolReceivers[];                  // Массив получателей для отдельных символов
 | 
						|
 | 
						|
   CVirtualInterface
 | 
						|
   *m_interface;                          // Объект интерфейса для показа состояния пользователю
 | 
						|
 | 
						|
//--- Частные методы
 | 
						|
                     CVirtualReceiver();                    // Закрытый конструктор
 | 
						|
   bool              IsTradeAllowed();    // Торговля доступна?
 | 
						|
 | 
						|
public:
 | 
						|
   static   datetime          s_lastChangeTime;       // Время последней успешной коррекции
 | 
						|
 | 
						|
                    ~CVirtualReceiver();  // Деструктор
 | 
						|
 | 
						|
//--- Статические методы
 | 
						|
   static
 | 
						|
   CVirtualReceiver  *Instance(ulong p_magic = 0);    // Синглтон - создание и получение единственного экземпляра
 | 
						|
 | 
						|
   static void       Get(CVirtualStrategy *strategy,
 | 
						|
                         CVirtualOrder *&orders[],
 | 
						|
                         int n); // Выделение стратегии необходимого количества виртуальных позиций
 | 
						|
 | 
						|
//--- Публичные методы
 | 
						|
   virtual void      Changed()   override;
 | 
						|
   void              OnOpen(CVirtualOrder *p_order);  // Обработка открытия виртуальной позиции
 | 
						|
   void              OnClose(CVirtualOrder *p_order); // Обработка закрытия виртуальной позиции
 | 
						|
   void              Tick();     // Обработка тика для массива виртуальных ордеров (позиций)
 | 
						|
 | 
						|
   virtual bool      Correct() override;              // Корректировка открытых объёмов
 | 
						|
 | 
						|
   // Оператор получения объекта символьного получателя
 | 
						|
   CVirtualSymbolReceiver*      operator[](const string symbol);
 | 
						|
 | 
						|
   CVirtualOrder*    Order(int i);
 | 
						|
   int               OrdersTotal();
 | 
						|
};
 | 
						|
 | 
						|
// Инициализация статического указателя на единственный экземпляр данного класса
 | 
						|
CVirtualReceiver *CVirtualReceiver::s_instance = NULL;
 | 
						|
datetime CVirtualReceiver::s_lastChangeTime = 0;
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Закрытый конструктор                                             |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CVirtualReceiver::CVirtualReceiver() :
 | 
						|
   m_interface(CVirtualInterface::Instance()) {
 | 
						|
   CVirtualOrder::Reset();
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Торговля доступна?                                               |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
bool CVirtualReceiver::IsTradeAllowed() {
 | 
						|
   return (true
 | 
						|
           && MQLInfoInteger(MQL_TRADE_ALLOWED)
 | 
						|
           && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)
 | 
						|
           && AccountInfoInteger(ACCOUNT_TRADE_EXPERT)
 | 
						|
           && AccountInfoInteger(ACCOUNT_TRADE_ALLOWED)
 | 
						|
           && TerminalInfoInteger(TERMINAL_CONNECTED)
 | 
						|
          );
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Деструктор                                                       |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CVirtualReceiver::~CVirtualReceiver() {
 | 
						|
   FOREACH(m_orders) delete m_orders[i]; // Удаляем виртуальные позиции
 | 
						|
   FOREACH(m_symbolReceivers) delete m_symbolReceivers[i]; // Удаляем символьные получатели
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Синглтон - создание и получение единственного экземпляра         |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CVirtualReceiver* CVirtualReceiver::Instance(ulong p_magic = 0) {
 | 
						|
   if(!s_instance) {
 | 
						|
      s_instance = new CVirtualReceiver();
 | 
						|
   }
 | 
						|
   if(s_magic == 0 && p_magic != 0) {
 | 
						|
      s_magic = p_magic;
 | 
						|
   }
 | 
						|
   return s_instance;
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Выделение стратегии необходимого количества виртуальных позиций  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
static void CVirtualReceiver::Get(CVirtualStrategy *strategy,   // Стратегия
 | 
						|
                                  CVirtualOrder *&orders[],     // Массив позиций стратегии
 | 
						|
                                  int n                         // Требуемое количество
 | 
						|
                                 ) {
 | 
						|
   CVirtualReceiver *self = Instance();   // Синглтон получателя
 | 
						|
   CVirtualInterface *draw = CVirtualInterface::Instance();
 | 
						|
   ArrayResize(orders, n);                // Расширяем массив виртуальных позиций
 | 
						|
   FOREACH(orders) {
 | 
						|
      orders[i] = new CVirtualOrder(strategy); // Наполняем массив новыми объектами
 | 
						|
      APPEND(self.m_orders, orders[i]);
 | 
						|
      draw.Add(orders[i]); // Регистрируем созданную виртуальную позицию
 | 
						|
   }
 | 
						|
   PrintFormat(__FUNCTION__ + " | OK, Strategy orders: %d from %d total",
 | 
						|
               ArraySize(orders),
 | 
						|
               ArraySize(self.m_orders));
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CVirtualReceiver::Changed() {
 | 
						|
   m_isChanged = true;
 | 
						|
   FOREACH(m_symbolReceivers) m_symbolReceivers[i].Changed();
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Обработка открытия виртуальной позиции                           |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CVirtualReceiver::OnOpen(CVirtualOrder *p_order) {
 | 
						|
   m_interface.Changed(p_order);
 | 
						|
 | 
						|
   if(p_order.IsPendingOrder()) {         // Если это виртуальный отложенный ордер,
 | 
						|
      return;                             // то ничего не делаем
 | 
						|
   }
 | 
						|
 | 
						|
   CVirtualSymbolReceiver* symbolReceiver = this[p_order.Symbol()];
 | 
						|
 | 
						|
   PrintFormat(__FUNCTION__"#%s | OPEN VirtualOrder #%d", p_order.Symbol(),  p_order.Id());
 | 
						|
   symbolReceiver.Open(p_order); // Оповещаем символьный получатель о новой позиции
 | 
						|
   m_isChanged = true;           // Запомним, что изменения есть
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Обработка закрытия виртуальной позиции                           |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CVirtualReceiver::OnClose(CVirtualOrder *p_order) {
 | 
						|
   m_interface.Changed(p_order);
 | 
						|
   CVirtualSymbolReceiver* symbolReceiver = this[p_order.Symbol()];
 | 
						|
 | 
						|
   if(!!symbolReceiver) {
 | 
						|
      PrintFormat(__FUNCTION__"#%s | CLOSE VirtualOrder #%d", p_order.Symbol(),  p_order.Id());
 | 
						|
      symbolReceiver.Close(p_order);   // Оповещаем символьный получатель о закрытии позиции
 | 
						|
      m_isChanged = true;                    // Запомним, что изменения есть
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Обработка тика для массива виртуальных ордеров (позиций)         |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CVirtualReceiver::Tick() {
 | 
						|
   FOREACH(m_orders) m_orders[i].Tick();
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Корректировка открытых объемов                                   |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
bool CVirtualReceiver::Correct() {
 | 
						|
   bool res = true;
 | 
						|
   if(m_isChanged && IsTradeAllowed()) {
 | 
						|
      // Если есть изменения, то вызываем корректировку получателей отдельных символов
 | 
						|
      FOREACH(m_symbolReceivers) res &= m_symbolReceivers[i].Correct();
 | 
						|
      if(res) {
 | 
						|
         m_isChanged = false;                // Сбрасываем флаг изменений
 | 
						|
         s_lastChangeTime = TimeCurrent();   // Запоминаем время последней успешной коррекции
 | 
						|
      }
 | 
						|
   }
 | 
						|
   return res;
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Оператор получения объекта символьного получателя                |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CVirtualSymbolReceiver* CVirtualReceiver::operator[](const string symbol) {
 | 
						|
   CVirtualSymbolReceiver* symbolReceiver = NULL;
 | 
						|
// Ищем информационный объект для данного символа в массиве
 | 
						|
   int i;
 | 
						|
   FIND(m_symbolReceivers, symbol, i);
 | 
						|
 | 
						|
// Если нашли, то возвращаем его
 | 
						|
   if(i != -1) {
 | 
						|
      symbolReceiver = m_symbolReceivers[i];
 | 
						|
   } else {
 | 
						|
      // Иначе создаём новый информационный объект
 | 
						|
      // Если не нашли, то создаем нового получателя для данного символа
 | 
						|
      symbolReceiver = new CVirtualSymbolReceiver(symbol);
 | 
						|
      // и добавляем его в массив символьных получателей
 | 
						|
      APPEND(m_symbolReceivers, symbolReceiver);
 | 
						|
   }
 | 
						|
   return symbolReceiver;
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CVirtualOrder* CVirtualReceiver::Order(int i) {
 | 
						|
   return m_orders[i];
 | 
						|
}
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
int CVirtualReceiver::OrdersTotal() {
 | 
						|
   return ArraySize(m_orders);
 | 
						|
}
 | 
						|
//+------------------------------------------------------------------+
 |