private unsafe void TradeUpdate(LimeQuoteMessage message) { var trade = (LimeQuotesInterop.trade_msg *)message.Ptr; uint symbolIndex = Reverse(trade->common.symbol_index); var symbol = FindSymbol(symbolIndex); var symbolInfo = Factory.Symbol.LookupSymbol(symbol); var handler = symbolHandlers[symbolInfo.BinaryIdentifier]; double price = LimeQuoteMessage.priceToDouble(trade->common.price_mantissa, trade->common.price_exponent); uint totalVolume = Reverse(trade->total_volume); handler.Last = price; handler.LastSize = (int)totalVolume; if (UseLocalTickTime) { SetLocalTickTIme(handler); if (trace) { log.TraceFormat("Trade {0} at {1} ", symbol, price); } //handler.SendQuote(); } else { // is simulator. var ordertime = trade->common.timestamp | ((long)trade->common.order_id << 32); SetSimulatorTime(handler, ordertime); if (trace) { log.TraceFormat("Trade {0} at {1} time: {2}", symbol, price, new TimeStamp(ordertime)); } //handler.SendQuote(); } handler.SendTimeAndSales(); }
public unsafe static void LogMessage(byte *message, Log log) { ushort length = (ushort)((message[0] << 8) | message[1]); if (length < 3) { return; } var messageType = (LimeQuotesInterop.limeq_message_type)message[2]; string logMessage = ""; string symbol = ""; switch (messageType) { case LimeQuotesInterop.limeq_message_type.LOGIN_RESPONSE: var lrm = (LimeQuotesInterop.login_response_msg *)message; logMessage = string.Format("Login Response ({1} bytes) Ver={5}.{6}, Resp={3}, heartbeat={2}, timeout={5}", messageType, length, lrm->heartbeat_interval, lrm->response_code, lrm->timeout_interval, lrm->ver_major, lrm->ver_minor); break; case LimeQuotesInterop.limeq_message_type.BOOK_REBUILD: var br = (LimeQuotesInterop.book_rebuild_msg *)message; int symLength = 0; for (int i = 0; i < 21; i++) { if (br->symbol[i] == 0) { symLength = i; break; } } symbol = new string((sbyte *)br->symbol, 0, symLength); logMessage = string.Format("Book rebuild symbol '{0}' flags: {1} index {2}", symbol, br->symbol_flags, Reverse(br->symbol_index)); break; case LimeQuotesInterop.limeq_message_type.ORDER: var order = (LimeQuotesInterop.order_msg *)message; logMessage = string.Format("Order id {0}: symbol '{1}' price {6} timestamp {2} side {3} shares {4} flags {5}", order->common.order_id, GetSymbol(order->common.symbol_index), order->common.timestamp, order->common.side, Reverse(order->common.shares), order->common.quote_flags, LimeQuoteMessage.priceToDouble(order->common.price_mantissa, order->common.price_exponent)); break; case LimeQuotesInterop.limeq_message_type.TRADE: var trade = (LimeQuotesInterop.trade_msg *)message; logMessage = string.Format("Trade id {0}: symbol '{1}' price {10} timestamp {2} size {3} shared {4} flags {5} fill {6} fill2 {7} flags {8} total vol {9}", trade->common.order_id, GetSymbol(trade->common.symbol_index), trade->common.timestamp, trade->common.side, Reverse(trade->common.shares), trade->common.quote_flags, trade->fill1, Reverse(trade->fill2), trade->flags, Reverse(trade->total_volume), LimeQuoteMessage.priceToDouble(trade->common.price_mantissa, trade->common.price_exponent) ); break; default: logMessage = string.Format("Message {0} ({1} bytes)", messageType, length); break; } log.Trace(logMessage); log.Trace("Message HexDump: " + Environment.NewLine + HexDump(message, length, 32)); }
private unsafe void OrderUpdate(LimeQuoteMessage message) { LimeQuotesInterop.order_msg *order = (LimeQuotesInterop.order_msg *)message.Ptr; bool isTopOfBook = (order->common.quote_flags & 1) == 1; uint symbolIndex = Reverse(order->common.symbol_index); var symbol = FindSymbol(symbolIndex); bool bookUpdate = true; if (!_IDToBookRebuild.TryGetValue(symbolIndex, out bookUpdate)) { bookUpdate = true; } if (isTopOfBook) { SymbolHandler handler; try { SymbolInfo symbolInfo = Factory.Symbol.LookupSymbol(symbol); handler = symbolHandlers[symbolInfo.BinaryIdentifier]; } catch (ApplicationException) { log.Info("Received tick: " + new string(message.DataIn.ReadChars(message.Remaining))); throw; } // For the simulator, it should send the Ask first, then the bid. However, the test code expects // both prices to appear in one quote. So we cache the ask, then send the quote on the bid. bool sendQuote = false; double price = LimeQuoteMessage.priceToDouble(order->common.price_mantissa, order->common.price_exponent); long ordertime = order->common.timestamp | ((long)order->common.order_id << 32); if (order->common.side == LimeQuotesInterop.quote_side.SELL) { handler.Ask = price; handler.AskSize = (int)Reverse(order->common.shares); if (trace) { log.TraceFormat("Ask {0} at {1} size {2} time: {3}", symbol, price, handler.AskSize, new TimeStamp(ordertime)); } } else { handler.Bid = price; handler.BidSize = (int)Reverse(order->common.shares); if (trace) { log.TraceFormat("Bid {0} at {1} size {2} time: {3}", symbol, price, handler.BidSize, new TimeStamp(ordertime)); } sendQuote = true; } //TODO: Translate Cirtris timestamp to internal if (UseLocalTickTime) { if (trace) { log.TraceFormat("{0}: Bid {1} Ask: {2} BidShares {3} AskShares: {4}", symbol, handler.Bid, handler.Ask, handler.BidSize, handler.AskSize); } SetLocalTickTIme(handler); handler.SendQuote(); } else { // is simulator. if (sendQuote) { SetSimulatorTime(handler, ordertime); handler.SendQuote(); } } } else if (trace) { log.TraceFormat("Quote not top of book"); } }