/// <summary> /// Return discrete clone of limit order book (thread-safe) /// </summary> public LimitOrderBook Clone() { LimitOrderBook result = new LimitOrderBook(Symbol, Exchange); lock (_lock) { result.Bid = Bid.Clone(); result.Ask = Ask.Clone(); } return(result); }
/// <summary> /// AggregatedLimitOrderBook constructor /// </summary> /// <param name="orderBook">Limit order book</param> public AggregatedLimitOrderBook(LimitOrderBook orderBook) : this(orderBook, -1) { }
/// <summary> /// AggregatedLimitOrderBook constructor /// </summary> /// <param name="orderBook">Limit order book</param> /// <param name="maximumPriceLevels">Number of aggregate price levels to calculate</param> public AggregatedLimitOrderBook(LimitOrderBook orderBook, int maximumPriceLevels) { Bid = GeneratePriceLevels(orderBook.Bid, maximumPriceLevels); Ask = GeneratePriceLevels(orderBook.Ask, maximumPriceLevels); }
/// <summary> /// Processes the Spark update event provided in the EventFeedArgs and updates security properties based on the event type /// </summary> /// <param name="sender">Event sender</param> /// <param name="eventFeedArgs">Event feed args</param> internal void EventReceived(object sender, EventFeedArgs eventFeedArgs) { //Process event Spark.Event eventItem = eventFeedArgs.Event; switch (eventItem.Type) { //Depth update case Spark.EVENT_NEW_DEPTH: case Spark.EVENT_AMEND_DEPTH: case Spark.EVENT_DELETE_DEPTH: //Check if exchange order book exists and create if it doesn't LimitOrderBook orderBook; if (!OrderBooks.TryGetValue(eventFeedArgs.Exchange, out orderBook)) { orderBook = new LimitOrderBook(eventFeedArgs.Symbol, eventFeedArgs.Exchange); OrderBooks.Add(eventFeedArgs.Exchange, orderBook); } //Submit update to appropriate exchange order book orderBook.SubmitEvent(eventItem); if (OnDepthUpdate != null) { OnDepthUpdate(this, new GenericEventArgs <LimitOrderBook>(eventFeedArgs.TimeStamp, orderBook)); } break; //Trade update case Spark.EVENT_TRADE: //Create and store trade record Trade trade = eventItem.ToTrade(eventFeedArgs.Symbol, eventFeedArgs.Exchange, eventFeedArgs.TimeStamp); Trades.Add(trade); if (OnTradeUpdate != null) { OnTradeUpdate(this, new GenericEventArgs <Trade>(eventFeedArgs.TimeStamp, trade)); } break; //Trade cancel case Spark.EVENT_CANCEL_TRADE: //Find original trade in trade record and delete Trade cancelledTrade = eventItem.ToTrade(eventFeedArgs.TimeStamp); Trade originalTrade = Trades.Find(x => (x.TimeStamp == cancelledTrade.TimeStamp && x.Price == cancelledTrade.Price && x.Volume == cancelledTrade.Volume)); if (originalTrade != null) { Trades.Remove(originalTrade); } break; //Market state update case Spark.EVENT_STATE_CHANGE: State = ApiFunctions.ConvertToMarketState(eventItem.State); if (OnMarketStateUpdate != null) { OnMarketStateUpdate(this, new GenericEventArgs <MarketState>(eventFeedArgs.TimeStamp, State)); } break; //Market quote update (change to best market bid-ask prices) case Spark.EVENT_QUOTE: if (OnQuoteUpdate != null) { LimitOrderBook depth = OrderBooks[eventFeedArgs.Exchange]; MarketQuote quote = new MarketQuote(eventFeedArgs.Symbol, eventFeedArgs.Exchange, depth.BidPrice, depth.AskPrice, eventFeedArgs.TimeStamp); OnQuoteUpdate(this, new GenericEventArgs <MarketQuote>(eventFeedArgs.TimeStamp, quote)); } break; //IAP (Indicative Auction Price) Update case Spark.EVENT_AUCTION_PRICE: break; default: //Console.WriteLine(eventItem.ToOutputString()); break; } }