Exemplo n.º 1
0
        private async Task HandleOrderEventAsync(string productId, long orderEventSequenceNumber,
                                                 OrderBookEventType eventType, OrderBookItem orderBookItem)
        {
            // Queue this item if the order book is not fully populated yet
            var orderBookExists =
                _symbolsLastSequenceNumbers.TryGetValue(productId, out long seqNumberInOrderBook) &&
                TryGetOrderBookSnapshot(productId, out var _);

            if (!orderBookExists)
            {
                QueueItem(productId, new GdaxQueueOrderItem(orderEventSequenceNumber,
                                                            eventType, orderBookItem));
                return;
            }

            // Dequeue all items in the order events queue
            foreach (var queuedItem in DequeuOrderItems(productId)
                     .Where(q => q.SequenceNumber > seqNumberInOrderBook))
            {
                await HandleOrdersEventsAsync(productId, queuedItem.OrderBookEventType,
                                              new[] { queuedItem.OrderBookItem });
            }

            // Handle the current item
            if (orderEventSequenceNumber > seqNumberInOrderBook)
            {
                await HandleOrdersEventsAsync(productId, eventType, new[] { orderBookItem });
            }
        }
Exemplo n.º 2
0
        private async Task HandleTableResponse(MarketDataSnapshotFullRefresh snapshot)
        {
            var symbol = snapshot.Symbol.Obj;

            var equFun   = new Func <OrderBookItem, OrderBookItem, bool>((item1, item2) => item1.Id == item2.Id);
            var hashFunc = new Func <OrderBookItem, int>(item => item.Id.GetHashCode());
            var orders   = new List <OrderBookItem>();

            for (var j = 1; j <= snapshot.NoMDEntries.Obj; j++)
            {
                var ob    = snapshot.GetGroup(j, new MarketDataSnapshotFullRefresh.NoMDEntriesGroup());
                var dir   = ob.GetField(new MDEntryType()).Obj;
                var price = ob.GetField(new MDEntryPx()).Obj;
                var size  = ob.GetField(new MDEntrySize()).Obj;
                var id    = long.Parse(ob.GetField(new QuoteEntryID()).Obj);

                var ordeItem = new OrderBookItem(equFun, hashFunc)
                {
                    Id     = id.ToString(),
                    Symbol = symbol,
                    IsBuy  = dir == MDEntryType.BID,
                    Price  = price,
                    Size   = size
                };
                orders.Add(ordeItem);
            }

            await HandleOrderBookSnapshotAsync(symbol, DateTime.UtcNow, orders);
        }
Exemplo n.º 3
0
 public GdaxQueueOrderItem(long sequenceNumber,
                           OrderBookEventType orderBookEventType, OrderBookItem orderBookItem)
 {
     SequenceNumber     = sequenceNumber;
     OrderBookItem      = orderBookItem;
     OrderBookEventType = orderBookEventType;
 }
Exemplo n.º 4
0
        private void RegisterOrderBookChannel(Pusher pusher, CurrencyPair pair)
        {
            var orderBookChannel = pusher.Subscribe($"order_book{GetSubscriptionName(pair)}");

            orderBookChannel.Subscribed += _chatChannel_Subscribed;

            orderBookChannel.Bind("data", (dynamic data) =>
            {
                _dateLastUpdated       = DateTime.UtcNow;
                var orderBook          = new OrderBook();
                orderBook.CurrencyPair = pair;
                foreach (var bid in data.bids)
                {
                    var orderBookItem = new OrderBookItem
                    {
                        Volume = bid[1],
                        Price  = bid[0]
                    };
                    orderBook.Bids.Add(orderBookItem);
                }
                foreach (var ask in data.asks)
                {
                    var orderBookItem = new OrderBookItem
                    {
                        Volume = ask[1],
                        Price  = ask[0]
                    };
                    orderBook.Asks.Add(orderBookItem);
                }
                _orderBookDict[pair] = orderBook;
                OrderBookChanged?.Invoke(pair, orderBook);
            });
        }
