/// <summary> /// Emits a new quote tick /// </summary> /// <param name="symbol">The symbol</param> /// <param name="bidPrice">The bid price</param> /// <param name="bidSize">The bid size</param> /// <param name="askPrice">The ask price</param> /// <param name="askSize">The ask price</param> private void EmitQuoteTick(Symbol symbol, decimal bidPrice, decimal bidSize, decimal askPrice, decimal askSize) { _aggregator.Update(new Tick { AskPrice = askPrice, BidPrice = bidPrice, Value = (askPrice + bidPrice) / 2m, Time = DateTime.UtcNow, Symbol = symbol, TickType = TickType.Quote, AskSize = askSize, BidSize = bidSize }); }
private void ProcessEquityTrade(EquityTradeMessage trade) { var symbol = _symbolMapper.GetLeanSymbol(trade.Symbol, SecurityType.Equity, Market.USA); var time = GetTickTime(symbol, trade.Timestamp); var tick = new Tick { TickType = TickType.Trade, Symbol = symbol, Time = time, Value = trade.Price, Quantity = trade.Size }; _dataAggregator.Update(tick); }
/// <summary> /// Emit stream tick /// </summary> /// <param name="tick"></param> private void EmitTick(Tick tick) { lock (TickLocker) { _aggregator.Update(tick); } }
/// <summary> /// Pumps a bunch of ticks into the queue /// </summary> private void PopulateQueue() { List <Symbol> symbols; lock (_sync) { symbols = _symbols.ToList(); } foreach (var symbol in symbols) { // emits 500k per second for (var i = 0; i < 500000; i++) { _aggregator.Update(new Tick { Time = DateTime.Now, Symbol = symbol, Value = 10 + (decimal)Math.Abs(Math.Sin(DateTime.Now.TimeOfDay.TotalMinutes)), TickType = TickType.Trade, Quantity = _random.Next(10, (int)_timer.Interval) }); } } }
internal void ProcessJsonObject(JObject message) { try { // https://iextrading.com/developer/#tops-tops-response var symbolString = message["symbol"].Value <string>(); Symbol symbol; if (!_symbols.TryGetValue(symbolString, out symbol)) { if (_subscribedToAll) { symbol = Symbol.Create(symbolString, SecurityType.Equity, Market.USA); } else { Log.Trace("IEXDataQueueHandler.ProcessJsonObject(): Received unexpected symbol '" + symbolString + "' from IEX in IEXDataQueueHandler"); return; } } var bidSize = message["bidSize"].Value <long>(); var bidPrice = message["bidPrice"].Value <decimal>(); var askSize = message["askSize"].Value <long>(); var askPrice = message["askPrice"].Value <decimal>(); var volume = message["volume"].Value <int>(); var lastSalePrice = message["lastSalePrice"].Value <decimal>(); var lastSaleSize = message["lastSaleSize"].Value <int>(); var lastSaleTime = message["lastSaleTime"].Value <long>(); var lastSaleDateTime = _unixEpoch.AddMilliseconds(lastSaleTime); var lastUpdated = message["lastUpdated"].Value <long>(); if (lastUpdated == -1) { // there were no trades on this day return; } var lastUpdatedDatetime = _unixEpoch.AddMilliseconds(lastUpdated); var tick = new Tick() { Symbol = symbol, Time = lastUpdatedDatetime.ConvertFromUtc(TimeZones.NewYork), TickType = lastUpdatedDatetime == lastSaleDateTime ? TickType.Trade : TickType.Quote, Exchange = "IEX", BidSize = bidSize, BidPrice = bidPrice, AskSize = askSize, AskPrice = askPrice, Value = lastSalePrice, Quantity = lastSaleSize }; _aggregator.Update(tick); } catch (Exception err) { // this method should never fail Log.Error("IEXDataQueueHandler.ProcessJsonObject(): " + err.Message); } }
/// <summary> /// Pumps a bunch of ticks into the queue /// </summary> private void PopulateQueue() { List <Symbol> symbols; lock (_sync) { symbols = _symbols.ToList(); } foreach (var symbol in symbols) { var offsetProvider = GetTimeZoneOffsetProvider(symbol); var trades = SubscriptionManager.DefaultDataTypes()[symbol.SecurityType].Contains(TickType.Trade); var quotes = SubscriptionManager.DefaultDataTypes()[symbol.SecurityType].Contains(TickType.Quote); // emits 500k per second for (var i = 0; i < 500000; i++) { var now = TimeProvider.GetUtcNow(); if (trades) { _count++; _aggregator.Update(new Tick { Time = offsetProvider.ConvertFromUtc(now), Symbol = symbol, Value = 10 + (decimal)Math.Abs(Math.Sin(now.TimeOfDay.TotalMinutes)), TickType = TickType.Trade, Quantity = _random.Next(10, (int)_timer.Interval) }); } if (quotes) { _count++; var bid = 10 + (decimal)Math.Abs(Math.Sin(now.TimeOfDay.TotalMinutes)); var bidSize = _random.Next(10, (int)_timer.Interval); var askSize = _random.Next(10, (int)_timer.Interval); var time = offsetProvider.ConvertFromUtc(now); _aggregator.Update(new Tick(time, symbol, "", "", bid, bidSize, bid * 1.01m, askSize)); } } } }
private void EmitQuoteTick(Symbol symbol, decimal bidPrice, decimal bidSize, decimal askPrice, decimal askSize) { var tick = new Tick { AskPrice = askPrice, BidPrice = bidPrice, Time = DateTime.UtcNow, Symbol = symbol, TickType = TickType.Quote, AskSize = askSize, BidSize = bidSize }; tick.SetValue(); lock (TickLocker) { _aggregator.Update(tick); } }
private void OnTrade(object sender, Trade trade) { try { var symbol = GetSymbolUsingCache(trade.symbol_id); if (symbol == null) { return; } var tick = new Tick(trade.time_exchange, symbol, string.Empty, string.Empty, quantity: trade.size, price: trade.price); lock (symbol) { _dataAggregator.Update(tick); } } catch (Exception e) { Log.Error(e); } }
private void OnTrade(object sender, Trade trade) { try { var tick = new Tick { Symbol = _symbolMapper.GetLeanSymbol(trade.symbol_id, SecurityType.Crypto, string.Empty), Time = trade.time_exchange, Value = trade.price, Quantity = trade.size, TickType = TickType.Trade }; lock (_locker) { _dataAggregator.Update(tick); } } catch (Exception e) { Log.Error(e); } }
private void Emit(BaseData tick) { _aggregator.Update(tick); Interlocked.Increment(ref _dataQueueCount); }
/// <summary> /// Emit stream tick /// </summary> /// <param name="tick"></param> public void EmitTick(Tick tick) { _aggregator.Update(tick); }
/// <summary> /// Emit ticks /// </summary> /// <param name="tick">The new tick to emit</param> protected void EmitTick(Tick tick) { Aggregator.Update(tick); }
private void ProcessJsonObject(string json) { try { var dataList = JsonConvert.DeserializeObject <List <StreamResponseStocksUS> >(json); foreach (var item in dataList) { var symbolString = item.Symbol; Symbol symbol; if (!_symbols.TryGetValue(symbolString, out symbol)) { // Symbol is no loner in dictionary, it may be the stream not has been updated yet, // and the old client is still sending messages for unsubscribed symbols - // so there can be residual messages for the symbol, which we must skip continue; } var lastPrice = item.IexRealtimePrice ?? 0; var lastSize = item.IexRealtimeSize ?? 0; // Refers to the last update time of iexRealtimePrice in milliseconds since midnight Jan 1, 1970 UTC or -1 or 0. // If the value is -1 or 0, IEX has not quoted the symbol in the trading day. var lastUpdateMillis = item.IexLastUpdated ?? 0; if (lastUpdateMillis <= 0) { continue; } // (!) Epoch timestamp in milliseconds of the last market hours trade excluding the closing auction trade. var lastTradeMillis = item.LastTradeTime ?? 0; if (lastTradeMillis <= 0) { continue; } // If there is a last trade time but no last price or size - this is an error if (lastPrice == 0 || lastSize == 0) { throw new InvalidOperationException("ProcessJsonObject(): Invalid price & size."); } // Check if there is a kvp entry for a symbol long value; var isInDictionary = _iexLastTradeTime.TryGetValue(symbolString, out value); // We should update with trade-tick if: // - there exist an entry for a symbol and new trade time is different from time in dictionary // - not in dictionary, means the first trade-tick case if (isInDictionary && value != lastTradeMillis || !isInDictionary) { var lastTradeDateTime = UnixEpoch.AddMilliseconds(lastTradeMillis); var lastTradeTimeNewYork = lastTradeDateTime.ConvertFromUtc(TimeZones.NewYork); var tradeTick = new Tick() { Symbol = symbol, Time = lastTradeTimeNewYork, TickType = TickType.Trade, Value = lastPrice, Quantity = lastSize }; _aggregator.Update(tradeTick); _iexLastTradeTime[symbolString] = lastTradeMillis; } } } catch (Exception err) { Log.Error("IEXDataQueueHandler.ProcessJsonObject(): " + err.Message); } }