Esempio n. 1
0
        public override ExchangeOrderBook GetOrderBook(string symbol, int maxCount = 100)
        {
            symbol = NormalizeSymbol(symbol);
            JObject json = MakeJsonRequest <JObject>("/0/public/Depth?pair=" + symbol + "&count=" + maxCount);
            JToken  obj  = CheckError(json);

            obj = obj[symbol];
            if (obj == null)
            {
                return(null);
            }
            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            bids   = obj["bids"];

            foreach (JToken token in bids)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token[1].Value <decimal>(), Price = token[0].Value <decimal>()
                };
                orders.Bids.Add(order);
            }
            JToken asks = obj["asks"];

            foreach (JToken token in asks)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token[1].Value <decimal>(), Price = token[0].Value <decimal>()
                };
                orders.Asks.Add(order);
            }
            return(orders);
        }
Esempio n. 2
0
        public override ExchangeOrderBook GetOrderBook(string symbol, int maxCount = 100)
        {
            symbol = NormalizeSymbol(symbol);
            JObject           obj    = MakeJsonRequest <Newtonsoft.Json.Linq.JObject>("public/getorderbook?market=" + symbol + "&type=both&limit_bids=" + maxCount + "&limit_asks=" + maxCount);
            JToken            book   = CheckError(obj);
            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            bids   = book["buy"];

            foreach (JToken token in bids)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token["Quantity"].ConvertInvariant <decimal>(), Price = token["Rate"].ConvertInvariant <decimal>()
                };
                orders.Bids.Add(order);
            }
            JToken asks = book["sell"];

            foreach (JToken token in asks)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token["Quantity"].ConvertInvariant <decimal>(), Price = token["Rate"].ConvertInvariant <decimal>()
                };
                orders.Asks.Add(order);
            }
            return(orders);
        }
        protected override async Task <IEnumerable <KeyValuePair <string, ExchangeOrderBook> > > OnGetOrderBooksAsync(int maxCount = 100)
        {
            List <KeyValuePair <string, ExchangeOrderBook> > books = new List <KeyValuePair <string, ExchangeOrderBook> >();
            JToken obj = await MakeJsonRequestAsync <JToken>("/public?command=returnOrderBook&currencyPair=all&depth=" + maxCount);

            foreach (JProperty token in obj.Children())
            {
                ExchangeOrderBook book = new ExchangeOrderBook();
                foreach (JArray array in token.First["asks"])
                {
                    var depth = new ExchangeOrderPrice {
                        Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>()
                    };
                    book.Asks[depth.Price] = depth;
                }
                foreach (JArray array in token.First["bids"])
                {
                    var depth = new ExchangeOrderPrice {
                        Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>()
                    };
                    book.Bids[depth.Price] = depth;
                }
                books.Add(new KeyValuePair <string, ExchangeOrderBook>(token.Name, book));
            }
            return(books);
        }
        public override ExchangeOrderBook GetOrderBook(string symbol, int maxCount = 100)
        {
            symbol = NormalizeSymbol(symbol);
            JObject obj = MakeJsonRequest <Newtonsoft.Json.Linq.JObject>("/book/" + symbol + "?limit_bids=" + maxCount + "&limit_asks=" + maxCount);

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

            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            bids   = obj["bids"];

            foreach (JToken token in bids)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token["amount"].Value <decimal>(), Price = token["price"].Value <decimal>()
                };
                orders.Bids.Add(order);
            }
            JToken asks = obj["asks"];

            foreach (JToken token in asks)
            {
                ExchangeOrderPrice order = new ExchangeOrderPrice {
                    Amount = token["amount"].Value <decimal>(), Price = token["price"].Value <decimal>()
                };
                orders.Asks.Add(order);
            }
            return(orders);
        }