Exemplo n.º 5
0
        private void Snapshot(dynamic data)
        {
            var currencyPair = _currencyMapper.GetCurrency((string)data.product_id);
            var orderBook    = new OrderBook
            {
                CurrencyPair = currencyPair
            };

            foreach (var bid in data.bids)
            {
                var bookItem = new OrderBookItem()
                {
                    Price  = DecimalHelper.Get((string)bid[0]),
                    Volume = DecimalHelper.Get((string)bid[1]),
                };
                orderBook.Bids.Add(bookItem);
            }
            foreach (var ask in data.asks)
            {
                var bookItem = new OrderBookItem()
                {
                    Price  = DecimalHelper.Get((string)ask[0]),
                    Volume = DecimalHelper.Get((string)ask[1]),
                };
                orderBook.Asks.Add(bookItem);
            }
            SortBids(orderBook);
            SortAsks(orderBook);
            _orderBookDict[currencyPair] = orderBook;
            OrderBookChanged?.Invoke(orderBook.CurrencyPair, orderBook);
        }
Exemplo n.º 6
0
        public IActionResult Get()
        {
            var observations = _observationService.GetObservations();
            var list         = new List <WatchModel>();

            foreach (var item in observations)
            {
                var orderBook = new WatchOrderBookModel();

                var sell_book = _exchangeDataService.GetOrderBook(item.ToExchangeName, item.CurrencyPair);
                var buy_book  = _exchangeDataService.GetOrderBook(item.FromExchangeName, item.CurrencyPair);
                var bid1      = new OrderBookItem();
                var ask1      = new OrderBookItem();
                if (sell_book.Bids.Count > 0)
                {
                    bid1           = sell_book.Bids[0];
                    orderBook.Bid1 = bid1.ToString();
                    orderBook.Bid2 = sell_book.Bids[1].ToString();
                    orderBook.Bid3 = sell_book.Bids[2].ToString();
                }
                else
                {
                    orderBook.Bid1 = "";
                    orderBook.Bid2 = "";
                    orderBook.Bid3 = "";
                }
                if (buy_book.Asks.Count > 0)
                {
                    ask1           = buy_book.Asks[0];
                    orderBook.Ask1 = ask1.ToString();
                    orderBook.Ask2 = buy_book.Asks[1].ToString();
                    orderBook.Ask3 = buy_book.Asks[2].ToString();
                }
                else
                {
                    orderBook.Ask1 = "";
                    orderBook.Ask2 = "";
                    orderBook.Ask3 = "";
                }
                orderBook.SpreadValue  = (bid1.Price - ask1.Price).ToString("f2");
                orderBook.SpreadVolume = Math.Min(bid1.Volume, ask1.Volume).ToString("f4");

                var model = new WatchModel()
                {
                    Observation = item,
                    OrderBook   = orderBook
                };
                list.Add(model);
            }
            return(Ok(list));
        }
Exemplo n.º 7
0
        /// <summary>
        ///     Парсинг стакана
        /// </summary>
        private void ParseBook(IStompFrame frame, string subscription)
        {
            if (!obIdToInstrument.TryGetValue(subscription, out var instrument))
            {
                return;
            }

            var json = JObject.Parse(frame.Body);

            var columns = (JArray)json["columns"];
            var allData = (JArray)json["data"];

            var ob = new OrderBook(allData.Count)
            {
                Instrument = instrument
            };

            var ip = GetInstrumentParams(instrument);

            OrderBookItem prev = null, curr;

            for (var i = allData.Count - 1; i >= 0; i--)
            {
                var data = (JArray)allData[i];
                var dict = new JArrayDictionary(columns, data);

                ob.Items.Add(curr = new OrderBookItem
                {
                    Operation = dict["BUYSELL"].ToString() == "B" ? OrderOperation.Buy : OrderOperation.Sell,
                    Price     = (decimal)dict["PRICE"][0],
                    Quantity  = (int)dict["QUANTITY"],
                });

                if (prev?.Operation == OrderOperation.Sell && curr.Operation == OrderOperation.Buy)
                {
                    ip.BestOfferPrice    = prev.Price;
                    ip.BestOfferQuantity = prev.Quantity;

                    ip.BestBidPrice    = curr.Price;
                    ip.BestBidQuantity = curr.Quantity;
                }

                prev = curr;
            }

            OnMessageReceived(ip);
            OnMessageReceived(ob);
        }
