/// <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); } }
private static async Task Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", false, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // Get configuration settings. var symbols = configuration.GetSection("Statistics:Symbols").Get <string[]>() ?? new string[] { Symbol.BTC_USDT }; var cache = services.GetService <ISymbolStatisticsCache>(); using (var controller = new RetryTaskController()) { var api = services.GetService <IBinanceApi>(); // Query and display the 24-hour statistics. Display(await Get24HourStatisticsAsync(api, symbols)); // Monitor 24-hour statistics of a symbol and display updates in real-time. if (symbols.Length == 1) { controller.Begin( tkn => cache.StreamAsync(symbols[0], evt => Display(evt.Statistics), tkn), err => Console.WriteLine(err.Message)); } else { // Alternative usage (if sharing IBinanceWebSocket for combined streams). cache.Subscribe(evt => Display(evt.Statistics), symbols); controller.Begin( tkn => cache.Client.WebSocket.StreamAsync(tkn), err => Console.WriteLine(err.Message)); } Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
public static async Task ExampleMain(string[] args) { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .AddUserSecrets <AccountBalancesExample>() .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() .AddOptions() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .Configure <UserDataWebSocketManagerOptions>(configuration.GetSection("UserDataOptions")) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); var asset = Asset.BTC; var api = services.GetService <IBinanceApi>(); var cache = services.GetService <IAccountInfoCache>(); var userProvider = services.GetService <IBinanceApiUserProvider>(); using (var user = userProvider.CreateUser(key, secret)) using (var controller = new RetryTaskController( tkn => cache.SubscribeAndStreamAsync(user, evt => Display(evt.AccountInfo.GetBalance(asset)), tkn), err => Console.WriteLine(err.Message))) { // Query and display current account balance. var account = await api.GetAccountInfoAsync(user); Display(account.GetBalance(asset)); // Display updated account balance. controller.Begin(); Console.WriteLine("...press any key to continue."); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); } }
private static void Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging").GetSection("File")); // 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 { /* ignored */ } var limit = 25; try { limit = Convert.ToInt32(configuration.GetSection("PriceChart")?["Limit"] ?? "25"); } catch { /* ignored */ } var cache = services.GetService <ICandlestickCache>(); using (var controller = new RetryTaskController()) { // Monitor latest aggregate trades and display updates in real-time. controller.Begin( tkn => cache.SubscribeAndStreamAsync(symbol, interval, limit, evt => Display(evt.Candlesticks), tkn), err => Console.WriteLine(err.Message)); // Alternative usage (if sharing IBinanceWebSocket for combined streams). //cache.Subscribe(symbol, interval, limit, evt => Display(evt.Candlesticks)); //controller.Begin( // tkn => cache.StreamAsync(tkn), // err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
private static async Task Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging").GetSection("File")); // Get configuration settings. var limit = 10; var symbol = configuration.GetSection("OrderBook")?["Symbol"] ?? Symbol.BTC_USDT; try { limit = Convert.ToInt32(configuration.GetSection("OrderBook")?["Limit"]); } catch { /* ignored */ } // NOTE: Currently the Depth WebSocket Endpoint/Client only supports maximum limit of 100. // TODO var cache = services.GetService <IOrderBookCache>(); using (var controller = new RetryTaskController()) { var api = services.GetService <IBinanceApi>(); // Query and display the order book. Display(await api.GetOrderBookAsync(symbol, limit)); // Monitor order book and display updates in real-time. controller.Begin( tkn => cache.SubscribeAsync(symbol, limit, evt => Display(evt.OrderBook), tkn), err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
private static async Task Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging").GetSection("File")); // Get configuration settings. var limit = 25; var symbol = configuration.GetSection("TradeHistory")?["Symbol"] ?? Symbol.BTC_USDT; try { limit = Convert.ToInt32(configuration.GetSection("TradeHistory")?["Limit"]); } catch { /* ignored */ } var cache = services.GetService <IAggregateTradeCache>(); using (var controller = new RetryTaskController()) { var api = services.GetService <IBinanceApi>(); // Query and display the latest aggregate trades for the symbol. Display(await api.GetAggregateTradesAsync(symbol, limit)); // Monitor latest aggregate trades and display updates in real-time. controller.Begin( tkn => cache.SubscribeAsync(symbol, limit, evt => Display(evt.Trades), tkn), err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
private static async Task Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging").GetSection("File")); // Get configuration settings. var symbol = configuration.GetSection("Statistics")?["Symbol"] ?? Symbol.BTC_USDT; var cache = services.GetService <ISymbolStatisticsCache>(); using (var controller = new RetryTaskController()) { var api = services.GetService <IBinanceApi>(); // Query and display the 24-hour statistics. Display(await api.Get24HourStatisticsAsync(symbol)); // Monitor 24-hour statistics and display updates in real-time. controller.Begin( tkn => cache.SubscribeAsync(symbol, evt => Display(evt.Statistics), tkn), err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } 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 <AccountBalancesExample>() .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. var api = services.GetService <IBinanceApi>(); var client = services.GetService <IUserDataWebSocketClient>(); var userProvider = services.GetService <IBinanceApiUserProvider>(); var streamControl = services.GetService <IUserDataWebSocketStreamControl>(); using (var user = userProvider.CreateUser(key, secret)) { // Query and display current account balance. var account = await api.GetAccountInfoAsync(user); Display(account.GetBalance(_asset)); var listenKey = await streamControl.OpenStreamAsync(user); // add user and start timer. streamControl.ListenKeyUpdate += (s, a) => { try { // Unsubscribe old listen key. Console.WriteLine($"Unsubscribe old listen key... {a.OldListenKey}"); client.Unsubscribe(a.OldListenKey); if (a.NewListenKey == null) { Console.WriteLine("! Failed to get new listen key..."); return; } Console.WriteLine($"Subscribe to new listen key... {a.NewListenKey}"); client.Subscribe <AccountUpdateEventArgs>(a.NewListenKey, user, Display); listenKey = a.NewListenKey; } catch (Exception e) { Console.WriteLine(e.Message); } }; Console.WriteLine($"Subscribe to listen key... {listenKey}"); client.Subscribe <AccountUpdateEventArgs>(listenKey, user, Display); using (var controller = new RetryTaskController(client.Stream.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Begin streaming. controller.Begin(); Console.WriteLine("...press any key to continue."); Console.ReadKey(true); } Console.WriteLine($"Unsubscribe listen key... {listenKey}"); client.Unsubscribe(listenKey); await streamControl.CloseStreamAsync(user); streamControl.Dispose(); } } catch (Exception e) { Console.WriteLine(e.Message); } }
/// <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 stream. var stream1 = services.GetService <IBinanceWebSocketStream>(); var stream2 = services.GetService <IBinanceWebSocketStream>(); // NOTE: IBinanceWebSocketStream must be setup as Transient with DI (default). // Initialize controllers. using (var controller1 = new RetryTaskController(stream1.StreamAsync)) using (var controller2 = new RetryTaskController(stream2.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); }); // Subscribe cache to stream (with observed streams). stream1.Subscribe(btcCache, btcCache.ObservedStreams); stream2.Subscribe(ethCache, ethCache.ObservedStreams); // NOTE: This must be done after cache subscribe. // Begin streaming. controller1.Begin(); controller2.Begin(); // Verify we are NOT using a shared/combined stream (not necessary). if (stream1.IsCombined() || stream2.IsCombined() || stream1 == stream2) { 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); } }
private static async Task Main() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() // Use a single web socket stream (combined streams). .AddSingleton <IWebSocketStream, BinanceWebSocketStream>() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); var limit = 5; // set to 0 to use diff. depth stream (instead of partial depth stream). var api = services.GetService <IBinanceApi>(); var btcCache = services.GetService <IOrderBookCache>(); var ethCache = services.GetService <IOrderBookCache>(); using (var controller = new RetryTaskController()) { // 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); /////////////////////////////////////////////////////////////////////////// // Use one controller and a singleton IBinanceWebSocket (combined streams). // NOTE: IWebSocketStream must be configured as Singleton in DI setup. // 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); }); // Verify we are using a shared/combined stream (not necessary). if (!btcCache.Client.WebSocket.IsCombined || btcCache.Client.WebSocket != ethCache.Client.WebSocket) { throw new Exception(":("); } controller.Begin( tkn => btcCache.Client.WebSocket.StreamAsync(tkn), err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); 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. // Get configuration settings. var limit = 25; var symbol = configuration.GetSection("TradeHistory")?["Symbol"] ?? Symbol.BTC_USDT; try { limit = Convert.ToInt32(configuration.GetSection("TradeHistory")?["Limit"]); } catch { /* ignored */ } // Initialize cache. var cache = services.GetService <IAggregateTradeCache>(); // Initialize stream. var stream = services.GetService <IBinanceWebSocketStream>(); // Initialize controller. using (var controller = new RetryTaskController(stream.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); // Subscribe cache to symbol with limit and callback. cache.Subscribe(symbol, limit, Display); // Subscribe cache to stream (with observed streams). stream.Subscribe(cache, cache.ObservedStreams); // NOTE: This must be done after cache subscribe. // Begin streaming. controller.Begin(); // ReSharper disable once InconsistentlySynchronizedField _message = "...press any key to continue."; Console.ReadKey(true); } //*//////////////////////////////////////////////////////// // Alternative usage (with an existing IJsonStreamClient). /////////////////////////////////////////////////////////// // Initialize stream/client. var client = services.GetService <IAggregateTradeWebSocketClient>(); cache.Client = client; // link [new] client to cache. // Initialize controller. using (var controller = new RetryTaskController(client.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). // NOTE: With IJsonStreamClient, stream is automagically subscribed. // Begin streaming. controller.Begin(); // ReSharper disable once InconsistentlySynchronizedField _message = "...press any key to exit."; Console.ReadKey(true); } /////////////////////////////////////////////////////////*/ } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
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() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); // Get configuration settings. var symbols = configuration.GetSection("CombinedStreamsExample:Symbols").Get <string[]>() ?? new string[] { Symbol.BTC_USDT }; var client = services.GetService <ISymbolStatisticsWebSocketClient>(); using (var controller = new RetryTaskController( tkn => client.StreamAsync(tkn), err => Console.WriteLine(err.Message))) { if (symbols.Length == 1) { // Subscribe to symbol with callback. client.Subscribe(symbols[0], evt => Display(evt.Statistics[0])); } else { // Alternative usage (combined streams). client.StatisticsUpdate += (s, evt) => { Display(evt.Statistics[0]); }; // Subscribe to all symbols. foreach (var symbol in symbols) { client.Subscribe(symbol); // using event instead of callbacks. } } // Begin streaming. controller.Begin(); _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. //*////////////////////////////////////////////////// // Example: Unsubscribe/Subscribe after streaming... // Cancel streaming. await controller.CancelAsync(); // Unsubscribe a symbol. client.Unsubscribe(symbols[0]); // Remove unsubscribed symbol and clear display (application specific). _statistics.Remove(symbols[0]); Console.Clear(); // Subscribe to the real Bitcoin :D client.Subscribe(Symbol.BCH_USDT); // a.k.a. BCC. // Begin streaming again. controller.Begin(); _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); } }
private static void ExampleMain() { try { // Load configuration. var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, false) .Build(); // Configure services. var services = new ServiceCollection() .AddBinance() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging").GetSection("File")); 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 { /* ignored */ } // 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; } var cache = services.GetService <IOrderBookCache>(); using (var controller = new RetryTaskController()) { // Monitor order book and display updates in real-time. // 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. controller.Begin( tkn => cache.SubscribeAndStreamAsync(symbol, limit, evt => Display(evt.OrderBook), tkn), err => Console.WriteLine(err.Message)); // Alternative usage (if sharing IBinanceWebSocket for combined streams). //cache.Subscribe(symbol, limit, evt => Display(evt.OrderBook)); //controller.Begin( // tkn => cache.StreamAsync(tkn), // err => Console.WriteLine(err.Message)); Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); 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. // 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); } }
public static async Task ExampleMain(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() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); Console.Clear(); // clear the display. _limit = 5; var symbol = Symbol.BTC_USDT; var asset = symbol.BaseAsset; var api = services.GetService <IBinanceApi>(); var cache = services.GetService <IOrderBookCache>(); var manager = services.GetService <IUserDataWebSocketManager>(); var userProvider = services.GetService <IBinanceApiUserProvider>(); using (var user = userProvider.CreateUser(key, secret)) { // 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); Func <CancellationToken, Task> action1 = tkn => cache.SubscribeAndStreamAsync(symbol, evt => Display(evt.OrderBook, balance), tkn); Func <CancellationToken, Task> action2 = tkn => manager.SubscribeAndStreamAsync(user, evt => { if (evt is AccountUpdateEventArgs accountUpdateEvent) { // Update asset balance. balance = accountUpdateEvent.AccountInfo.GetBalance(asset); // Display latest order book and asset balance. Display(cache.OrderBook, balance); } }, tkn); Action <Exception> onError = err => Console.WriteLine(err.Message); using (var controller1 = new RetryTaskController(action1, onError)) using (var controller2 = new RetryTaskController(action2, onError)) { // Subscribe to symbol to display latest order book and asset balance. controller1.Begin(); // Subscribe to user account information and begin streaming. controller2.Begin(); // Verify we are NOT using a combined streams (DEMONSTRATION ONLY). if (cache.Client.WebSocket.IsCombined || cache.Client.WebSocket == manager.Client.WebSocket) { throw new Exception("Using combined streams :("); } _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 close window."); Console.ReadKey(true); } }
public static void 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. // Get configuration settings. var symbols = configuration.GetSection("CombinedStreamsExample:Symbols").Get <string[]>() ?? new string[] { Symbol.BTC_USDT }; Console.Clear(); // clear the display. const int limit = 5; // Create client. var client = services.GetService <IDepthWebSocketClient>(); using (var controller = new RetryTaskController(client.StreamAsync)) { controller.Error += (s, e) => HandleError(e.Exception); if (symbols.Length == 1) { // Subscribe to symbol with callback. client.Subscribe(symbols[0], Display); } else { // Alternative usage (combined streams). client.DepthUpdate += (s, evt) => { Display(evt); }; // Subscribe to all symbols. foreach (var symbol in symbols) { client.Subscribe(symbol, limit); // using event instead of callbacks. } } // Begin streaming. controller.Begin(); _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. //*////////////////////////////////////////////////// // Example: Unsubscribe/Subscribe after streaming... ///////////////////////////////////////////////////// // NOTE: When stream names are subscribed/unsubscribed, the // websocket is aborted and a new connection is made. // There's a small delay before streaming restarts to // allow for multiple subscribe/unsubscribe changes. // Unsubscribe a symbol. client.Unsubscribe(symbols[0], limit); // Subscribe to the real Bitcoin :D client.Subscribe(Symbol.BCH_USDT, limit); // a.k.a. BCC. lock (_sync) { // Remove unsubscribed symbol and clear display (application specific). _orderBookTops.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); } }
/// <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 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() .AddLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)) .BuildServiceProvider(); // Configure logging. services.GetService <ILoggerFactory>() .AddFile(configuration.GetSection("Logging:File")); Console.Clear(); // clear the display. var 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); var btcCache = services.GetService <IOrderBookCache>(); var ethCache = services.GetService <IOrderBookCache>(); Func <CancellationToken, Task> action1 = tkn => btcCache.SubscribeAndStreamAsync(Symbol.BTC_USDT, limit, evt => { btcOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }, tkn); Func <CancellationToken, Task> action2 = tkn => ethCache.SubscribeAndStreamAsync(Symbol.ETH_BTC, limit, evt => { ethOrderBook = evt.OrderBook; Display(btcOrderBook, ethOrderBook); }, tkn); Action <Exception> onError = err => Console.WriteLine(err.Message); using (var controller1 = new RetryTaskController(action1, onError)) using (var controller2 = new RetryTaskController(action2, onError)) { ////////////////////////////////////////////////////////////////////// // Using multiple controllers and multiple (non-combined) web sockets. // NOTE: IWebSocketStream must be left as Transient in DI setup. // Monitor order book and display updates in real-time. controller1.Begin(); // Monitor order book and display updates in real-time. controller2.Begin(); // Verify we are not using a shared/combined stream (not necessary). if (btcCache.Client.WebSocket.IsCombined || ethCache.Client.WebSocket.IsCombined || btcCache.Client.WebSocket == ethCache.Client.WebSocket) { throw new Exception(":("); } Console.ReadKey(true); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine(" ...press any key to close window."); Console.ReadKey(true); } }
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. _limit = 5; var symbol = Symbol.BTC_USDT; var asset = symbol.BaseAsset; var api = services.GetService <IBinanceApi>(); var cache = services.GetService <IOrderBookCache>(); var stream = 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)); // Subscribe stream to cache observed streams. stream.Subscribe(cache, cache.ObservedStreams); // NOTE: This must be done after cache subscribe. try { // 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(stream.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 (stream.IsCombined() || stream == manager.Controller.Stream) { throw new Exception("You ARE using combined streams :("); } _message = "...press any key to continue."; Console.ReadKey(true); // wait for user input. } } finally { stream.Unsubscribe(); } } } 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 stream. var webSocket = services.GetService <IBinanceWebSocketStream>(); 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); // Subscribe cache to stream (with observed streams). webSocket.Subscribe(cache, cache.ObservedStreams); // NOTE: This must be done after cache subscribe. // Begin streaming. controller.Begin(); lock (_sync) { _message = "...press any key to continue."; } Console.ReadKey(true); // wait for user input. } //*//////////////////////////////////////////////////////// // Alternative usage (with an existing IJsonStreamClient). /////////////////////////////////////////////////////////// // Initialize stream/client. var client = services.GetService <IDepthWebSocketClient>(); cache.Client = client; // link [new] client to cache. // Initialize controller. using (var controller = new RetryTaskController(client.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). // NOTE: With IJsonStreamClient, stream is automagically subscribed. // Begin streaming. controller.Begin(); lock (_sync) { _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); } }