public PositionsForm()
        {
            InitializeComponent();
            Load += new EventHandler(Form1_Load);

            //Connecting to WebSocket
            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                communicator.Name             = "Bitmex-1";
                communicator.ReconnectTimeout = TimeSpan.FromMinutes(10);
                communicator.ReconnectionHappened.Subscribe(type =>
                                                            Console.WriteLine($"Reconnection happened, type: {type.Type}"));

                using (var client = new BitmexWebsocketClient(communicator))
                {
                    client.Streams.InfoStream.Subscribe(info =>
                    {
                        Console.WriteLine($"Reconnection happened, Message: {info.Info}, Version: {info.Version:D}");
                        SendSubscriptionRequests(client).Wait();
                    });

                    SubscribeToStreams(client);

                    communicator.Start();

                    _ = StartPinging(client);
                }
            }
        }
Esempio n. 2
0
        private static async Task <ICryptoOrderBook> StartBitmex(string pair, bool optimized, bool l2Optimized)
        {
            var url          = BitmexValues.ApiWebsocketUrl;
            var communicator = new BitmexWebsocketCommunicator(url)
            {
                Name = "Bitmex"
            };
            var client = new BitmexWebsocketClient(communicator);

            var source    = new BitmexOrderBookSource(client);
            var orderBook = l2Optimized ?
                            new CryptoOrderBookL2(pair, source) :
                            (ICryptoOrderBook) new CryptoOrderBook(pair, source);

            if (optimized)
            {
                ConfigureOptimized(source, orderBook);
            }

            _ = communicator.Start();

            // Send subscription request to order book data
            client.Send(new Bitmex.Client.Websocket.Requests.BookSubscribeRequest(pair));

            return(orderBook);
        }
        public async Task Authentication()
        {
            Skip.If(string.IsNullOrWhiteSpace(API_SECRET));

            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                AuthenticationResponse received = null;
                var receivedEvent = new ManualResetEvent(false);

                using (var client = new BitmexWebsocketClient(communicator))
                {
                    client.Streams.AuthenticationStream.Subscribe(auth =>
                    {
                        received = auth;
                        receivedEvent.Set();
                    });

                    await communicator.Start();

                    await client.Authenticate(API_KEY, API_SECRET);

                    receivedEvent.WaitOne(TimeSpan.FromSeconds(30));

                    Assert.NotNull(received);
                    Assert.True(received.Success);
                }
            }
        }
        public async Task PingPong()
        {
            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                PongResponse received      = null;
                var          receivedEvent = new ManualResetEvent(false);

                using (var client = new BitmexWebsocketClient(communicator))
                {
                    client.Streams.PongStream.Subscribe(pong =>
                    {
                        received = pong;
                        receivedEvent.Set();
                    });

                    await communicator.Start();

                    await client.Send(new PingRequest());

                    receivedEvent.WaitOne(TimeSpan.FromSeconds(30));

                    Assert.NotNull(received);
                }
            }
        }
        public async Task AutoSnapshotReloading_ShouldWorkAfterTimeout()
        {
            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                using (var client = new BitmexWebsocketClient(communicator))
                {
                    var pair = "XBTUSD";

                    var source = new BitmexOrderBookSource(client)
                    {
                        LoadSnapshotEnabled = true
                    };
                    var orderBook = new CryptoOrderBook(pair, source)
                    {
                        SnapshotReloadTimeout = TimeSpan.FromSeconds(5),
                        SnapshotReloadEnabled = true
                    };

                    await Task.Delay(TimeSpan.FromSeconds(13));

                    Assert.True(orderBook.BidPrice > 0);
                    Assert.True(orderBook.AskPrice > 0);

                    Assert.NotEmpty(orderBook.BidLevels);
                    Assert.NotEmpty(orderBook.AskLevels);
                }
            }
        }
