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); } } }
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); } } }
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)); } }
/// <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()); }); }
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(); }
/// <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()); }
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(); }
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)); } }
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); } }
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); }
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); }
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)); }
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); } } }
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); }
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)); }