Esempio n. 5
0
        protected override IWebSocket OnGetOrderBookWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] marketSymbols)
        {
            if (marketSymbols == null || marketSymbols.Length == 0)
            {
                marketSymbols = GetMarketSymbolsAsync().Sync().ToArray();
            }
            string combined = string.Join("/", marketSymbols.Select(s => this.NormalizeMarketSymbol(s).ToLowerInvariant() + "@depth"));

            return(ConnectWebSocket($"/stream?streams={combined}", (_socket, msg) =>
            {
                string json = msg.ToStringFromUTF8();
                var update = JsonConvert.DeserializeObject <MultiDepthStream>(json);
                string marketSymbol = update.Data.MarketSymbol;
                ExchangeOrderBook book = new ExchangeOrderBook {
                    SequenceId = update.Data.FinalUpdate, MarketSymbol = marketSymbol
                };
                foreach (List <object> ask in update.Data.Asks)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = ask[0].ConvertInvariant <decimal>(), Amount = ask[1].ConvertInvariant <decimal>()
                    };
                    book.Asks[depth.Price] = depth;
                }
                foreach (List <object> bid in update.Data.Bids)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = bid[0].ConvertInvariant <decimal>(), Amount = bid[1].ConvertInvariant <decimal>()
                    };
                    book.Bids[depth.Price] = depth;
                }
                callback(book);
                return Task.CompletedTask;
            }));
        }
        protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100)
        {
            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            token  = await MakeJsonRequestAsync <JToken>("/products/" + symbol + "/book?level=" + (maxCount > 50 ? "0" : "2"));

            if (token.HasValues)
            {
                foreach (JArray array in token["bids"])
                {
                    if (orders.Bids.Count < maxCount)
                    {
                        var depth = new ExchangeOrderPrice {
                            Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>()
                        };
                        orders.Bids[depth.Price] = depth;
                    }
                }

                foreach (JArray array in token["asks"])
                {
                    if (orders.Asks.Count < maxCount)
                    {
                        var depth = new ExchangeOrderPrice {
                            Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>()
                        };
                        orders.Asks[depth.Price] = depth;
                    }
                }
            }
            return(orders);
        }
Esempio n. 7
0
        /// <summary>
        /// Read from a binary reader
        /// </summary>
        /// <param name="reader">Binary reader</param>
        public void FromBinary(BinaryReader reader)
        {
            Asks.Clear();
            Bids.Clear();
            int askCount = reader.ReadInt32();
            int bidCount = reader.ReadInt32();

            while (askCount-- > 0)
            {
                var exchangeOrderPrice = new ExchangeOrderPrice(reader);
                Asks.Add(exchangeOrderPrice.Price, exchangeOrderPrice);
            }
            while (bidCount-- > 0)
            {
                var exchangeOrderPrice = new ExchangeOrderPrice(reader);
                Bids.Add(exchangeOrderPrice.Price, exchangeOrderPrice);
            }
        }