Esempio n. 6
0
        public async Task OnStart_ShouldStreamMessagesFromFile()
        {
            var files = new[]
            {
                "data/bitmex_raw_xbtusd_2018-11-13.txt"
            };

            foreach (var file in files)
            {
                var exist = File.Exists(file);
                Skip.If(!exist, $"The file '{file}' doesn't exist. Don't forget to decompress gzip file!");
            }

            var trades = new List <Trade>();

            var communicator = new BitmexFileCommunicator();

            communicator.FileNames = files;
            communicator.Delimiter = ";;";

            var client = new BitmexWebsocketClient(communicator);

            client.Streams.TradesStream.Subscribe(response =>
            {
                trades.AddRange(response.Data);
            });

            await communicator.Start();

            Assert.Equal(44259, trades.Count);
        }
        public async Task ConnectToSource_ShouldHandleOrderBookCorrectly()
        {
            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                using (var client = new BitmexWebsocketClient(communicator))
                {
                    var pair = "XBTUSD";

                    var source    = new BitmexOrderBookSource(client);
                    var orderBook = new CryptoOrderBook(pair, source);

                    await communicator.Start();

                    client.Send(new BookSubscribeRequest(pair));

                    await Task.Delay(TimeSpan.FromSeconds(10));

                    Assert.True(orderBook.BidPrice > 0);
                    Assert.True(orderBook.AskPrice > 0);

                    Assert.NotEmpty(orderBook.BidLevels);
                    Assert.NotEmpty(orderBook.AskLevels);
                }
            }
        }
 private static async Task SendSubscriptionRequests(BitmexWebsocketClient client)
 {
     client.Send(new PingRequest());
     if (!string.IsNullOrWhiteSpace(AccessKeys.bitmexSecret))
     {
         client.Send(new AuthenticationRequest(AccessKeys.bitmexKey, AccessKeys.bitmexSecret));
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Change client and resubscribe to the new streams
        /// </summary>
        public void ChangeClient(BitmexWebsocketClient client)
        {
            CryptoValidations.ValidateInput(client, nameof(client));

            _client = client;
            _subscription?.Dispose();
            Subscribe();
        }
        /// <inheritdoc />
        public BitmexOrderBookSource(BitmexWebsocketClient client, bool isTestnet = false)
        {
            _httpClient.BaseAddress = isTestnet ?
                                      new Uri("https://testnet.bitmex.com") :
                                      new Uri("https://www.bitmex.com");

            ChangeClient(client);
        }
 private void OnStop()
 {
     _pingSubscription.Dispose();
     _client.Dispose();
     _communicator.Dispose();
     _client       = null;
     _communicator = null;
     Clear();
 }
 private void StartPingCheck(BitmexWebsocketClient client)
 {
     _pingSubscription = Observable
                         .Interval(TimeSpan.FromSeconds(5))
                         .Subscribe(async x =>
     {
         _pingRequest = DateTime.UtcNow;
         await client.Send(new PingRequest());
     });
 }
Esempio n. 13
0
        static void Main(string[] args)
        {
            InitLogging();

            AppDomain.CurrentDomain.ProcessExit   += CurrentDomainOnProcessExit;
            AssemblyLoadContext.Default.Unloading += DefaultOnUnloading;
            Console.CancelKeyPress += ConsoleOnCancelKeyPress;

            Console.WriteLine("|=======================|");
            Console.WriteLine("|     BITMEX CLIENT     |");
            Console.WriteLine("|=======================|");
            Console.WriteLine();

            Log.Debug("====================================");
            Log.Debug("              STARTING              ");
            Log.Debug("====================================");



            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                communicator.Name             = "Bitmex-1";
                communicator.ReconnectTimeout = TimeSpan.FromMinutes(10);
                communicator.ReconnectionHappened.Subscribe(type =>
                                                            Log.Information($"Reconnection happened, type: {type.Type}"));

                using (var client = new BitmexWebsocketClient(communicator))
                {
                    client.Streams.InfoStream.Subscribe(info =>
                    {
                        Log.Information($"Reconnection happened, Message: {info.Info}, Version: {info.Version:D}");
                        SendSubscriptionRequests(client);
                    });

                    SubscribeToStreams(client);

                    communicator.Start();

                    _ = StartPinging(client);

                    ExitEvent.WaitOne();
                }
            }

            Log.Debug("====================================");
            Log.Debug("              STOPPING              ");
            Log.Debug("====================================");
            Log.CloseAndFlush();
        }
Esempio n. 14
0
        /// <summary>
        /// Send the requests for the subscriptions needed.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="pair"></param>
        /// <param name="acc"></param>
        /// <returns></returns>
        private async Task SendSubscriptions(BitmexWebsocketClient client, string pair, MTAccount acc)
        {
            var    appSettings = ConfigurationManager.AppSettings;
            string api, sec;

            if (acc == MTAccount.A)
            {
                if (_view.isTest)
                {
                    api = appSettings["API_KEY_BITMEX_A_TEST"] ?? string.Empty;
                    sec = appSettings["API_SECRET_BITMEX_A_TEST"] ?? string.Empty;
                }
                else
                {
                    api = appSettings["API_KEY_BITMEX_A_LIVE"] ?? string.Empty;
                    sec = appSettings["API_SECRET_BITMEX_A_LIVE"] ?? string.Empty;
                }

                // Trade stats
                //await client.Send(new TradesSubscribeRequest(pair));

                // Bid and Ask
                await client.Send(new BookSubscribeRequest(pair));
            }
            else
            {
                if (_view.isTest)
                {
                    api = appSettings["API_KEY_BITMEX_B_TEST"] ?? string.Empty;
                    sec = appSettings["API_SECRET_BITMEX_B_TEST"] ?? string.Empty;
                }
                else
                {
                    api = appSettings["API_KEY_BITMEX_B_LIVE"] ?? string.Empty;
                    sec = appSettings["API_SECRET_BITMEX_B_LIVE"] ?? string.Empty;
                }
            }

            if (!string.IsNullOrEmpty(api) && !string.IsNullOrEmpty(sec))
            {
                await client.Send(new AuthenticationRequest(api, sec));
            }

            await client.Send(new OrderSubscribeRequest());

            await client.Send(new PositionSubscribeRequest());

            await client.Send(new MarginSubscribeRequest());

            //await client.Send(new ExecutionSubscribeRequest());
        }
Esempio n. 15
0
        private static async Task SendSubscriptionRequests(BitmexWebsocketClient client)
        {
            await client.Send(new PingRequest());

            //await client.Send(new BookSubscribeRequest());
            await client.Send(new TradesSubscribeRequest("XBTUSD"));

            //await client.Send(new QuoteSubscribeRequest("XBTUSD"));
            await client.Send(new LiquidationSubscribeRequest());

            if (!string.IsNullOrWhiteSpace(API_SECRET))
            {
                await client.Send(new AuthenticationRequest(API_KEY, API_SECRET));
            }
        }
        private static (ITradeSource, IWebsocketClient) GetBitmex(string pair, bool isTestnet)
        {
            var url          = isTestnet ? BitmexValues.ApiWebsocketTestnetUrl : BitmexValues.ApiWebsocketUrl;
            var communicator = new BitmexWebsocketCommunicator(url)
            {
                Name = "Bitmex"
            };
            var client = new BitmexWebsocketClient(communicator);

            var source = new BitmexTradeSource(client);

            communicator.ReconnectionHappened.Subscribe(x =>
            {
                client.Send(new Bitmex.Client.Websocket.Requests.TradesSubscribeRequest(pair));
            });

            return(source, communicator);
        }
        private async Task OnStart()
        {
            var pair = _view.Pair;

            if (string.IsNullOrWhiteSpace(pair))
            {
                pair = _defaultPair;
            }
            pair = pair.ToUpper();

            _tradeStatsComputer     = new TradeStatsComputer();
            _orderBookStatsComputer = new OrderBookStatsComputer();

            var url = _view.IsTestNet ?
                      BitmexValues.ApiWebsocketTestnetUrl :
                      BitmexValues.ApiWebsocketUrl;

            _communicator = new BitmexWebsocketCommunicator(url);
            _client       = new BitmexWebsocketClient(_communicator);

            Subscribe(_client);

            _communicator.ReconnectionHappened.Subscribe(async type =>
            {
                _view.Status($"Reconnected (type: {type})", StatusType.Info);
                await SendSubscriptions(_client, pair);
            });

            _communicator.DisconnectionHappened.Subscribe(type =>
            {
                if (type == DisconnectionType.Error)
                {
                    _view.Status($"Disconnected by error, next try in {_communicator.ErrorReconnectTimeoutMs/1000} sec",
                                 StatusType.Error);
                    return;
                }
                _view.Status($"Disconnected (type: {type})",
                             StatusType.Warning);
            });

            await _communicator.Start();

            StartPingCheck(_client);
        }
        public static void RunSample(ManualResetEvent ExitEvent)
        {
            Console.WriteLine("|=======================|");
            Console.WriteLine("|     BITMEX CLIENT     |");
            Console.WriteLine("|=======================|");
            Console.WriteLine();

            Log.Debug("====================================");
            Log.Debug("              STARTING              ");
            Log.Debug("====================================");



            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                communicator.Name = "Bitmex-1";
                communicator.ReconnectTimeoutMs = (int)TimeSpan.FromMinutes(10).TotalMilliseconds;
                communicator.ReconnectionHappened.Subscribe(type =>
                                                            Log.Information($"Reconnection happened, type: {type}"));

                using (var client = new BitmexWebsocketClient(communicator))
                {
                    client.Streams.InfoStream.Subscribe(info =>
                    {
                        Log.Information($"Reconnection happened, Message: {info.Info}, Version: {info.Version:D}");
                        SendSubscriptionRequests(client).Wait();
                    });

                    SubscribeToStreams(client);

                    communicator.Start();

                    ExitEvent.WaitOne();
                }
            }

            Log.Debug("====================================");
            Log.Debug("              STOPPING              ");
            Log.Debug("====================================");
            Log.CloseAndFlush();
        }
