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");
            }
        }