Esempio n. 8
0
        private ExchangeOrderBook ParseOrderBook(JToken data)
        {
            ExchangeOrderBook book = new ExchangeOrderBook();

            foreach (JToken token in data["bids"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = token["quantity"].ConvertInvariant <decimal>(), Price = token["price"].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
            }
            foreach (JToken token in data["asks"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = token["quantity"].ConvertInvariant <decimal>(), Price = token["price"].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
            }
            return(book);
        }
Esempio n. 9
0
        private ExchangeOrderBook ParseOrderBook(JToken token)
        {
            ExchangeOrderBook book = new ExchangeOrderBook();

            foreach (JArray array in token["bids"])
            {
                var depth = new ExchangeOrderPrice {
                    Price = array[0].ConvertInvariant <decimal>(), Amount = array[1].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
            }
            foreach (JArray array in token["asks"])
            {
                var depth = new ExchangeOrderPrice {
                    Price = array[0].ConvertInvariant <decimal>(), Amount = array[1].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
            }
            return(book);
        }
        /// <summary>Common order book parsing method, checks for "amount" or "quantity" and "price"
        /// elements</summary>
        /// <param name="token">Token</param>
        /// <param name="asks">Asks key</param>
        /// <param name="bids">Bids key</param>
        /// <param name="price">Price key</param>
        /// <param name="amount">Quantity key</param>
        /// <param name="sequence">Sequence key</param>
        /// <param name="maxCount">Max count</param>
        /// <returns>Order book</returns>
        internal static ExchangeOrderBook ParseOrderBookFromJTokenDictionaries
        (
            this JToken token,
            string asks     = "asks",
            string bids     = "bids",
            string price    = "price",
            string amount   = "amount",
            string sequence = "ts",
            int maxCount    = 100
        )
        {
            var book = new ExchangeOrderBook {
                SequenceId = token[sequence].ConvertInvariant <long>()
            };

            foreach (JToken ask in token[asks])
            {
                var depth = new ExchangeOrderPrice {
                    Price = ask[price].ConvertInvariant <decimal>(), Amount = ask[amount].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
                if (book.Asks.Count == maxCount)
                {
                    break;
                }
            }

            foreach (JToken bid in token[bids])
            {
                var depth = new ExchangeOrderPrice {
                    Price = bid[price].ConvertInvariant <decimal>(), Amount = bid[amount].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
                if (book.Bids.Count == maxCount)
                {
                    break;
                }
            }

            return(book);
        }
Esempio n. 11
0
        protected override IDisposable OnGetOrderBookDeltasWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols)
        {
            if (callback == null || symbols == null || !symbols.Any())
            {
                return(null);
            }

            string combined = string.Join("/", symbols.Select(s => this.NormalizeSymbol(s).ToLowerInvariant() + "@depth"));

            return(ConnectWebSocket($"/stream?streams={combined}", (msg, _socket) =>
            {
                try
                {
                    string json = msg.UTF8String();
                    var update = JsonConvert.DeserializeObject <BinanceMultiDepthStream>(json);
                    string symbol = update.Data.Symbol;
                    ExchangeOrderBook book = new ExchangeOrderBook {
                        SequenceId = update.Data.FinalUpdate, Symbol = symbol
                    };
                    foreach (List <object> ask in update.Data.Asks)
                    {
                        var depth = new ExchangeOrderPrice {
                            Price = ask[0].ConvertInvariant <decimal>(), Amount = ask[1].ConvertInvariant <decimal>()
                        };
                        book.Asks[depth.Price] = depth;
                    }
                    foreach (List <object> bid in update.Data.Bids)
                    {
                        var depth = new ExchangeOrderPrice {
                            Price = bid[0].ConvertInvariant <decimal>(), Amount = bid[1].ConvertInvariant <decimal>()
                        };
                        book.Bids[depth.Price] = depth;
                    }
                    callback(book);
                }
                catch
                {
                }
            }));
        }
        protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100)
        {
            var token = await MakeRequestOkexAsync(symbol, "/depth.do?symbol=$SYMBOL$");

            ExchangeOrderBook book = new ExchangeOrderBook();

            foreach (JArray ask in token.Item1["asks"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = ask[1].ConvertInvariant <decimal>(), Price = ask[0].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
            }
            foreach (JArray bid in token.Item1["bids"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = bid[1].ConvertInvariant <decimal>(), Price = bid[0].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
            }
            return(book);
        }
        /// <summary>Common order book parsing method, most exchanges use "asks" and "bids" with
        /// arrays of length 2 for price and amount (or amount and price)</summary>
        /// <param name="token">Token</param>
        /// <param name="asks">Asks key</param>
        /// <param name="bids">Bids key</param>
        /// <param name="maxCount">Max count</param>
        /// <returns>Order book</returns>
        internal static ExchangeOrderBook ParseOrderBookFromJTokenArrays
        (
            this JToken token,
            string asks     = "asks",
            string bids     = "bids",
            string sequence = "ts",
            int maxCount    = 100
        )
        {
            var book = new ExchangeOrderBook {
                SequenceId = token[sequence].ConvertInvariant <long>()
            };

            foreach (JArray array in token[asks])
            {
                var depth = new ExchangeOrderPrice {
                    Price = array[0].ConvertInvariant <decimal>(), Amount = array[1].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
                if (book.Asks.Count == maxCount)
                {
                    break;
                }
            }

            foreach (JArray array in token[bids])
            {
                var depth = new ExchangeOrderPrice {
                    Price = array[0].ConvertInvariant <decimal>(), Amount = array[1].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
                if (book.Bids.Count == maxCount)
                {
                    break;
                }
            }

            return(book);
        }
        protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100)
        {
            symbol = NormalizeSymbol(symbol);
            JToken token = await MakeBitstampRequestAsync("/order_book/" + symbol);

            ExchangeOrderBook book = new ExchangeOrderBook();

            foreach (JArray ask in token["asks"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = ask[1].ConvertInvariant <decimal>(), Price = ask[0].ConvertInvariant <decimal>()
                };
                book.Asks[depth.Price] = depth;
            }
            foreach (JArray bid in token["bids"])
            {
                var depth = new ExchangeOrderPrice {
                    Amount = bid[1].ConvertInvariant <decimal>(), Price = bid[0].ConvertInvariant <decimal>()
                };
                book.Bids[depth.Price] = depth;
            }
            return(book);
        }
        protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100)
        {
            symbol = NormalizeSymbol(symbol);
            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            obj    = await MakeJsonRequestAsync <JToken>("/depth/" + symbol + "?limit=" + maxCount, BaseUrl, null);

            foreach (JArray prop in obj[symbol]["asks"])
            {
                var depth = new ExchangeOrderPrice {
                    Price = prop[0].ConvertInvariant <decimal>(), Amount = prop[1].ConvertInvariant <decimal>()
                };
                orders.Asks[depth.Price] = depth;
            }
            foreach (JArray prop in obj[symbol]["bids"])
            {
                var depth = new ExchangeOrderPrice {
                    Price = prop[0].ConvertInvariant <decimal>(), Amount = prop[1].ConvertInvariant <decimal>()
                };
                orders.Bids[depth.Price] = depth;
            }

            return(orders);
        }
Esempio n. 16
0
        protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100)
        {
            ExchangeOrderBook orders = new ExchangeOrderBook();
            JToken            token  = await MakeJsonRequestAsync <JToken>("/open/orders?symbol=" + symbol + "&limit=" + maxCount);

            if (token.HasValues)
            {
                foreach (JToken order in token["BUY"])
                {
                    var depth = new ExchangeOrderPrice {
                        Price = order[0].ConvertInvariant <decimal>(), Amount = order[1].ConvertInvariant <decimal>()
                    };
                    orders.Bids[depth.Price] = depth;
                }
                foreach (JToken order in token["SELL"])
                {
                    var depth = new ExchangeOrderPrice {
                        Price = order[0].ConvertInvariant <decimal>(), Amount = order[1].ConvertInvariant <decimal>()
                    };
                    orders.Asks[depth.Price] = depth;
                }
            }
            return(orders);
        }
Esempio n. 17
0
        protected override IWebSocket OnGetDeltaOrderBookWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] marketSymbols)
        {
            /*
             * {"info":"Welcome to the BitMEX Realtime API.","version":"2018-06-29T18:05:14.000Z","timestamp":"2018-07-05T14:22:26.267Z","docs":"https://www.bitmex.com/app/wsAPI","limit":{"remaining":39}}
             * {"success":true,"subscribe":"orderBookL2:XBTUSD","request":{"op":"subscribe","args":["orderBookL2:XBTUSD"]}}
             * {"table":"orderBookL2","action":"update","data":[{"symbol":"XBTUSD","id":8799343000,"side":"Buy","size":350544}]}
             */

            if (marketSymbols == null || marketSymbols.Length == 0)
            {
                marketSymbols = GetMarketSymbolsAsync().Sync().ToArray();
            }
            return(ConnectWebSocket(string.Empty, (_socket, msg) =>
            {
                var str = msg.ToStringFromUTF8();
                JToken token = JToken.Parse(str);

                if (token["table"] == null)
                {
                    return Task.CompletedTask;
                }

                var action = token["action"].ToStringInvariant();
                JArray data = token["data"] as JArray;

                ExchangeOrderBook book = new ExchangeOrderBook();
                var price = 0m;
                var size = 0m;
                foreach (var d in data)
                {
                    var marketSymbol = d["symbol"].ToStringInvariant();
                    var id = d["id"].ConvertInvariant <long>();
                    if (d["price"] == null)
                    {
                        if (!dict_long_decimal.TryGetValue(id, out price))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        price = d["price"].ConvertInvariant <decimal>();
                        dict_long_decimal[id] = price;
                        dict_decimal_long[price] = id;
                    }

                    var side = d["side"].ToStringInvariant();

                    if (d["size"] == null)
                    {
                        size = 0m;
                    }
                    else
                    {
                        size = d["size"].ConvertInvariant <decimal>();
                    }

                    var depth = new ExchangeOrderPrice {
                        Price = price, Amount = size
                    };

                    if (side.EqualsWithOption("Buy"))
                    {
                        book.Bids[depth.Price] = depth;
                    }
                    else
                    {
                        book.Asks[depth.Price] = depth;
                    }
                    book.MarketSymbol = marketSymbol;
                }

                if (!string.IsNullOrEmpty(book.MarketSymbol))
                {
                    callback(book);
                }
                return Task.CompletedTask;
            }, async(_socket) =>
            {
                if (marketSymbols.Length == 0)
                {
                    marketSymbols = (await GetMarketSymbolsAsync()).ToArray();
                }
                await _socket.SendMessageAsync(new { op = "subscribe", args = marketSymbols.Select(s => "orderBookL2:" + this.NormalizeMarketSymbol(s)).ToArray() });
            }));
        }
        protected override IWebSocket OnGetDeltaOrderBookWebSocket
        (
            Action <ExchangeOrderBook> callback,
            int maxCount = 20,
            params string[] marketSymbols
        )
        {
            if (marketSymbols == null || marketSymbols.Length == 0)
            {
                marketSymbols = GetMarketSymbolsAsync().Sync().ToArray();
            }
            Task innerCallback(string json)
            {
                #region sample json

                /*
                 *  {
                 *      MarketName : string,
                 *      Nonce      : int,
                 *      Buys:
                 *      [
                 *          {
                 *              Type     : int,
                 *              Rate     : decimal,
                 *              Quantity : decimal
                 *          }
                 *      ],
                 *      Sells:
                 *      [
                 *          {
                 *              Type     : int,
                 *              Rate     : decimal,
                 *              Quantity : decimal
                 *          }
                 *      ],
                 *      Fills:
                 *      [
                 *          {
                 *              FillId    : int,
                 *              OrderType : string,
                 *              Rate      : decimal,
                 *              Quantity  : decimal,
                 *              TimeStamp : date
                 *          }
                 *      ]
                 *  }
                 */
                #endregion

                var ordersUpdates = JsonConvert.DeserializeObject <BittrexStreamUpdateExchangeState>(json);
                var book          = new ExchangeOrderBook();
                foreach (BittrexStreamOrderBookUpdateEntry ask in ordersUpdates.Sells)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = ask.Rate, Amount = ask.Quantity
                    };
                    book.Asks[depth.Price] = depth;
                }

                foreach (BittrexStreamOrderBookUpdateEntry bid in ordersUpdates.Buys)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = bid.Rate, Amount = bid.Quantity
                    };
                    book.Bids[depth.Price] = depth;
                }

                book.MarketSymbol = ordersUpdates.MarketName;
                book.SequenceId   = ordersUpdates.Nonce;
                callback(book);
                return(Task.CompletedTask);
            }

            return(new BittrexWebSocketManager().SubscribeToExchangeDeltas(innerCallback, marketSymbols));
        }