Esempio n. 19
0
        private static void SendSubscriptionRequests(BitmexWebsocketClient client)
        {
            client.Send(new PingRequest());
            //client.Send(new BookSubscribeRequest("XBTUSD"));
            client.Send(new TradesSubscribeRequest("XBTUSD"));
            //client.Send(new TradeBinSubscribeRequest("1m", "XBTUSD"));
            //client.Send(new TradeBinSubscribeRequest("5m", "XBTUSD"));
            client.Send(new QuoteSubscribeRequest("XBTUSD"));
            client.Send(new LiquidationSubscribeRequest());
            client.Send(new InstrumentSubscribeRequest("XBTUSD"));
            client.Send(new FundingsSubscribeRequest("XBTUSD"));
            //client.Send(new Book25SubscribeRequest("XBTUSD"));
            //client.Send(new Book10SubscribeRequest("XBTUSD"));

            if (!string.IsNullOrWhiteSpace(API_SECRET))
            {
                client.Send(new AuthenticationRequest(API_KEY, API_SECRET));
            }
        }
Esempio n. 20
0
        private void Subscribe(BitmexWebsocketClient client, MTAccount acc)
        {
            client
            .Streams
            .MarginStream
            .Select(trade => Observable.FromAsync(async() => {
                HandleMarginResponse(trade);
            }))
            .Concat()
            .Subscribe();

            client
            .Streams
            .OrderStream
            .Select(ord => Observable.FromAsync(async() => {
                HandleOrderResponse(ord);
            }))
            .Concat()
            .Subscribe();

            //client
            //    .Streams
            //    .PositionStream
            //    .Select(pos => Observable.FromAsync(async () => {
            //        HandlePositionResponse(pos);
            //    }))
            //    .Concat()
            //    .Subscribe();

            //client.Streams.ErrorStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleErrorResponse);

            if (acc == MTAccount.A)
            {
                client.Streams.TradesStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleTrades);
                client.Streams.BookStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleOrderBook);
                client.Streams.PongStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandlePongA);
                client.Streams.PositionStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandlePositionResponse);
            }
            else
            {
                client.Streams.PongStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandlePongB);
            }
        }
