Click or drag to resize

Multiple connections

S# has a mechanism to work simultaneously with multiple connections (connectors). For example, the algorithm can simultaneously perform trade through Interactive Brokers and OpenECry, or work with multiple Interactive Brokers terminals. This mechanism is implemented at the message level (see Messages). Behind the scenes of this mechanism is the use of the BasketMessageAdapter class, which allows you to sequentially operate multiple adapters connected to various trading systems. The Connector class has the Adapter property of this type.

It is possible to organize work with several connectors downloading the settings from the special configuration file, in which the connector settings are saved, including adapters settings. Or it is possible to use the ConnectorWindow component, which is a graphical service for the connector configuration.

The following is an example of creating multiple connection. Source codes of the example are in the Samples/Common/SampleMultiConnection project.

multiconnection main

Creating multiple connection

  1. In the main window constructor we call the InitConnector method in which the connector is configured, as well as subscription to the required events is performed.

    C#
    public MainWindow()
    {
        InitializeComponent();
        Instance = this;
    
        Title = Title.Put("Multi connection");
    
        _ordersWindow.MakeHideable();
        _myTradesWindow.MakeHideable();
        _tradesWindow.MakeHideable();
        _securitiesWindow.MakeHideable();
        _stopOrdersWindow.MakeHideable();
        _portfoliosWindow.MakeHideable();
    
        var logManager = new LogManager();
        logManager.Listeners.Add(new FileLogListener("sample.log"));
    
        var entityRegistry = new CsvEntityRegistry("Data");
    
        ConfigManager.RegisterService<IEntityRegistry>(entityRegistry);
        // ecng.serialization invoke in several places IStorage obj
        ConfigManager.RegisterService(entityRegistry.Storage);
    
        var storageRegistry = ConfigManager.GetService<IStorageRegistry>();
    
        Connector = new Connector(entityRegistry, storageRegistry);
        logManager.Sources.Add(Connector);
    
        InitConnector(entityRegistry);
    }
  2. The subscription to the connector events is performed in the InitConnector method, as well as connector settings loading from the configuration file using the ConnectorLoad(SettingsStorage) method.

    C#
    private void InitConnector(CsvEntityRegistry entityRegistry)
    {
        // subscribe on connection successfully event
        Connector.Connected += () =>
        {
            this.GuiAsync(() => ChangeConnectStatus(true));
        };
    
        // subscribe on connection error event
        Connector.ConnectionError += error => this.GuiAsync(() =>
        {
            ChangeConnectStatus(false);
            MessageBox.Show(this, error.ToString(), LocalizedStrings.Str2959);
        });
    
        Connector.Disconnected += () => this.GuiAsync(() => ChangeConnectStatus(false));
    
        // subscribe on error event
        Connector.Error += error =>
            this.GuiAsync(() => MessageBox.Show(this, error.ToString(), LocalizedStrings.Str2955));
    
        // subscribe on error of market data subscription event
        Connector.MarketDataSubscriptionFailed += (security, msg, error) =>
            this.GuiAsync(() => MessageBox.Show(this, error.ToString(), LocalizedStrings.Str2956Params.Put(msg.DataType, security)));
    
        Connector.NewSecurity += security => _securitiesWindow.SecurityPicker.Securities.Add(security);
        Connector.NewTrade += trade => _tradesWindow.TradeGrid.Trades.Add(trade);
    
        Connector.NewOrder += order => _ordersWindow.OrderGrid.Orders.Add(order);
        Connector.NewStopOrder += order => _stopOrdersWindow.OrderGrid.Orders.Add(order);
        Connector.NewMyTrade += trade => _myTradesWindow.TradeGrid.Trades.Add(trade);
    
        Connector.NewPortfolio += portfolio => _portfoliosWindow.PortfolioGrid.Portfolios.Add(portfolio);
        Connector.NewPosition += position => _portfoliosWindow.PortfolioGrid.Positions.Add(position);
    
        // subscribe on error of order registration event
        Connector.OrderRegisterFailed += _ordersWindow.OrderGrid.AddRegistrationFail;
        // subscribe on error of order cancelling event
        Connector.OrderCancelFailed += OrderFailed;
    
        // subscribe on error of stop-order registration event
        Connector.OrderRegisterFailed += _stopOrdersWindow.OrderGrid.AddRegistrationFail;
        // subscribe on error of stop-order cancelling event
        Connector.StopOrderCancelFailed += OrderFailed;
    
        // set market data provider
        _securitiesWindow.SecurityPicker.MarketDataProvider = Connector;
    
        try
        {
            if (File.Exists(_settingsFile))
                Connector.Load(new XmlSerializer<SettingsStorage>().Deserialize(_settingsFile));
        }
        catch
        {
        }
    
        if (Connector.StorageAdapter == null)
            return;
    
        try
        {
            entityRegistry.Init();
        }
        catch (Exception ex)
        {
            MessageBox.Show(this, ex.ToString());
        }
    
        Connector.StorageAdapter.DaysLoad = TimeSpan.FromDays(3);
        Connector.StorageAdapter.Load();
    
        ConfigManager.RegisterService<IExchangeInfoProvider>(new StorageExchangeInfoProvider(entityRegistry));
    }
  3. The following is the code of the Settings button Click event handler. The Configure(Connector, Window) method is called in the handler. This method opens the Connection Settings window (see below). Also in the handler the connector settings are saved to the configuration file. Further this file can be used to configure the connector without calling the Connection Settings window

    C#
    private void SettingsClick(object sender, RoutedEventArgs e)
    {
        if (Connector.Configure(this))
            new XmlSerializer<SettingsStorage>().Serialize(Connector.Save(), _settingsFile);
    }
  4. The connection settings window is shown here. It is necessary to select the required adapters from the drop-down list (it is opened by clicking '+') and to set their properties in the Properties window on the right. For example, for OpenECry it is required to specify the server address, login and password.

    multiconnection settings
    Note Note

    The valid of the connection can be checked using the Test button.

    The result of this window will be creating and adding the adapters to the list of the ConnectorAdapter property internal adapters.