/// <summary> /// Example using cache, web socket stream (or client), and controller. /// </summary> /// <returns></returns> // ReSharper disable once UnusedMember.Local private static void AdvancedExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", false, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. // Get configuration settings. var symbols = configuration.GetSection("Statistics:Symbols").Get <string[]>() ?? new string[] { Symbol.BTC_USDT }; // Initialize cache. var cache = services.GetService <ISymbolStatisticsCache>(); // Initialize web socket stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbols. cache.Subscribe(Display, symbols); // Set web socket URI using cache subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(cache); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket.Message += (s, e) => cache.HandleMessage(e.Subject, e.Json); // Begin streaming. controller.Begin(); Console.ReadKey(true); // wait for user input. } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
public void IsCombined() { Assert.False(_stream.IsCombined); _stream.Uri = BinanceWebSocketStream.CreateUri(_streamName); Assert.False(_stream.IsCombined); _stream.Uri = BinanceWebSocketStream.CreateUri(_streamName, "combined"); Assert.True(_stream.IsCombined); }
public void CreateUri() { var uri = BinanceWebSocketStream.CreateUri(); Assert.Null(uri); uri = BinanceWebSocketStream.CreateUri(_streamName); Assert.Equal($"{BinanceWebSocketStream.BaseUri}/ws/{_streamName}", uri.AbsoluteUri); // Duplicates are ignored. var uri2 = BinanceWebSocketStream.CreateUri(_streamName, _streamName); Assert.Equal(uri, uri2); const string streamName = "combined"; uri = BinanceWebSocketStream.CreateUri(_streamName, streamName); Assert.Equal($"{BinanceWebSocketStream.BaseUri}/stream?streams={_streamName}/{streamName}", uri.AbsoluteUri); }
/// <summary> /// Example using cache, web socket stream (or client), and controller. /// </summary> // ReSharper disable once UnusedMember.Local private static void AdvancedExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. // Get configuration settings. var symbol = configuration.GetSection("PriceChart")?["Symbol"] ?? Symbol.BTC_USDT; var interval = CandlestickInterval.Minute; try { interval = configuration.GetSection("PriceChart")?["Interval"].ToCandlestickInterval() ?? CandlestickInterval.Minute; } catch { /* ignore */ } var limit = 25; try { limit = Convert.ToInt32(configuration.GetSection("PriceChart")?["Limit"] ?? "25"); } catch { /* ignore */ } // Initialize cache. var cache = services.GetService <ICandlestickCache>(); // Initialize stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbol and interval with limit and callback. cache.Subscribe(symbol, interval, limit, Display); // Set web socket URI using cache subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(cache); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket.Message += (s, e) => cache.HandleMessage(e.Subject, e.Json); // Begin streaming. controller.Begin(); lock (_sync) _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. } //*///////////////////////////////////////// // Alternative usage (with an IJsonClient). //////////////////////////////////////////// // Initialize publisher/client. var client = services.GetService <ICandlestickClient>(); cache.Client = client; // link [new] client to cache. // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbol and interval with limit and callback. //cache.Subscribe(symbol, interval, limit, Display); // NOTE: Cache is already subscribed to symbol (above). // Begin streaming. controller.Begin(); lock (_sync) _message = "(alternative usage) ...press any key to exit."; Console.ReadKey(true); // wait for user input. } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
/// <summary> /// Example with single controller using combined streams. /// </summary> /// <returns></returns> public static async Task ExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder // configure logging. .SetMinimumLevel(LogLevel.Trace) .AddFile(configuration.GetSection("Logging:File"))) .BuildServiceProvider(); Console.Clear(); // clear the display. var limit = 5; // set to 0 to use diff. depth stream (instead of partial depth stream). var api = services.GetService <IBinanceApi>(); // Create cache. var btcCache = services.GetService <IOrderBookCache>(); var ethCache = services.GetService <IOrderBookCache>(); // Create web socket stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Query and display the order books. var btcOrderBook = await api.GetOrderBookAsync(Symbol.BTC_USDT, limit); var ethOrderBook = await api.GetOrderBookAsync(Symbol.ETH_BTC, limit); Display(btcOrderBook, ethOrderBook); // Monitor order book and display updates in real-time. btcCache.Subscribe(Symbol.BTC_USDT, limit, evt => { btcOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }); // Monitor order book and display updates in real-time. ethCache.Subscribe(Symbol.ETH_BTC, limit, evt => { ethOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }); // Set web socket URI using cache subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri( btcCache.SubscribedStreams.Concat(ethCache.SubscribedStreams)); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket.Message += (s, e) => btcCache.HandleMessage(e.Subject, e.Json); webSocket.Message += (s, e) => ethCache.HandleMessage(e.Subject, e.Json); // Verify we are using a shared/combined stream (not necessary). if (!webSocket.IsCombined()) { throw new Exception("You are NOT using combined streams :("); } // Begin streaming. controller.Begin(); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
public BinanceWebSocketStreamTest() { _uri = BinanceWebSocketStream.CreateUri(_streamName); _stream = new BinanceWebSocketStream(DefaultWebSocketClientTest.CreateMockWebSocketClient(_message)); }
public static void AdvancedExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. // Get configuration settings. var symbols = configuration.GetSection("CombinedStreamsExample:Symbols").Get <string[]>() ?? new string[] { Symbol.BTC_USDT }; // Initialize the client. var client = services.GetService <ISymbolStatisticsClient>(); // Initialize the stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); if (symbols.Length == 1) { // Subscribe to symbol with callback. client.Subscribe(Display, symbols[0]); } else { // Alternative usage (combined streams). client.StatisticsUpdate += (s, evt) => { Display(evt); }; // Subscribe to all symbols. foreach (var symbol in symbols) { client.Subscribe(symbol); // using event instead of callbacks. } } // Set stream URI using client subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(client); // NOTE: This must be done after client subscribe. // Route stream messages to client. webSocket.Message += (s, e) => client.HandleMessage(e.Subject, e.Json); // Begin streaming. controller.Begin(); _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. //*////////////////////////////////////////////////// // Example: Unsubscribe/Subscribe after streaming... ///////////////////////////////////////////////////// // NOTE: When the URI is changed, the web socket is aborted // and a new connection is made. There's a delay // before streaming begins to allow for multiple // changes. // Unsubscribe a symbol. client.Unsubscribe(symbols[0]); // Subscribe to the real Bitcoin :D client.Subscribe(Symbol.BCH_USDT); // a.k.a. BCC. // Set stream URI using client subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(client); // NOTE: This must be done after client subscribe. lock (_sync) { // Remove unsubscribed symbol and clear display (application specific). _statistics.Remove(symbols[0]); Console.Clear(); } _message = "...press any key to exit."; Console.ReadKey(true); // wait for user input. ///////////////////////////////////////////////////*/ } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
public static async Task AdvancedExampleMain(string[] args) { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .AddUserSecrets <Program>() // for access to API key and secret. .Build(); // Get API key. var key = configuration["BinanceApiKey"] // user secrets configuration. ?? configuration.GetSection("User")["ApiKey"]; // appsettings.json configuration. // Get API secret. var secret = configuration["BinanceApiSecret"] // user secrets configuration. ?? configuration.GetSection("User")["ApiSecret"]; // appsettings.json configuration. // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. Console.Clear(); // clear the display. // ReSharper disable once InconsistentlySynchronizedField _limit = 5; var symbol = Symbol.BTC_USDT; var asset = symbol.BaseAsset; var api = services.GetService <IBinanceApi>(); var cache = services.GetService <IOrderBookCache>(); var webSocket = services.GetService <IBinanceWebSocketStream>(); var userProvider = services.GetService <IBinanceApiUserProvider>(); using (var user = userProvider.CreateUser(key, secret)) using (var manager = services.GetService <IUserDataWebSocketManager>()) { // Query and display order book and current asset balance. var balance = (await api.GetAccountInfoAsync(user)).GetBalance(asset); var orderBook = await api.GetOrderBookAsync(symbol, _limit); Display(orderBook, balance); // Subscribe cache to symbol with callback. cache.Subscribe(symbol, _limit, evt => Display(evt.OrderBook, balance)); // Set web socket URI using cache subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(cache); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket.Message += (s, e) => cache.HandleMessage(e.Subject, e.Json); // Subscribe to symbol to display latest order book and asset balance. await manager.SubscribeAsync <AccountUpdateEventArgs>(user, evt => { // Update asset balance. balance = evt.AccountInfo.GetBalance(asset); // Display latest order book and asset balance. Display(cache.OrderBook, balance); }); using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Begin streaming. controller.Begin(); // Optionally, wait for web socket is connected (open). await manager.WaitUntilWebSocketOpenAsync(); // Verify we are NOT using a combined streams (DEMONSTRATION ONLY). if (webSocket.IsCombined() || webSocket == manager.Client.Publisher.Stream) { throw new Exception("You ARE using combined streams :("); } lock (_sync) _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. } } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine("...press any key to continue."); Console.ReadKey(true); } }
/// <summary> /// Example using cache, web socket stream (or client), and controller. /// </summary> // ReSharper disable once UnusedMember.Local private static void AdvancedExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. Console.Clear(); // clear the display. // Get configuration settings. var limit = 10; var symbol = configuration.GetSection("OrderBook")?["Symbol"] ?? Symbol.BTC_USDT; try { limit = Convert.ToInt32(configuration.GetSection("OrderBook")?["Limit"]); } catch { /* ignore */ } // NOTE: Currently the Partial Book Depth Stream only supports limits of: 5, 10, or 20. if (limit > 10) { limit = 20; } else if (limit > 5) { limit = 10; } else if (limit > 0) { limit = 5; } // Initialize cache. var cache = services.GetService <IOrderBookCache>(); // Initialize web socket stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbol with limit and callback. // NOTE: If no limit is provided (or limit = 0) then the order book is initialized with // limit = 1000 and the diff. depth stream is used to keep order book up-to-date. cache.Subscribe(symbol, limit, Display); // Set web socket URI using cache subscribed streams. webSocket.Uri = BinanceWebSocketStream.CreateUri(cache); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket.Message += (s, e) => cache.HandleMessage(e.Subject, e.Json); // Begin streaming. controller.Begin(); lock (_sync) _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. } //*///////////////////////////////////////// // Alternative usage (with an IJsonClient). //////////////////////////////////////////// // Initialize client. var client = services.GetService <IDepthClient>(); cache.Client = client; // link [new] client to cache. // Initialize controller. using (var controller = new RetryTaskController(webSocket.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbol with limit and callback. //cache.Subscribe(symbol, limit, Display); // NOTE: Cache is already subscribed to symbol (above). // Begin streaming. controller.Begin(); lock (_sync) _message = "(alternative usage) ...press any key to exit."; Console.ReadKey(true); // wait for user input. } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
/// <summary> /// Example with multiple controllers not using combined streams. /// </summary> /// <returns></returns> public static async Task ExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // add default Binance services. .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // NOTE: Using ":" requires Microsoft.Extensions.Configuration.Binder. Console.Clear(); // clear the display. const int limit = 5; var api = services.GetService <IBinanceApi>(); // Query and display the order books. var btcOrderBook = await api.GetOrderBookAsync(Symbol.BTC_USDT, limit); var ethOrderBook = await api.GetOrderBookAsync(Symbol.ETH_BTC, limit); Display(btcOrderBook, ethOrderBook); // Create cache. var btcCache = services.GetService <IOrderBookCache>(); var ethCache = services.GetService <IOrderBookCache>(); // Create web socket streams. var webSocket1 = services.GetService <IBinanceWebSocketStream>(); var webSocket2 = services.GetService <IBinanceWebSocketStream>(); // NOTE: IBinanceWebSocketStream must be setup as Transient with DI (default). // Initialize controllers. using (var controller1 = new RetryTaskController(webSocket1.StreamAsync)) using (var controller2 = new RetryTaskController(webSocket2.StreamAsync)) { controller1.Error += (s, e) => HandleError(e.Exception); controller2.Error += (s, e) => HandleError(e.Exception); btcCache.Subscribe(Symbol.BTC_USDT, limit, evt => { btcOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }); ethCache.Subscribe(Symbol.ETH_BTC, limit, evt => { ethOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }); // Set web socket URI using cache subscribed streams. webSocket1.Uri = BinanceWebSocketStream.CreateUri(btcCache); webSocket2.Uri = BinanceWebSocketStream.CreateUri(ethCache); // NOTE: This must be done after cache subscribe. // Route stream messages to cache. webSocket1.Message += (s, e) => btcCache.HandleMessage(e.Subject, e.Json); webSocket2.Message += (s, e) => ethCache.HandleMessage(e.Subject, e.Json); // Begin streaming. controller1.Begin(); controller2.Begin(); // Verify we are NOT using a shared/combined stream (not necessary). if (webSocket1.IsCombined() || webSocket2.IsCombined() || webSocket1 == webSocket2) { throw new Exception("You ARE using combined streams :("); } Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }