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);
        }
Example #2
0
        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);
                }
            }));
        }
Example #4
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
                }
            }));
        }
Example #10
0
        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));
        }