Esempio n. 21
0
 private void OnStopB()
 {
     //OnStopZoneRecovery();
     if (_pingSubscriptionB != null)
     {
         _pingSubscriptionB.Dispose();
     }
     if (_clientB != null)
     {
         _clientB.Dispose();
     }
     if (_communicatorB != null)
     {
         _communicatorB.Dispose();
     }
     _clientB       = null;
     _communicatorB = null;
     Clear(ZoneRecoveryAccount.B);
 }
Esempio n. 22
0
        public static void run()
        {
            int failed = 0;

            while (true)
            {
                try
                {
                    var url = new Uri(wsURl);

                    using (var connector = new BitmexWebsocketCommunicator(url))
                    {
                        using (var client = new BitmexWebsocketClient(connector))
                        {
                            client.Streams.InfoStream.Subscribe(info =>
                            {
                                Console.WriteLine($"Info received, reconnection happened.");
                                client.Send(new PingRequest()).Wait();
                                SendSubscriptionRequests(client).Wait();
                            });

                            SubscribeToStreams(client);
                            connector.Start();

                            ExitEvent.WaitOne();
                        }
                    }
                }
                catch (Exception e)
                {
                    MainClass.log("WebSocket crashed due to: " + e.Message + e.StackTrace, ConsoleColor.White, "error");
                    if (failed >= MainClass.maxWebsocketsFail)
                    {
                        MainClass.log("Reverting to standard rest api calls...", ConsoleColor.Red);
                        MainClass.useWebSockets = false;
                        Thread.CurrentThread.Abort();
                    }
                    MainClass.log("Waiting 1s before restarting!", ConsoleColor.Red);
                    Thread.Sleep(1000);
                    failed++;
                }
            }
        }
        private static async Task <ICryptoOrders> StartBitmex(bool isTestnet, Action <CryptoOrder> handler,
                                                              Action <CryptoWallet[]> walletHandler, Action <CryptoPosition[]> positionHandler)
        {
            var url          = isTestnet ? BitmexValues.ApiWebsocketTestnetUrl : BitmexValues.ApiWebsocketUrl;
            var communicator = new BitmexWebsocketCommunicator(url)
            {
                Name = "Bitmex"
            };
            var client = new BitmexWebsocketClient(communicator);

            var source = new BitmexOrderSource(client);
            var orders = new CryptoOrders(source);

            orders.OrderChangedStream.Subscribe(handler);

            var walletSource = new BitmexWalletSource(client);

            walletSource.WalletChangedStream.Subscribe(walletHandler);

            var positionSource = new BitmexPositionSource(client);

            positionSource.PositionsStream.Subscribe(positionHandler);

            client.Streams.AuthenticationStream.Subscribe(x =>
            {
                Log.Information($"[Bitmex] Authenticated '{x.Success}'");
                client.Send(new Bitmex.Client.Websocket.Requests.WalletSubscribeRequest());
                client.Send(new Bitmex.Client.Websocket.Requests.MarginSubscribeRequest());
                client.Send(new Bitmex.Client.Websocket.Requests.PositionSubscribeRequest());
                client.Send(new Bitmex.Client.Websocket.Requests.OrderSubscribeRequest());
            });

            communicator.ReconnectionHappened.Subscribe(x =>
            {
                client.Authenticate(API_KEY, API_SECRET);
            });

            await communicator.Start();


            return(orders);
        }
