private unsafe void BookRebuild(LimeQuoteMessage message)
        {
            //UNDONE: Use the symbol_len field from the message and the action to filter
            LimeQuotesInterop.book_rebuild_msg *bookMsg = (LimeQuotesInterop.book_rebuild_msg *)message.Ptr;
            int last = 0;

            for (int i = 0; i < LimeQuotesInterop.SYMBOL_LEN; i++)
            {
                if (bookMsg->symbol[i] == 0)
                {
                    last = i;
                    break;
                }
            }
            string symbol = new string((sbyte *)bookMsg->symbol, 0, last);

            log.InfoFormat("Book Rebuild for {0} id {1} flags {2}", symbol, bookMsg->symbol_index, bookMsg->symbol_flags);

            using (_SymbolIDLock.Using())
            {
                uint id = Reverse(bookMsg->symbol_index);
                if (!_SymbolID.ContainsKey(symbol))
                {
                    _SymbolID.Add(symbol, id);
                    _IDToSymbol.Add(id, symbol);
                    _IDToBookRebuild.Add(id, (bookMsg->symbol_flags & 1) == 0);
                }
                else
                {
                    _SymbolID[symbol]    = id;
                    _IDToSymbol[id]      = symbol;
                    _IDToBookRebuild[id] = (bookMsg->symbol_flags & 1) == 0;
                }
            }
        }
        protected override void ReceiveMessage(LimeQuoteMessage message)
        {
            switch (message.MessageType)
            {
            case LimeQuotesInterop.limeq_message_type.SUBSCRIPTION_REPLY:
                SubscriptionReply(message);
                break;

            case LimeQuotesInterop.limeq_message_type.BOOK_REBUILD:
                BookRebuild(message);
                break;

            case LimeQuotesInterop.limeq_message_type.TRADE:
                TradeUpdate(message);
                break;

            case LimeQuotesInterop.limeq_message_type.ORDER:
                OrderUpdate(message);
                break;

            case LimeQuotesInterop.limeq_message_type.MOD_EXECUTION:
                ModExecution(message);
                break;

            default:
                log.InfoFormat("Message {0} not handled", message.MessageType);
                break;
            }
        }
        static readonly string BATS = "BATS"; // Citirus Demo server
        private unsafe void RequestStartSymbol(SymbolInfo symbol, Agent symbolAgent)
        {
            StartSymbolHandler(symbol, symbolAgent);
            if (symbol.OptionChain != OptionChain.None)
            {
                //TODO: Implement options
                throw new NotSupportedException();
                //StartSymbolOptionHandler(symbol, symbolAgent);
            }

            LimeQuoteMessage message = (LimeQuoteMessage)Socket.MessageFactory.Create();

            LimeQuotesInterop.subscription_request_msg *subRequest = (LimeQuotesInterop.subscription_request_msg *)message.Ptr;

            subRequest->msg_type = LimeQuotesInterop.limeq_message_type.SUBSCRIPTION_REQUEST;
            ushort msgLength = (ushort)(sizeof(LimeQuotesInterop.subscription_request_msg) - 64 + symbol.Symbol.Length + 1);

            subRequest->msg_len = Reverse(msgLength);
            message.Length      = msgLength;

            //TODO: Fix to use user selected qsid
            for (int i = 0; i < 4; i++)
            {
                subRequest->qsid[i] = (byte)BATS[i];
            }
            subRequest->flags       = LimeQuotesInterop.subscription_flags.SUBSCRIPTION_FLAG_MARKET_DATA;
            subRequest->num_symbols = 1;
            for (int i = 0; i < symbol.Symbol.Length; i++)
            {
                subRequest->syb_symbols[i] = (byte)symbol.Symbol[i];
            }
            subRequest->syb_symbols[symbol.Symbol.Length] = 0;
            log.InfoFormat("Sending subscrption request for {0}", symbol.Symbol);
            while (!Socket.TrySendMessage(message))
            {
                if (IsInterrupted)
                {
                    return;
                }
                Factory.Parallel.Yield();
            }

            //TODO: Options not yet implemented

            EventItem item;

            if (symbol.DisableRealtimeSimulation)
            {
                item = new EventItem(symbol, EventType.StartBroker);
                symbolAgent.SendEvent(item);
            }

            item = new EventItem(symbol, EventType.StartRealTime);
            symbolAgent.SendEvent(item);
        }
 private unsafe void SubscriptionReply(LimeQuoteMessage message)
 {
     LimeQuotesInterop.subscription_reply_msg *subReply = (LimeQuotesInterop.subscription_reply_msg *)message.Ptr;
     if (subReply->outcome != LimeQuotesInterop.subscription_outcome.SUBSCRIPTION_SUCCESSFUL)
     {
         log.ErrorFormat("Subscription request failed: error code {0}", subReply->outcome.ToString());
     }
     else
     {
         log.InfoFormat("Subscription started");
     }
 }
        public unsafe override void SendLogin()
        {
            Socket.MessageFactory = new MessageFactoryLimeQuotes();
            LimeQuoteMessage message = (LimeQuoteMessage)Socket.MessageFactory.Create();

            LimeQuotesInterop.login_request_msg *loginRequest =
                (LimeQuotesInterop.login_request_msg *)message.Ptr;
            ushort msgLength = (ushort)sizeof(LimeQuotesInterop.login_request_msg);

            loginRequest->msg_len   = Swap(msgLength);
            loginRequest->msg_type  = LimeQuotesInterop.limeq_message_type.LOGIN_REQUEST;
            loginRequest->auth_type = LimeQuotesInterop.auth_types.CLEAR_TEXT;

            message.Length = msgLength;
            for (int i = 0; i < UserName.Length; i++)
            {
                loginRequest->uname[i] = (byte)UserName[i];
            }
            for (int i = 0; i < Password.Length; i++)
            {
                loginRequest->passwd[i] = (byte)Password[i];
            }
            for (int i = 0; i < LimeQuotesInterop.HOST_ID_LEN; i++)
            {
                loginRequest->host_id[i] = 0;
            }
            loginRequest->session_type       = LimeQuotesInterop.app_type.CPP_API;
            loginRequest->heartbeat_interval = LimeQuotesInterop.heartbeat;
            loginRequest->timeout_interval   = LimeQuotesInterop.heartbeatTimeout;
            loginRequest->ver_major          = LimeQuotesInterop.majorVersion;
            loginRequest->ver_minor          = LimeQuotesInterop.minorVersion;

            if (trace)
            {
                log.Trace("Sending: " + UserName);
            }
            if (debug)
            {
                log.Debug("Sending: " + UserName);
            }

            while (!Socket.TrySendMessage(message))
            {
                if (IsInterrupted)
                {
                    return;
                }
                Factory.Parallel.Yield();
            }
        }
        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 override bool VerifyLogin()
        {
            bool    verified = false;
            Message message;

            if (!Socket.TryGetMessage(out message))
            {
                return(verified);
            }
            LimeQuoteMessage limeMessage = (LimeQuoteMessage)message;

            if (limeMessage.MessageType == LimeQuotesInterop.limeq_message_type.LOGIN_RESPONSE)
            {
                LimeQuotesInterop.login_response_msg *response = (LimeQuotesInterop.login_response_msg *)limeMessage.Ptr;
                if (response->response_code == LimeQuotesInterop.reject_reason_code.LOGIN_SUCCEEDED)
                {
                    log.Info("Lime Login verified");
                    verified = true;
                }
                else
                {
                    log.ErrorFormat("Lime Quotes Login Failed: {0}", response->response_code.ToString());
                }
            }
            else if (limeMessage.MessageType == LimeQuotesInterop.limeq_message_type.LIMEQ_CONTROL)
            {
                var response = (LimeQuotesInterop.limeq_control_msg *)limeMessage.Ptr;
                log.InfoFormat("Lime Control {0}", response->code);
            }
            else
            {
                log.ErrorFormat("Lime unexpected message {0}", limeMessage.MessageType);
            }

            return(verified);
        }
        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 TimeAndSalesUpdate(LimeQuoteMessage message)
 {
     throw new NotImplementedException();
 }
예제 #10
0
        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");
            }
        }
예제 #11
0
 protected abstract void ReceiveMessage(LimeQuoteMessage message);