Example #1
0
        public bool OnOrderUpdate(WebSocket.IMessageIn msg, out OrderBookDelta delta, out Trade trade)
        {
            delta = new OrderBookDelta()
            {
                Time     = msg.Time,
                Bids     = new List <PriceLevel>(),
                Asks     = new List <PriceLevel>(),
                Sequence = msg.Sequence,
            };
            trade = new Trade()
            {
                Time = msg.Time,
                Side = msg.Side,
            };
            if (msg.Sequence > _seqNum + 1)
            {
                _log.Warn("Detected a gap in sequence numbers for {0}: {1} => {2}",
                          msg.ProductId, _seqNum, msg.Sequence);
                return(false);
            }
            if (msg.Sequence <= _seqNum)
            {
                _log.Info("Ignoring message with sequence {0} for {1}: already at {2}",
                          msg.Sequence, msg.ProductId, _seqNum);
                return(true);
            }
            var book_side  = msg.Side == Side.Buy ? _bids : _asks;
            var delta_side = msg.Side == Side.Buy ? delta.Bids : delta.Asks;

            // It's important that Visit() doesn't modify book_side if it throws.
            msg.Visit(new MessageHandler(book_side, delta_side, trade));
            _seqNum = msg.Sequence;
            return(true);
        }
Example #2
0
        void RefreshOrderBook(string product, OrderBookBuilder book)
        {
            // Coinbase doesn't give us server time together with the full order book,
            // so we retrieve it with a separate request BEFORE requesting the order book.
            DateTime serverTime = _restClient.SendRequest(new REST.TimeRequest()).Result.Time;

            REST.OrderBookResponse snapshot =
                _restClient.SendRequest(new REST.OrderBookRequest()
            {
                Product = product
            }).Result;
            DateTime       received = DateTime.UtcNow;
            OrderBookDelta delta    = book.OnSnapshot(serverTime, snapshot); // Throws if the snapshot is malformed.

            if (delta != null && (delta.Bids.Any() || delta.Asks.Any()))
            {
                try
                {
                    OnOrderBook?.Invoke(
                        product,
                        new TimestampedMsg <OrderBookDelta>()
                    {
                        Received = received, Value = delta
                    });
                }
                catch (Exception e)
                {
                    _log.Warn(e, "Ignoring exception from OnOrderBook");
                }
            }
        }
Example #3
0
        public OrderBookDelta OnSnapshot(DateTime serverTime, REST.OrderBookResponse snapshot)
        {
            Condition.Requires(snapshot, "snapshot").IsNotNull();
            Condition.Requires(snapshot.Sequence, "snapshot.Sequence").IsGreaterOrEqual(_seqNum);
            var bids  = Aggregate(snapshot.Bids);
            var asks  = Aggregate(snapshot.Asks);
            var delta = new OrderBookDelta()
            {
                Time     = serverTime,
                Bids     = Diff(_bids, bids).ToList(),
                Asks     = Diff(_asks, asks).ToList(),
                Sequence = snapshot.Sequence,
            };

            delta.Bids.Reverse();
            _seqNum = snapshot.Sequence;
            _bids   = bids;
            _asks   = asks;
            return(delta);
        }
Example #4
0
        void OnMessage(TimestampedMsg <WebSocket.IMessageIn> msg)
        {
            Condition.Requires(msg, "msg").IsNotNull();
            Condition.Requires(msg.Value, "msg.Value").IsNotNull();
            Condition.Requires(msg.Value.ProductId, "msg.Value.ProductId").IsNotNullOrEmpty();
            Condition.Requires(_products.ContainsKey(msg.Value.ProductId));

            bool myFill = _orderManager.OnMessage(msg);

            OrderBookBuilder book  = _products[msg.Value.ProductId];
            OrderBookDelta   delta = null;
            Trade            trade = null;
            bool             ok    = false;

            try
            {
                ok = book.OnOrderUpdate(msg.Value, out delta, out trade);
            }
            catch (Exception e)
            {
                _log.Error(e, "Unable to process order update");
            }

            if (ok)
            {
                if (!myFill && trade != null && trade.Size > 0m)
                {
                    try
                    {
                        OnTrade?.Invoke(
                            msg.Value.ProductId,
                            new TimestampedMsg <Trade>()
                        {
                            Received = msg.Received, Value = trade
                        });
                    }
                    catch (Exception e)
                    {
                        _log.Warn(e, "Ignoring exception from OnTrade");
                    }
                }
                if (delta != null && (delta.Bids.Any() || delta.Asks.Any()))
                {
                    try
                    {
                        OnOrderBook?.Invoke(
                            msg.Value.ProductId,
                            new TimestampedMsg <OrderBookDelta>()
                        {
                            Received = msg.Received, Value = delta
                        });
                    }
                    catch (Exception e)
                    {
                        _log.Warn(e, "Ignoring exception from OnOrderBook");
                    }
                }
            }
            else
            {
                RefreshOrderBook(msg.Value.ProductId, book);
            }
        }