예제 #1
0
        private static void SubscribeToStreams(BinanceWebsocketClient client)
        {
            client.Streams.PongStream.Subscribe(x =>
                                                Log.Information($"Pong received ({x.Message})"));

            client.Streams.AggregateTradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade aggreg [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.TradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade normal [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.OrderBookPartialStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book snapshot [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
            });

            client.Streams.OrderBookDiffStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book diff [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
            });
        }
예제 #2
0
        private static async Task<ICryptoOrderBook> StartBinance(string pair, bool optimized, bool l2Optimized)
        {
            var url = BinanceValues.ApiWebsocketUrl;
            var communicator = new BinanceWebsocketCommunicator(url) { Name = "Binance" };
            var client = new BinanceWebsocketClient(communicator);

            client.SetSubscriptions(
                new OrderBookDiffSubscription(pair)
            );

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

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

            _ = communicator.Start();

            // Binance is special
            // We need to load snapshot in advance manually via REST call
            _ = source.LoadSnapshot(communicator, pair);

            return orderBook;
        }
        public async Task ConnectToSource_ShouldHandleOrderBookCorrectly()
        {
            var url = BinanceValues.ApiWebsocketUrl;

            using (var communicator = new BinanceWebsocketCommunicator(url))
            {
                using (var client = new BinanceWebsocketClient(communicator))
                {
                    var pair = "BTCUSDT";

                    client.SetSubscriptions(
                        new OrderBookDiffSubscription(pair)
                        );

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

                    await communicator.Start();

                    // Binance is special
                    // We need to load snapshot in advance manually via REST call
                    await source.LoadSnapshot(pair);

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

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

                    Assert.NotEmpty(orderBook.BidLevels);
                    Assert.NotEmpty(orderBook.AskLevels);
                }
            }
        }
        public async Task AutoSnapshotReloading_ShouldWorkAfterTimeout()
        {
            var url = BinanceValues.ApiWebsocketUrl;

            using (var communicator = new BinanceWebsocketCommunicator(url))
            {
                using (var client = new BinanceWebsocketClient(communicator))
                {
                    var pair = "BTCUSDT";

                    client.SetSubscriptions(
                        new OrderBookDiffSubscription(pair)
                        );

                    var source = new BinanceOrderBookSource(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);
                }
            }
        }
예제 #5
0
        public async Task Connect_ShouldWorkAndReceiveResponse()
        {
            var url = BinanceValues.ApiWebsocketUrl;

            using (var communicator = new BinanceWebsocketCommunicator(url))
            {
                TradeResponse received      = null;
                var           receivedEvent = new ManualResetEvent(false);

                using (var client = new BinanceWebsocketClient(communicator))
                {
                    client.Streams.TradesStream.Subscribe(response =>
                    {
                        received = response;
                        receivedEvent.Set();
                    });

                    client.SetSubscriptions(
                        new TradeSubscription("btcusdt")
                        );

                    await communicator.Start();

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

                    Assert.NotNull(received);
                }
            }
        }
예제 #6
0
 private void SetSubscriptions(BinanceWebsocketClient client, string pair)
 {
     client.SetSubscriptions(
         new TradeSubscription(pair),
         new OrderBookPartialSubscription(pair, 20)
         );
 }
        public async Task OnStart_ShouldStreamMessagesFromFile()
        {
            var files = new[]
            {
                "data/binance_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 BinanceFileCommunicator();

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

            var client = new BinanceWebsocketClient(communicator);

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

            await communicator.Start();

            Assert.Equal(44259, trades.Count);
        }
예제 #8
0
        /// <summary>
        /// Change client and resubscribe to the new streams
        /// </summary>
        public void ChangeClient(BinanceWebsocketClient client)
        {
            CryptoValidations.ValidateInput(client, nameof(client));

            _client = client;
            _subscription?.Dispose();
            Subscribe();
        }
예제 #9
0
 private void OnStop()
 {
     _pingSubscription?.Dispose();
     _client.Dispose();
     _communicator.Dispose();
     _client       = null;
     _communicator = null;
     Clear();
 }
예제 #10
0
 private void StartPingCheck(BinanceWebsocketClient client)
 {
     //_pingSubscription = Observable
     //    .Interval(TimeSpan.FromSeconds(5))
     //    .Subscribe(async x =>
     //    {
     //        _pingRequest = DateTime.UtcNow;
     //        await client.Send(new PingRequest());
     //    });
 }
        static void Main(string[] args)
        {
            InitLogging();

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

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

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



            var url = BinanceValues.ApiWebsocketUrl;

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

                using (var client = new BinanceWebsocketClient(communicator))
                {
                    SubscribeToStreams(client, communicator);

                    client.SetSubscriptions(
                        new TradeSubscription("btcusdt"),
                        //new TradeSubscription("ethbtc"),
                        //new TradeSubscription("bnbusdt"),
                        new AggregateTradeSubscription("bnbusdt"),
                        new OrderBookPartialSubscription("btcusdt", 5),
                        //new OrderBookPartialSubscription("bnbusdt", 10),
                        new OrderBookDiffSubscription("ltcusdt")
                        );
                    communicator.Start().Wait();

                    ExitEvent.WaitOne();
                }
            }

            Log.Debug("====================================");
            Log.Debug("              STOPPING              ");
            Log.Debug("====================================");
            Log.CloseAndFlush();
        }
        private static (ITradeSource, IWebsocketClient) GetBinance(string pair)
        {
            var url          = BinanceValues.ApiWebsocketUrl;
            var communicator = new BinanceWebsocketCommunicator(url)
            {
                Name = "Binance"
            };
            var client = new BinanceWebsocketClient(communicator);

            var source = new BinanceTradeSource(client);

            client.SetSubscriptions(
                new TradeSubscription(pair)
                );

            return(source, communicator);
        }