Esempio n. 24
0
        private static async Task SendSubscriptionRequests(BitmexWebsocketClient client)
        {
            await client.Send(new PingRequest());

            //await client.Send(new BookSubscribeRequest(MainClass.pair));
            //await client.Send(new TradesSubscribeRequest(MainClass.pair));
            await client.Send(new TradeBinSubscribeRequest("1m", MainClass.pair));

            await client.Send(new TradeBinSubscribeRequest("5m", MainClass.pair));

            await client.Send(new TradeBinSubscribeRequest("1h", MainClass.pair));

            //await client.Send(new InstrumentSubscribeRequest(MainClass.pair));
            await client.Send(new QuoteSubscribeRequest(MainClass.pair));

            //await client.Send(new LiquidationSubscribeRequest());

            //if (!string.IsNullOrWhiteSpace(MainClass.bitmexKeyWebSocket))
            //await client.Send(new AuthenticationRequest(MainClass.bitmexKeyWebSocket, MainClass.bitmexSecretWebSocket));
        }
Esempio n. 25
0
        private void OnStopA()
        {
            OnStopZoneRecovery();
            if (_pingSubscriptionA != null)
            {
                _pingSubscriptionA.Dispose();
            }
            if (_clientA != null)
            {
                _clientA.Dispose();
            }
            if (_communicatorA != null)
            {
                _communicatorA.Dispose();
            }
            _clientA       = null;
            _communicatorA = null;

            Clear(ZoneRecoveryAccount.A);
        }
        public async Task ConnectToSource_ShouldHandleOrderBookOneByOne()
        {
            var url = BitmexValues.ApiWebsocketUrl;

            using (var communicator = new BitmexWebsocketCommunicator(url))
            {
                using (var client = new BitmexWebsocketClient(communicator))
                {
                    var pair   = "XBTUSD";
                    var called = 0;

                    var source    = new BitmexOrderBookSource(client);
                    var orderBook = new CryptoOrderBook(pair, source)
                    {
                        DebugEnabled = true
                    };

                    orderBook.OrderBookUpdatedStream.Subscribe(x =>
                    {
                        called++;
                        Thread.Sleep(2000);
                    });

                    await communicator.Start();

                    client.Send(new BookSubscribeRequest(pair));

                    await Task.Delay(TimeSpan.FromSeconds(5));

                    Assert.Equal(2, called);

                    await Task.Delay(TimeSpan.FromSeconds(2));

                    Assert.Equal(3, called);
                }
            }
        }