Exemplo n.º 8
0
        private List <IOrderBookItem> ParseOrders(List <string[]> orders)
        {
            var _result = new List <IOrderBookItem>();

            foreach (var _order in orders)
            {
                var _o = new OrderBookItem
                {
                    price    = decimal.Parse(_order[0], NumberStyles.Float),
                    quantity = decimal.Parse(_order[1], NumberStyles.Float),
                    count    = 1
                };

                _o.amount = _o.quantity * _o.price;
                _result.Add(_o);
            }

            return(_result);
        }
Exemplo n.º 9
0
        private OrderBookItem[] EnumerateBook(OrderOperation operation)
        {
            var sorted = operation == OrderOperation.Buy ? bids : asks;

            var size   = Math.Min(Capacity, sorted.Count);
            var rArray = new OrderBookItem[size];

            var c = 0;

            foreach (var pair in sorted)
            {
                var price = pair.Key;
                var list  = pair.Value;

                rArray[c] = new OrderBookItem(operation, price, list.Sum(_ => _.Quantity));

                if (++c >= Capacity)
                {
                    break;
                }
            }

            return(rArray);
        }
Exemplo n.º 10
0
            /// <summary>
            /// Обработка Quote-ов. Могут приходить в разных сообщениях
            /// </summary>
            private SendMessageFlags HandleQuotes(List <Quote> quotes)
            {
                var result = SendMessageFlags.None;

                if (quotes == null || quotes.Count == 0)
                {
                    return(result);
                }

                foreach (var quote in quotes)
                {
                    // marketData.contract_id
                    var price  = instrumentResolver.ConvertPriceBack(ContractId, quote.price);
                    var volume = (long)quote.volume;

                    switch ((Quote.Type)quote.type)
                    {
                    case Quote.Type.BESTBID:
                        if (InstrumentParams.BestBidPrice != price ||
                            InstrumentParams.BestBidQuantity != volume)
                        {
                            InstrumentParams.BestBidPrice    = price;
                            InstrumentParams.BestBidQuantity = volume;

                            if (!level2QuoteReceived)
                            {
                                domBids.Clear();
                                domBids[price] = new OrderBookItem(OrderOperation.Buy, price, volume);
                                result        |= SendMessageFlags.OrderBook;
                            }
                            result |= SendMessageFlags.InstrumentParams;
                        }
                        break;

                    case Quote.Type.BESTASK:
                        if (InstrumentParams.BestOfferPrice != price ||
                            InstrumentParams.BestOfferQuantity != volume)
                        {
                            InstrumentParams.BestOfferPrice    = price;
                            InstrumentParams.BestOfferQuantity = volume;

                            if (!level2QuoteReceived)
                            {
                                domAsks.Clear();
                                domAsks[-price] = new OrderBookItem(OrderOperation.Sell, price, volume);
                                result         |= SendMessageFlags.OrderBook;
                            }
                            result |= SendMessageFlags.InstrumentParams;
                        }
                        break;

                    case Quote.Type.BID:
                        level2QuoteReceived = true;
                        if (volume == 0)
                        {
                            domBids.Remove(price);
                        }
                        else
                        {
                            domBids[price] = new OrderBookItem(OrderOperation.Buy, price, volume);
                        }

                        result |= SendMessageFlags.OrderBook;
                        break;

                    case Quote.Type.ASK:
                        level2QuoteReceived = true;
                        // Цена с минусом, чтобы был правильный порядок сортировки
                        if (volume == 0)
                        {
                            domAsks.Remove(-price);
                        }
                        else
                        {
                            domAsks[-price] = new OrderBookItem(OrderOperation.Sell, price, volume);
                        }
                        result |= SendMessageFlags.OrderBook;
                        break;

                    case Quote.Type.SETTLEMENT:
                        if (InstrumentParams.Settlement != price)
                        {
                            InstrumentParams.Settlement = price;

                            if (InstrumentParams.LastPrice == 0)
                            {
                                InstrumentParams.LastPrice = price;
                            }

                            UpdatePriceStep(price);
                            result |= SendMessageFlags.InstrumentParams;
                        }
                        break;

                    case Quote.Type.TRADE:
                        if (InstrumentParams.LastPrice != price)
                        {
                            InstrumentParams.LastPrice = price;
                            UpdatePriceStep(price);
                            result |= SendMessageFlags.InstrumentParams;
                        }
                        break;
                    }
                }
                return(result);
            }