예제 #13
0
        private static void SubscribeToStreams(BinanceWebsocketClient client, IBinanceCommunicator comm)
        {
            client.Streams.PongStream.Subscribe(x =>
                                                Log.Information($"Pong received ({x.Message})"));

            client.Streams.FundingStream.Subscribe(response =>
            {
                var funding = response.Data;
                Log.Information($"Funding: [{funding.Symbol}] rate:[{funding.FundingRate}] " +
                                $"mark price: {funding.MarkPrice} next funding: {funding.NextFundingTime} " +
                                $"index price {funding.IndexPrice}");
            });

            client.Streams.AggregateTradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade aggreg [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.TradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade normal [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.OrderBookPartialStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book snapshot [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
                Task.Delay(500).Wait();
                //OrderBookPartialResponse.StreamFakeSnapshot(response.Data, comm);
            });

            client.Streams.OrderBookDiffStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book diff [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
            });
        }
예제 #14
0
        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 = BinanceValues.ApiWebsocketUrl;

            _communicator = new BinanceWebsocketCommunicator(url);
            _client       = new BinanceWebsocketClient(_communicator);

            Subscribe(_client);

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

            _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);
            });

            SetSubscriptions(_client, pair);
            await _communicator.Start();

            StartPingCheck(_client);
        }
예제 #15
0
 private void Subscribe(BinanceWebsocketClient client)
 {
     client.Streams.TradesStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleTrades);
     client.Streams.OrderBookPartialStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandleOrderBook);
     client.Streams.PongStream.ObserveOn(TaskPoolScheduler.Default).Subscribe(HandlePong);
 }
예제 #16
0
        private static void SubscribeToStreams(BinanceWebsocketClient client, IBinanceCommunicator comm)
        {
            client.Streams.PongStream.Subscribe(x =>
                                                Log.Information($"Pong received ({x.Message})"));

            client.Streams.FundingStream.Subscribe(response =>
            {
                var funding = response.Data;
                Log.Information($"Funding: [{funding.Symbol}] rate:[{funding.FundingRate}] " +
                                $"mark price: {funding.MarkPrice} next funding: {funding.NextFundingTime} " +
                                $"index price {funding.IndexPrice}");
            });

            client.Streams.AggregateTradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade aggreg [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.TradesStream.Subscribe(response =>
            {
                var trade = response.Data;
                Log.Information($"Trade normal [{trade.Symbol}] [{trade.Side}] " +
                                $"price: {trade.Price} size: {trade.Quantity}");
            });

            client.Streams.OrderBookPartialStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book snapshot [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
                Task.Delay(500).Wait();
                //OrderBookPartialResponse.StreamFakeSnapshot(response.Data, comm);
            });

            client.Streams.OrderBookDiffStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Order book diff [{ob.Symbol}] " +
                                $"bid: {ob.Bids.FirstOrDefault()?.Price:F} " +
                                $"ask: {ob.Asks.FirstOrDefault()?.Price:F}");
            });

            client.Streams.BookTickerStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Book ticker [{ob.Symbol}] " +
                                $"Best ask price: {ob.BestAskPrice} " +
                                $"Best ask qty: {ob.BestAskQty} " +
                                $"Best bid price: {ob.BestBidPrice} " +
                                $"Best bid qty: {ob.BestBidQty}");
            });

            client.Streams.KlineStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Kline [{ob.Symbol}] " +
                                $"Kline start time: {ob.StartTime} " +
                                $"Kline close time: {ob.CloseTime} " +
                                $"Interval: {ob.Interval} " +
                                $"First trade ID: {ob.FirstTradeId} " +
                                $"Last trade ID: {ob.LastTradeId} " +
                                $"Open price: {ob.OpenPrice} " +
                                $"Close price: {ob.ClosePrice} " +
                                $"High price: {ob.HighPrice} " +
                                $"Low price: {ob.LowPrice} " +
                                $"Base asset volume: {ob.BaseAssetVolume} " +
                                $"Number of trades: {ob.NumberTrades} " +
                                $"Is this kline closed?: {ob.IsClose} " +
                                $"Quote asset volume: {ob.QuoteAssetVolume} " +
                                $"Taker buy base: {ob.TakerBuyBaseAssetVolume} " +
                                $"Taker buy quote: {ob.TakerBuyQuoteAssetVolume} " +
                                $"Ignore: {ob.Ignore} ");
            });

            client.Streams.MiniTickerStream.Subscribe(response =>
            {
                var ob = response.Data;
                Log.Information($"Mini-ticker [{ob.Symbol}] " +
                                $"Open price: {ob.OpenPrice} " +
                                $"Close price: {ob.ClosePrice} " +
                                $"High price: {ob.HighPrice} " +
                                $"Low price: {ob.LowPrice} " +
                                $"Base asset volume: {ob.BaseAssetVolume} " +
                                $"Quote asset volume: {ob.QuoteAssetVolume}");
            });
        }
예제 #17
0
        /// <inheritdoc />
        public BinanceOrderBookSource(BinanceWebsocketClient client)
        {
            _httpClient.BaseAddress = new Uri("https://www.binance.com");

            ChangeClient(client);
        }
 /// <inheritdoc />
 public BinanceTradeSource(BinanceWebsocketClient client)
 {
     ChangeClient(client);
 }