private void ProcessOrderBookUpdate(BitfinexChannel channel, string[] entries) { try { var symbol = _symbolMapper.GetLeanSymbol(channel.Symbol); var orderBook = _orderBooks[symbol]; var price = decimal.Parse(entries[0], NumberStyles.Float, CultureInfo.InvariantCulture); var count = int.Parse(entries[1]); var amount = decimal.Parse(entries[2], NumberStyles.Float, CultureInfo.InvariantCulture); if (count == 0) { orderBook.RemovePriceLevel(price); } else { if (amount > 0) { orderBook.UpdateBidRow(price, amount); } else if (amount < 0) { orderBook.UpdateAskRow(price, Math.Abs(amount)); } } } catch (Exception e) { Log.Error(e); throw; } }
private void OnSubscribe(Messages.ChannelSubscription data) { try { Channel existing = null; lock (channelLocker) { if (!ChannelList.TryGetValue(data.ChannelId, out existing)) { ChannelList[data.ChannelId] = new BitfinexChannel() { ChannelId = data.ChannelId, Name = data.Channel, Symbol = data.Symbol };; } else { BitfinexChannel typedChannel = existing as BitfinexChannel; typedChannel.Name = data.Channel; typedChannel.ChannelId = data.ChannelId; typedChannel.Symbol = data.Symbol; } } } catch (Exception e) { Log.Error(e); throw; } }
private void OnUpdate(string channelId, string[] entries) { try { BitfinexChannel channel = ChannelList[channelId] as BitfinexChannel; if (channel == null) { OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, $"Message recieved from unknown channel Id {channelId}")); return; } switch (channel.Name.ToLower()) { case "book": ProcessOrderBookUpdate(channel, entries); return; case "trades": ProcessTradeUpdate(channel, entries); return; } } catch (Exception e) { Log.Error(e); throw; } }
private BitfinexWebSocketWrapper GetFreeWebSocket(BitfinexChannel channel) { int count; lock (_locker) { foreach (var kvp in _channelsByWebSocket) { if (kvp.Value.Count < MaximumSubscriptionsPerSocket) { kvp.Value.Add(channel); count = _channelsByWebSocket.Sum(x => x.Value.Count); Log.Trace($"BitfinexSubscriptionManager.GetFreeWebSocket(): Channel added: Total channels:{count}"); return(kvp.Key); } } } if (!_connectionRateLimiter.WaitToProceed(TimeSpan.Zero)) { _connectionRateLimiter.WaitToProceed(); } var webSocket = new BitfinexWebSocketWrapper( new DefaultConnectionHandler { MaximumIdleTimeSpan = TimeSpan.FromSeconds(15) }); lock (_locker) { _channelsByWebSocket.TryAdd(webSocket, new List <BitfinexChannel> { channel }); count = _channelsByWebSocket.Sum(x => x.Value.Count); Log.Trace($"BitfinexSubscriptionManager.GetFreeWebSocket(): Channel added: Total channels:{count}"); } webSocket.Initialize(_wssUrl); webSocket.Message += OnMessage; webSocket.Error += OnError; Connect(webSocket); webSocket.ConnectionHandler.ConnectionLost += OnConnectionLost; webSocket.ConnectionHandler.ConnectionRestored += OnConnectionRestored; webSocket.ConnectionHandler.ReconnectRequested += OnReconnectRequested; webSocket.ConnectionHandler.Initialize(webSocket.ConnectionId); Log.Trace("BitfinexSubscriptionManager.GetFreeWebSocket(): New websocket added: " + $"Hashcode: {webSocket.GetHashCode()}, " + $"WebSocket connections: {_channelsByWebSocket.Count}"); return(webSocket); }
private void ProcessTradesSnapshot(BitfinexChannel channel, string[][] entries) { try { var symbol = _symbolMapper.GetLeanSymbol(channel.Symbol); foreach (var entry in entries) { // pass time, price, amount EmitTradeTick(symbol, entry.Skip(1).ToArray()); } } catch (Exception e) { Log.Error(e); throw; } }
private BitfinexWebSocketWrapper SubscribeChannel(string channelName, Symbol symbol) { var ticker = _symbolMapper.GetBrokerageSymbol(symbol); var channel = new BitfinexChannel { Name = channelName, Symbol = ticker, ChannelId = string.Empty }; var webSocket = GetFreeWebSocket(channel); webSocket.Send(JsonConvert.SerializeObject(new { @event = "subscribe", channel = channelName, pair = ticker })); return(webSocket); }
private void ProcessTradeUpdate(BitfinexChannel channel, string[] entries) { try { var symbol = _symbolMapper.GetLeanSymbol(channel.Symbol); var time = Time.UnixMillisecondTimeStampToDateTime(double.Parse(entries[1], NumberStyles.Float, CultureInfo.InvariantCulture)); var amount = decimal.Parse(entries[2], NumberStyles.Float, CultureInfo.InvariantCulture); var price = decimal.Parse(entries[3], NumberStyles.Float, CultureInfo.InvariantCulture); EmitTradeTick(symbol, time, price, amount); } catch (Exception e) { Log.Error(e); throw; } }
private void ProcessTradeUpdate(BitfinexChannel channel, string[] entries) { try { string eventType = entries[0]; if (eventType == "tu") { var symbol = _symbolMapper.GetLeanSymbol(channel.Symbol); // pass time, price, amount EmitTradeTick(symbol, new[] { entries[3], entries[4], entries[5] }); } } catch (Exception e) { Log.Error(e); throw; } }
private void ProcessOrderBookSnapshot(BitfinexChannel channel, string[][] entries) { try { var symbol = _symbolMapper.GetLeanSymbol(channel.Symbol); OrderBook orderBook; if (!_orderBooks.TryGetValue(symbol, out orderBook)) { orderBook = new OrderBook(symbol); _orderBooks[symbol] = orderBook; } else { orderBook.BestBidAskUpdated -= OnBestBidAskUpdated; orderBook.Clear(); } foreach (var entry in entries) { var price = decimal.Parse(entry[0], NumberStyles.Float, CultureInfo.InvariantCulture); var amount = decimal.Parse(entry[2], NumberStyles.Float, CultureInfo.InvariantCulture); if (amount > 0) { orderBook.UpdateBidRow(price, amount); } else { orderBook.UpdateAskRow(price, Math.Abs(amount)); } } orderBook.BestBidAskUpdated += OnBestBidAskUpdated; EmitQuoteTick(symbol, orderBook.BestBidPrice, orderBook.BestBidSize, orderBook.BestAskPrice, orderBook.BestAskSize); } catch (Exception e) { Log.Error(e); throw; } }