Автоматическое управление вкладками из робота. Semi HFT

Собственно сабж

  1. karuzzo

    Регистрация:
    16.08.19
    Сообщения:
    99
    Был на сайте:
    05.01.23

    Основная задача автоматического управления вкладками из робота это упрощение реализации арбитражных стратегий, путем использования кода управления позициями вкладкой арбитражируемого инструметна. В прочем это не мешает использовать данный подход и в прочих стратегиях, например для автоматического создания вкладок верхнего таймфрейма или обращения к данным разных способов построения чарта. Если в случае арбитража использование такого подхода - необходимость, то в случае классических стратегий лишь упрощение предварительной настройки робота перед торговлей.

    1. Реализация :

    В конструкторе робота мы подписываемся на событие создания нового сервера в классе менеджера серверов ServerMaster

    public ClassicArbitrageSemiHFT(string name, StartProgram startProgram) : base(name, startProgram)
        {
          ServerMaster.ServerCreateEvent += ServerMaster_ServerCreateEvent;
        }

    Метод реализации логики на данное событие принимает в качестве аргумента созданный сервер, а сама логика метода предполагает подписку на события созданного сервера, но мы должны использовать несколько серверов при этом их количество нам не известно, и все события на которые мы подпишемся так же должны возвращать тип сервера от которого пришло событие. Для этого мы создадим класс-событийную прослойку в который запишем тип сервера и подпишемся на события экземпляров нового класса.

    2. Реализация класса-событийной прослойки:

    public class ServerTyped
      {
          public ServerType Type;
          public IServer Server;
          public ServerConnectStatus ServerStatus;
          public bool isActive = false;
            public List<Portfolio> Portfolios;

          public ServerTyped(IServer server)
          {
              Server = server;
              Type = server.ServerType;
              SubscribeEvents();
            }

          private void SubscribeEvents()
          {
              Server.ConnectStatusChangeEvent += Serv_ConnectStatusChangeEvent;
              Server.NeadToReconnectEvent += Serv_NeadToReconnectEvent;
              Server.PortfoliosChangeEvent += Serv_PortfoliosChangeEvent;
              Server.SecuritiesChangeEvent += Serv_SecuritiesChangeEvent;
              Server.NewMyTradeEvent += Serv_NewMyTradeEvent;
              Server.NewOrderIncomeEvent += Serv_NewOrderIncomeEvent;
              Server.NewBidAscIncomeEvent += Serv_NewBidAscIncomeEvent;
              Server.ConnectStatusChangeEvent += Server_ConnectStatusChangeEvent;
            }

          private void Server_ConnectStatusChangeEvent(string obj)
          {
              ServerStatus = Server.ServerStatus;
            }

          private void Serv_NewBidAscIncomeEvent(decimal arg1, decimal arg2, Security arg3)
          {
              NewBidAscIncomeEvent(Type, arg1, arg2, arg3);
          }

          private void Serv_NewOrderIncomeEvent(Order obj)
          {
              NewOrderIncomeEvent(Type, obj);
          }

          private void Serv_NewMyTradeEvent(MyTrade obj)
          {
              NewMyTradeEvent(Type, obj);
            }

          private void Serv_SecuritiesChangeEvent(List<Security> obj)
          {
              SecuritiesChangeEvent(Type, obj);
          }

          private void Serv_PortfoliosChangeEvent(List<Portfolio> obj)
          {
              PortfoliosChangeEvent(Type, obj);
          }

          private void Serv_NeadToReconnectEvent()
          {
              NeadToReconnectEvent(Type);
          }

          private void Serv_ConnectStatusChangeEvent(string obj)
          {
              ConnectStatusChangeEvent(Type, obj);
            }

          public event Action<ServerType, decimal, decimal, Security> NewBidAscIncomeEvent;
          public event Action<ServerType, Order> NewOrderIncomeEvent;
          public event Action<ServerType, MyTrade> NewMyTradeEvent;
          public event Action<ServerType, List<Security>> SecuritiesChangeEvent;
          public event Action<ServerType, List<Portfolio>> PortfoliosChangeEvent;
          public event Action<ServerType> NeadToReconnectEvent;
            public event Action<ServerType, string> ConnectStatusChangeEvent;

          public void StopServer()
          {
              Server.StopServer();
            }

          public void StartServer()
          {
              Server.StartServer();
          }
        }

    3. Теперь когда мы имеем такой класс реализуем логику обработки события создания нового сервера из пункта 1, а так же сразу создадим список серверов и обработаем их события ориентируясь на типы серверов данных событий.

    private void ServerMaster_ServerCreateEvent(IServer server)
      {
          if (serversList != null && serversList.Count > 0)
              foreach (var serv in serversList)
                  if (serv == server)
                        return;

          serversList.Add(new ServerTyped(server) { });
          serversList.Last().ConnectStatusChangeEvent += ClassicArbitrageHFT_ConnectStatusChangeEvent;
          serversList.Last().NeadToReconnectEvent += ClassicArbitrageHFT_NeadToReconnectEvent;
      }

      private void ClassicArbitrageHFT_ConnectStatusChangeEvent(ServerType type, string obj)
      {
          foreach (var serv in serversList.Where(x => x.isActive == false && x.Type == type))
              if (serv.ServerStatus == ServerConnectStatus.Connect)
              {
                  serv.isActive = true;
                  serv.PortfoliosChangeEvent += Serv_PortfoliosChangeEvent;
                  serv.SecuritiesChangeEvent += Serv_SecuritiesChangeEvent;
                  serv.NewMyTradeEvent += Serv_NewMyTradeEvent;
                  serv.NewOrderIncomeEvent += Serv_NewOrderIncomeEvent;
                  serv.NewBidAscIncomeEvent += Serv_NewBidAscIncomeEvent;
              }
        }

      private void ClassicArbitrageHFT_NeadToReconnectEvent(ServerType type)
      {
          foreach (var serv in serversList.Where(x => x.Type == type))
          {
              serv.StopServer();
              serv.StartServer();
          }
        }

    Сами события обрабатываются согласно логике вашей стратегии, но все из них уже принимают в качестве параметра тип сервера на котором сработало событие.

    4. Создание вкладки и управление ее параметрами из робота. На одном или нескольких событий сервера могут быть соблюдены условия создания или изменения вкладки. Для этого мы применим следующий подход:

                                if (TabsSimple.Where(x => x.Securiti == master_sec).Count() == 0)
                              {
                                    TabCreate(BotTabType.Simple);

                                  var conCandles = TabsSimple.Last().Connector;
                                  conCandles.ServerType = masterInstrument.Type;
                                  conCandles.PortfolioName = masterPortfolio;
                                  conCandles.TimeFrameBuilder.CandleCreateMethodType = CandleCreateMethodType.Simple;
                                  conCandles.TimeFrame = TimeFrame.Min10;
                                    conCandles.NamePaper = master_sec.Name;

                                  while (TabsSimple.Last().IsReadyToTrade == false)
                                  {
                                      Thread.Sleep(50);
                                  }
                              }

    if (TabsSimple.Where(x => x.Securiti == slave_sec).Count() == 0) { TabCreate(BotTabType.Simple); var conCandles = TabsSimple.Last().Connector; conCandles.ServerType = slaveInstrument.Type; conCandles.PortfolioName = slavePortfolio; conCandles.TimeFrameBuilder.CandleCreateMethodType = CandleCreateMethodType.Simple; conCandles.TimeFrame = TimeFrame.Min10; conCandles.NamePaper = slave_sec.Name; while (TabsSimple.Last().IsReadyToTrade == false) { Thread.Sleep(50); } }

    var newTP = new TradingPair() { MasterSymbol = masterInstrument, SlaveSymbol = slaveInstrument, master_Tab = TabsSimple.Find(x => x.Connector.Security.Name == master_sec.Name), slave_Tab = TabsSimple.Find(x => x.Connector.Security.Name == slave_sec.Name) }; if (!tradingPairsList.Contains(newTP)) { tradingPairsList.Add(newTP); TabsSimple.Find(x => x.Securiti == master_sec).CandleUpdateEvent += _tab1_CandleUpdateEvent; TabsSimple.Find(x => x.Securiti == slave_sec).CandleUpdateEvent += _tab2_CandleUpdateEvent; TabsSimple.Find(x => x.Securiti == master_sec).CandleFinishedEvent += _tab1_CandleUpdateEvent; TabsSimple.Find(x => x.Securiti == slave_sec).CandleFinishedEvent += _tab2_CandleUpdateEvent; }

    Вот так просто в 4 шага мы получаем реализацию управления вкладками из бота. Я не претендую на истину в последней инстанции, возможно есть более элегантное решение. Но, в случае использования моего кода целиком или частично, вы не должны использовать нижнее подчеркивание в началах имен приватных членах класса.

    karuzzo
    31.05.2020 21:40
    #1