Esempio n. 19
0
        protected override IDisposable OnGetOrderBookDeltasWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols)
        {
            /*
             * {"info":"Welcome to the BitMEX Realtime API.","version":"2018-06-29T18:05:14.000Z","timestamp":"2018-07-05T14:22:26.267Z","docs":"https://www.bitmex.com/app/wsAPI","limit":{"remaining":39}}
             * {"success":true,"subscribe":"orderBookL2:XBTUSD","request":{"op":"subscribe","args":["orderBookL2:XBTUSD"]}}
             * {"table":"orderBookL2","action":"update","data":[{"symbol":"XBTUSD","id":8799343000,"side":"Buy","size":350544}]}
             */
            if (callback == null || symbols == null || !symbols.Any())
            {
                return(null);
            }

            return(ConnectWebSocket(string.Empty, (msg, _socket) =>
            {
                try
                {
                    var str = msg.UTF8String();
                    JToken token = JToken.Parse(str);

                    if (token["table"] == null)
                    {
                        return;
                    }

                    var action = token["action"].ToStringInvariant();
                    JArray data = token["data"] as JArray;

                    ExchangeOrderBook book = new ExchangeOrderBook();
                    var price = 0m;
                    var size = 0m;
                    foreach (var d in data)
                    {
                        var symbol = d["symbol"].ToStringInvariant();
                        var id = d["id"].ConvertInvariant <long>();
                        if (d["price"] == null)
                        {
                            if (!dict_long_decimal.TryGetValue(id, out price))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            price = d["price"].ConvertInvariant <decimal>();
                            dict_long_decimal[id] = price;
                            dict_decimal_long[price] = id;
                        }

                        var side = d["side"].ToStringInvariant();

                        if (d["size"] == null)
                        {
                            size = 0m;
                        }
                        else
                        {
                            size = d["size"].ConvertInvariant <decimal>();
                        }

                        var depth = new ExchangeOrderPrice {
                            Price = price, Amount = size
                        };

                        if (side.EqualsWithOption("Buy"))
                        {
                            book.Bids[depth.Price] = depth;
                        }
                        else
                        {
                            book.Asks[depth.Price] = depth;
                        }
                        book.Symbol = symbol;
                    }

                    callback(book);
                }
                catch
                {
                    // TODO: Handle exception
                }
            }, (_socket) =>
            {
                if (symbols.Length == 0)
                {
                    symbols = GetSymbols().ToArray();
                }

                string combined = string.Join(",", symbols.Select(s => "\"orderBookL2:" + this.NormalizeSymbol(s) + "\""));
                string msg = $"{{\"op\":\"subscribe\",\"args\":[{combined}]}}";
                _socket.SendMessage(msg);
            }));
        }
Esempio n. 20
0
        protected override IDisposable OnGetOrderBookDeltasWebSocket(
            Action <ExchangeOrderBook> callback,
            int maxCount = 20,
            params string[] symbols)
        {
            if (callback == null || symbols == null || !symbols.Any())
            {
                return(null);
            }

            void innerCallback(string json)
            {
                #region sample json

                /*
                 *  {
                 *      MarketName : string,
                 *      Nonce      : int,
                 *      Buys:
                 *      [
                 *          {
                 *              Type     : int,
                 *              Rate     : decimal,
                 *              Quantity : decimal
                 *          }
                 *      ],
                 *      Sells:
                 *      [
                 *          {
                 *              Type     : int,
                 *              Rate     : decimal,
                 *              Quantity : decimal
                 *          }
                 *      ],
                 *      Fills:
                 *      [
                 *          {
                 *              FillId    : int,
                 *              OrderType : string,
                 *              Rate      : decimal,
                 *              Quantity  : decimal,
                 *              TimeStamp : date
                 *          }
                 *      ]
                 *  }
                 */
                #endregion

                var ordersUpdates = JsonConvert.DeserializeObject <BittrexStreamUpdateExchangeState>(json);
                var book          = new ExchangeOrderBook();
                foreach (BittrexStreamOrderBookUpdateEntry ask in ordersUpdates.Sells)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = ask.Rate, Amount = ask.Quantity
                    };
                    book.Asks[depth.Price] = depth;
                }

                foreach (BittrexStreamOrderBookUpdateEntry bid in ordersUpdates.Buys)
                {
                    var depth = new ExchangeOrderPrice {
                        Price = bid.Rate, Amount = bid.Quantity
                    };
                    book.Bids[depth.Price] = depth;
                }

                book.Symbol     = ordersUpdates.MarketName;
                book.SequenceId = ordersUpdates.Nonce;
                callback(book);
            }

            IDisposable client = null;
            foreach (var sym in symbols)
            {
                client = this.SocketManager.SubscribeToExchangeDeltas(innerCallback, sym);
            }

            return(client);
        }