Esempio n. 27
0
        public async Task StreamFromFile_ShouldBeFast()
        {
            var pair         = "XBTUSD";
            var communicator = new RawFileCommunicator();

            communicator.FileNames = _rawFiles;

            var client = new BitmexWebsocketClient(communicator);
            var source = new BitmexOrderBookSource(client);

            source.LoadSnapshotEnabled = false;
            source.BufferEnabled       = false;

            var orderBook = new CryptoOrderBookL2(pair, source);

            orderBook.SnapshotReloadEnabled = false;
            orderBook.ValidityCheckEnabled  = false;

            var snapshotCount = 0;
            var diffCount     = 0;

            source.OrderBookSnapshotStream.Subscribe(x => snapshotCount++);
            source.OrderBookStream.Subscribe(x => diffCount++);

            var sw = Stopwatch.StartNew();
            await communicator.Start();

            sw.Stop();

            var elapsedMs = sw.ElapsedMilliseconds;
            var msg       = $"Processed snapshots: {snapshotCount}, diffs: {diffCount}, elapsed time was: {elapsedMs} ms";

            _output.WriteLine(msg);

            Assert.True(elapsedMs < 7000, msg);
        }
Esempio n. 28
0
        public async Task OnStart_ShouldStreamMessagesFromFile()
        {
            var files = new[]
            {
                "data/bitmex_raw_xbtusd_2018-11-13.txt"
            };
            var trades = new List <Trade>();

            var communicator = new BitmexFileCommunicator();

            communicator.FileNames = files;
            communicator.Delimiter = ";;";

            var client = new BitmexWebsocketClient(communicator);

            client.Streams.TradesStream.Subscribe(response =>
            {
                trades.AddRange(response.Data);
            });

            await communicator.Start();

            Assert.Equal(44259, trades.Count);
        }
 private void Subscribe(BitmexWebsocketClient client)
 {
     client.Streams.TradesStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleTrades);
     client.Streams.BookStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleOrderBook);
     client.Streams.PongStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandlePong);
 }
        private async Task SendSubscriptions(BitmexWebsocketClient client, string pair)
        {
            await client.Send(new TradesSubscribeRequest(pair));

            await client.Send(new BookSubscribeRequest(pair));
        }