public async Task <ExchangeOrderBook> GetOrderBookAsync(string exchange, string symbol, int maxCount = 100) { await new SynchronizationContextRemover(); ExchangeOrderBook book = new ExchangeOrderBook(); JToken result = await MakeJsonRequestAsync <JToken>("/markets/" + exchange.ToLowerInvariant() + "/" + symbol + "/orderbook"); int count = 0; foreach (JArray array in result["asks"]) { if (++count > maxCount) { break; } var depth = new ExchangeOrderPrice { Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>() }; book.Asks[depth.Price] = depth; } count = 0; foreach (JArray array in result["bids"]) { if (++count > maxCount) { break; } var depth = new ExchangeOrderPrice { Amount = array[1].ConvertInvariant <decimal>(), Price = array[0].ConvertInvariant <decimal>() }; book.Bids[depth.Price] = depth; } return(book); }
protected override async Task <IEnumerable <KeyValuePair <string, ExchangeOrderBook> > > OnGetOrderBooksAsync(int maxCount = 100) { string symbol = "all"; List <KeyValuePair <string, ExchangeOrderBook> > books = new List <KeyValuePair <string, ExchangeOrderBook> >(); var data = await MakeRequestBithumbAsync(symbol, "/public/orderbook/$SYMBOL$"); foreach (JProperty book in data.Item1) { if (book.Name != "timestamp" && book.Name != "payment_currency") { ExchangeOrderBook orderBook = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(book.Value); books.Add(new KeyValuePair <string, ExchangeOrderBook>(book.Name, orderBook)); } } return(books); }
protected override IWebSocket OnGetFutureOrderBookAllWebSocket(Action <ExchangeOrderBook> callback, string contractType, int maxCount = 20, params string[] symbols) { if (callback == null || symbols == null || symbols.Length == 0) { return(null); } return(ConnectWebSocket(string.Empty, (msg, _socket) => { try { JToken token = JToken.Parse(msg.UTF8String()); token = token[0]; var channel = token["channel"].ToStringInvariant(); if (channel.EqualsWithOption("addChannel")) { return; } var sArray = channel.Split('_'); var symbol = sArray[3] + "_" + sArray[4]; var data = token["data"]; ExchangeOrderBook book = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(data, sequence: "timestamp", maxCount: maxCount); book.Symbol = symbol; callback(book); } catch { // TODO: Handle exception } }, (_socket) => { if (symbols.Length == 0) { symbols = GetSymbols().ToArray(); } foreach (string symbol in symbols) { // subscribe to order book and trades channel for given symbol string normalizedSymbol = NormalizeSymbol(symbol); string channel = $"ok_sub_futureusd_{normalizedSymbol}_depth_{contractType}_{maxCount}"; Console.WriteLine($"[channel] {channel}"); string msg = $"{{\'event\':\'addChannel\',\'channel\':\'{channel}\'}}"; _socket.SendMessage(msg); } })); }
protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100) { /* * { * "status": "ok", * "ch": "market.btcusdt.depth.step0", * "ts": 1489472598812, * "tick": { * "id": 1489464585407, * "ts": 1489464585407, * "bids": [ * [7964, 0.0678], // [price, amount] * [7963, 0.9162], * [7961, 0.1], * [7960, 12.8898], * [7958, 1.2], * [7955, 2.1009], * [7954, 0.4708], * [7953, 0.0564], * [7951, 2.8031], * [7950, 13.7785], * [7949, 0.125], * [7948, 4], * [7942, 0.4337], * [7940, 6.1612], * [7936, 0.02], * [7935, 1.3575], * [7933, 2.002], * [7932, 1.3449], * [7930, 10.2974], * [7929, 3.2226] * ], * "asks": [ * [7979, 0.0736], * [7980, 1.0292], * [7981, 5.5652], * [7986, 0.2416], * [7990, 1.9970], * [7995, 0.88], */ symbol = NormalizeSymbol(symbol); ExchangeOrderBook orders = new ExchangeOrderBook(); JToken obj = await MakeJsonRequestAsync <JToken>("/market/depth?symbol=" + symbol + "&type=step0", BaseUrl, null); return(ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj["tick"], sequence: "ts", maxCount: maxCount)); }
protected override IWebSocket 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 { } })); }
/// <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> public static ExchangeOrderBook ParseOrderBookFromJTokenDictionaries( 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); }
protected override async Task <ExchangeOrderBook> OnGetOrderBookAsync(string symbol, int maxCount = 100) { symbol = NormalizeSymbol(symbol); ExchangeOrderBook orders = new ExchangeOrderBook(); decimal[][] books = await MakeJsonRequestAsync <decimal[][]>("/book/t" + symbol + "/P0?len=" + maxCount); foreach (decimal[] book in books) { if (book[2] > 0m) { orders.Bids[book[0]] = new ExchangeOrderPrice { Amount = book[2], Price = book[0] }; } else { orders.Asks[book[0]] = new ExchangeOrderPrice { Amount = -book[2], Price = book[0] }; } } return(orders); }
protected override IWebSocket OnGetOrderBookDeltasWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols) { if (callback == null || symbols == null || symbols.Length == 0) { return(null); } return(ConnectWebSocket(string.Empty, (msg, _socket) => { /* * {{ * "id": "id1", * "status": "ok", * "subbed": "market.btcusdt.depth.step0", * "ts": 1526749164133 * }} * * * {{ * "ch": "market.btcusdt.depth.step0", * "ts": 1526749254037, * "tick": { * "bids": [ * [ * 8268.3, * 0.101 * ], * [ * 8268.29, * 0.8248 * ], * * ], * "asks": [ * [ * 8275.07, * 0.1961 * ], * * [ * 8337.1, * 0.5803 * ] * ], * "ts": 1526749254016, * "version": 7664175145 * } * }} */ try { var str = msg.UTF8StringFromGzip(); JToken token = JToken.Parse(str); if (token["status"] != null) { return; } else if (token["ping"] != null) { _socket.SendMessage(str.Replace("ping", "pong")); return; } var ch = token["ch"].ToStringInvariant(); var sArray = ch.Split('.'); var symbol = sArray[1].ToStringInvariant(); ExchangeOrderBook book = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token["tick"], maxCount: maxCount); book.Symbol = symbol; callback(book); } catch { // TODO: Handle exception } }, (_socket) => { if (symbols.Length == 0) { symbols = GetSymbols().ToArray(); } // request all symbols, this does not work sadly, only the first is pulled foreach (string symbol in symbols) { long id = System.Threading.Interlocked.Increment(ref webSocketId); ////var normalizedSymbol = NormalizeSymbol(symbols[0]); var normalizedSymbol = NormalizeSymbol(symbol); // subscribe to order book and trades channel for given symbol string channel = $"market.{normalizedSymbol}.depth.step0"; string msg = $"{{\"sub\":\"{channel}\",\"id\":\"id{id}\"}}"; _socket.SendMessage(msg); } })); }
protected override IWebSocket OnGetOrderBookDeltasWebSocket(Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols) { if (callback == null || symbols == null || symbols.Length == 0) { return(null); } return(ConnectWebSocket(string.Empty, (msg, _socket) => { /* * {[ * { * "binary": 0, * "channel": "addChannel", * "data": { * "result": true, * "channel": "ok_sub_spot_bch_btc_depth_5" * } * } * ]} * * * * {[ * { * "data": { * "asks": [ * [ * "8364.1163", * "0.005" * ], * * ], * "bids": [ * [ * "8335.99", * "0.01837999" * ], * [ * "8335.9899", * "0.06" * ], * ], * "timestamp": 1526734386064 * }, * "binary": 0, * "channel": "ok_sub_spot_btc_usdt_depth_20" * } * ]} * */ try { JToken token = JToken.Parse(msg.UTF8String()); token = token[0]; var channel = token["channel"].ToStringInvariant(); if (channel.EqualsWithOption("addChannel")) { return; } var sArray = channel.Split('_'); var symbol = sArray[3] + "_" + sArray[4]; var data = token["data"]; ExchangeOrderBook book = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(data, sequence: "timestamp", maxCount: maxCount); book.Symbol = symbol; callback(book); } catch { // TODO: Handle exception } }, (_socket) => { if (symbols.Length == 0) { symbols = GetSymbols().ToArray(); } foreach (string symbol in symbols) { // subscribe to order book and trades channel for given symbol string normalizedSymbol = NormalizeSymbol(symbol); string channel = $"ok_sub_spot_{normalizedSymbol}_depth_{maxCount}"; string msg = $"{{\'event\':\'addChannel\',\'channel\':\'{channel}\'}}"; _socket.SendMessage(msg); } })); }
protected override IWebSocket 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); } return(this.SocketManager.SubscribeToExchangeDeltas(innerCallback, symbols)); }