Exemplo n.º 11
0
        /// <summary>
        /// Вставляет с сортировкой запись в стакан.
        /// </summary>
        /// <param name="replId">replId записи из plaza2.</param>
        /// <param name="p2Ob">Мэп replId на OrderBookItem.</param>
        /// <param name="ob">Объект стакана.</param>
        /// <param name="obi">Запись в стакане.</param>
        private void InsertOrderBookItemSorted(long replId, Dictionary <long, OrderBookItem> p2Ob, OrderBook ob, OrderBookItem obi)
        {
            p2Ob.Add(replId, obi);

            var indexToInsert = 0;

            if (ob.Items.Count > 0)
            {
                for (indexToInsert = 0; indexToInsert < ob.Items.Count; indexToInsert++)
                {
                    if (obi.Price > ob.Items[indexToInsert].Price)
                    {
                        break;
                    }
                }
            }

            ob.Items.Insert(indexToInsert, obi);
        }
Exemplo n.º 12
0
        private void ProcessOrderBookUpdates()
        {
            const int numberOfCyclesToFireEvent = 10; // каждые 10 циклов нижлежащего while мы райзим эвент об обновлении стаканов
            var       cyclesCount = 0;

            while (!cancellationTokenSource.Token.WaitHandle.WaitOne(10))
            {
                if (++cyclesCount > numberOfCyclesToFireEvent)
                {
                    cyclesCount = 0;
                    FireUpdatedOrderBooks();
                }

                CGateOrderBookUpdate record;

                while (orderBooksUdatesQueue.TryDequeue(out record))
                {
                    // вызываем событие обновления стаканов если в потоке пришло сообщение об окончании блока обновлений
                    if (record.Type == CGateOrderBookUpdateType.StreamDataEnd)
                    {
                        FireUpdatedOrderBooks();
                        continue;
                    }

                    if (record.Type == CGateOrderBookUpdateType.ClearTable)
                    {
                        ClearOrderBooks(record);
                        FireUpdatedOrderBooks();
                        continue;
                    }

                    //revisionsDictionary[record.ReplId] = record.ReplRev;
                    RememberUpdatedInstrument(record.IsinId);

                    int obItemIsinId;
                    var instrumentChanged = false;

                    if (!obRowsOnInstruments.TryGetValue(record.ReplId, out obItemIsinId))
                    {
                        obRowsOnInstruments.Add(record.ReplId, record.IsinId);
                    }
                    else if (record.IsinId != obItemIsinId)
                    {
                        RememberUpdatedInstrument(obItemIsinId);
                        obRowsOnInstruments[record.ReplId] = record.IsinId;
                        instrumentChanged = true;
                    }

                    Dictionary <long, OrderBookItem> p2ob;
                    OrderBook ob;

                    if (!plaza2OrderBooks.TryGetValue(record.IsinId, out p2ob))
                    {
                        p2ob = new Dictionary <long, OrderBookItem>();
                        plaza2OrderBooks.Add(record.IsinId, p2ob);
                    }

                    if (!orderBooks.TryGetValue(record.IsinId, out ob))
                    {
                        var instrument = instrumentResolver.GetInstrument(record.InstrumentCode);
                        ob = new OrderBook {
                            Instrument = instrument.Instrument
                        };
                        orderBooks.Add(record.IsinId, ob);
                    }

                    // если произошла смена инструмента у записи, то её нужно удалить из того стакана, в котором она была раньше
                    if (instrumentChanged)
                    {
                        Dictionary <long, OrderBookItem> p2obToDeleteRecord;
                        OrderBook obToDeleteRecord;

                        if (plaza2OrderBooks.TryGetValue(obItemIsinId, out p2obToDeleteRecord) &&
                            orderBooks.TryGetValue(obItemIsinId, out obToDeleteRecord))
                        {
                            if (p2obToDeleteRecord.ContainsKey(record.ReplId))
                            {
                                obToDeleteRecord.Items.Remove(p2obToDeleteRecord[record.ReplId]);
                                p2obToDeleteRecord.Remove(record.ReplId);
                            }
                        }
                    }

                    OrderBookItem obi;

                    if (!p2ob.TryGetValue(record.ReplId, out obi) && record.Price != 0m && record.Quantity != 0 && record.ReplAct == 0)
                    {
                        obi = new OrderBookItem {
                            Price = record.Price, Quantity = record.Quantity, Operation = record.Operation
                        };

                        // ишем место, куда приткнуть новую котировку
                        InsertOrderBookItemSorted(record.ReplId, p2ob, ob, obi);
                    }
                    else if (obi != null)
                    {
                        if (record.Price == 0 || record.Quantity == 0 || record.ReplAct > 0)
                        {
                            RemoveOrderBookItem(record.ReplId, p2ob, ob);
                        }
                        else
                        {
                            var needSort = obi.Price != record.Price || obi.Operation != record.Operation;

                            obi.Price     = record.Price;
                            obi.Operation = record.Operation;
                            obi.Quantity  = record.Quantity;

                            if (needSort)
                            {
                                RemoveOrderBookItem(record.ReplId, p2ob, ob);
                                InsertOrderBookItemSorted(record.ReplId, p2ob, ob, obi);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 13
0
 private void L2Update(dynamic data)
 {
     try
     {
         var currencyPair = _currencyMapper.GetCurrency((string)data.product_id);
         var orderBook    = _orderBookDict[currencyPair];
         foreach (var change in data.changes)
         {
             var tradeType = (string)change[0];
             var price     = DecimalHelper.Get((string)change[1]);
             var volume    = DecimalHelper.Get((string)change[2]);
             if (tradeType == "buy")
             {
                 var bid = orderBook.Bids.FirstOrDefault(it => it.Price == price);
                 if (volume == 0)
                 {
                     if (bid != null)
                     {
                         orderBook.Bids.Remove(bid);
                         SortBids(orderBook);
                     }
                 }
                 else
                 {
                     if (bid != null)
                     {
                         bid.Volume = volume;
                     }
                     else
                     {
                         bid = new OrderBookItem()
                         {
                             Price  = price,
                             Volume = volume
                         };
                         orderBook.Bids.Add(bid);
                         SortBids(orderBook);
                     }
                 }
             }
             else
             {
                 var ask = orderBook.Asks.FirstOrDefault(it => it.Price == price);
                 if (volume == 0)
                 {
                     if (ask != null)
                     {
                         orderBook.Asks.Remove(ask);
                         SortAsks(orderBook);
                     }
                 }
                 if (ask != null)
                 {
                     ask.Volume = volume;
                 }
                 else
                 {
                     ask = new OrderBookItem()
                     {
                         Price  = price,
                         Volume = volume
                     };
                     orderBook.Asks.Add(ask);
                     SortAsks(orderBook);
                 }
             }
             OrderBookChanged?.Invoke(currencyPair, orderBook);
         }
     }
     catch (Exception)
     {
         //Todo:log data format error
     }
 }