Esempio n. 21
0
        protected override async Task <IWebSocket> OnGetDeltaOrderBookWebSocketAsync(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] marketSymbols)
        {
            Dictionary <int, Tuple <string, long> > messageIdToSymbol = new Dictionary <int, Tuple <string, long> >();

            return(await ConnectWebSocketAsync(string.Empty, (_socket, msg) =>
            {
                JToken token = JToken.Parse(msg.ToStringFromUTF8());
                int msgId = token[0].ConvertInvariant <int>();

                //return if this is a heartbeat message
                if (msgId == 1010)
                {
                    return Task.CompletedTask;
                }

                var seq = token[1].ConvertInvariant <long>();
                var dataArray = token[2];
                ExchangeOrderBook book = new ExchangeOrderBook();
                foreach (var data in dataArray)
                {
                    var dataType = data[0].ToStringInvariant();
                    if (dataType == "i")
                    {
                        var marketInfo = data[1];
                        var market = marketInfo["currencyPair"].ToStringInvariant();
                        messageIdToSymbol[msgId] = new Tuple <string, long>(market, 0);

                        // we are only returning the deltas, this would create a full order book which we don't want, but keeping it
                        //  here for historical reference

                        /*
                         * foreach (JProperty jprop in marketInfo["orderBook"][0].Cast<JProperty>())
                         * {
                         *  var depth = new ExchangeOrderPrice
                         *  {
                         *      Price = jprop.Name.ConvertInvariant<decimal>(),
                         *      Amount = jprop.Value.ConvertInvariant<decimal>()
                         *  };
                         *  book.Asks[depth.Price] = depth;
                         * }
                         * foreach (JProperty jprop in marketInfo["orderBook"][1].Cast<JProperty>())
                         * {
                         *  var depth = new ExchangeOrderPrice
                         *  {
                         *      Price = jprop.Name.ConvertInvariant<decimal>(),
                         *      Amount = jprop.Value.ConvertInvariant<decimal>()
                         *  };
                         *  book.Bids[depth.Price] = depth;
                         * }
                         */
                    }
                    else if (dataType == "o")
                    {
                        //removes or modifies an existing item on the order books
                        if (messageIdToSymbol.TryGetValue(msgId, out Tuple <string, long> symbol))
                        {
                            int type = data[1].ConvertInvariant <int>();
                            var depth = new ExchangeOrderPrice {
                                Price = data[2].ConvertInvariant <decimal>(), Amount = data[3].ConvertInvariant <decimal>()
                            };
                            var list = (type == 1 ? book.Bids : book.Asks);
                            list[depth.Price] = depth;
                            book.MarketSymbol = symbol.Item1;
                            book.SequenceId = symbol.Item2 + 1;
                            messageIdToSymbol[msgId] = new Tuple <string, long>(book.MarketSymbol, book.SequenceId);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                if (book != null && (book.Asks.Count != 0 || book.Bids.Count != 0))
                {
                    callback(book);
                }
                return Task.CompletedTask;
            }, async (_socket) =>
            {
                if (marketSymbols == null || marketSymbols.Length == 0)
                {
                    marketSymbols = (await GetMarketSymbolsAsync()).ToArray();
                }
                // subscribe to order book and trades channel for each symbol
                foreach (var sym in marketSymbols)
                {
                    await _socket.SendMessageAsync(new { command = "subscribe", channel = NormalizeMarketSymbol(sym) });
                }
            }));
        }