private Task <decimal> CalculateUSDT(KeyValuePair <string, decimal> account, decimal ethUsdt) { var amount = 0m; // 如果持有币种为usdt if ("usdt".Equals(account.Key)) { amount = account.Value; } else { // 如果该币在usdt交易区,则折算为usdt if (this.usdt.Contains(account.Key.ToUpper())) { var depth = exchange.GetOrderBook(account.Key + "/usdt", 1); var bids = depth.Bids.OrderByDescending(a => a.Value.Price); amount = account.Value * bids.ElementAt(0).Value.Price; } // 如果该币在eth交易区,则先折算为eth,再折算为usdt else if (this.eth.Contains(account.Key.ToUpper())) { var depth = exchange.GetOrderBook(account.Key + "/eth", 1); var bids = depth.Bids.OrderByDescending(a => a.Value.Price); amount += account.Value * bids.ElementAt(0).Value.Price *ethUsdt; } } return(Task.FromResult <decimal>(amount)); }
static decimal GetFirstAsk(string market) { var depth = exchange.GetOrderBook(market, 1); var asks = depth.Asks.OrderByDescending(a => a.Value.Price); return(asks.ElementAt(0).Value.Price); }
/// <summary> /// Get full order book bids and asks via web socket. This is efficient and will only use the order book deltas. /// </summary> /// <param name="callback">Callback of symbol, order book</param> /// <param name="maxCount">Max count of bids and asks - not all exchanges will honor this parameter</param> /// <param name="symbol">Ticker symbols or null/empty for all of them (if supported)</param> /// <returns>Web socket, call Dispose to close</returns> public static IDisposable GetOrderBookWebSocket(this IExchangeAPI api, Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols) { // Gets a delta socket for a collection of order books, then maintains a full order book. // The suggested way to use this is: // 1. Open this socket and begin buffering events you receive // 2. Get a depth snapshot of the order books you care about // 3. Drop any event where SequenceNumber is less than or equal to the snapshot last update id // Notes: // * Confirm with the Exchange's API docs whether the data in each event is the absolute quantity or differential quantity // * If the quantity is 0, remove the price level // * Receiving an event that removes a price level that is not in your local order book can happen and is normal. // Dictionary <string, ExchangeOrderBook> fullBooks = new Dictionary <string, ExchangeOrderBook>(); void innerCallback(ExchangeOrderBook book) { // see if we have a full order book for the symbol if (!fullBooks.TryGetValue(book.Symbol, out ExchangeOrderBook fullBook)) { fullBooks[book.Symbol] = fullBook = api.GetOrderBook(book.Symbol, 1000); fullBook.Symbol = book.Symbol; } // update deltas as long as the full book is at or before the delta timestamp if (fullBook.SequenceId <= book.SequenceId) { foreach (var ask in book.Asks) { if (ask.Value.Amount <= 0m || ask.Value.Price <= 0m) { fullBook.Asks.Remove(ask.Value.Price); } else { fullBook.Asks[ask.Value.Price] = ask.Value; } } foreach (var bid in book.Bids) { if (bid.Value.Amount <= 0m || bid.Value.Price <= 0m) { fullBook.Bids.Remove(bid.Value.Price); } else { fullBook.Bids[bid.Value.Price] = bid.Value; } } fullBook.SequenceId = book.SequenceId; } callback(fullBook); }; return(api.GetOrderBookDeltasWebSocket(innerCallback, maxCount, symbols)); }
/// <summary>Get full order book bids and asks via web socket. This is efficient and will /// only use the order book deltas (if supported by the exchange).</summary> /// <param name="callback">Callback containing full order book</param> /// <param name="maxCount">Max count of bids and asks - not all exchanges will honor this /// parameter</param> /// <param name="symbols">Ticker symbols or null/empty for all of them (if supported)</param> /// <returns>Web socket, call Dispose to close</returns> public static IWebSocket GetOrderBookWebSocket(this IExchangeAPI api, Action <ExchangeOrderBook> callback, int maxCount = 20, params string[] symbols) { // Notes: // * Confirm with the Exchange's API docs whether the data in each event is the absolute quantity or differential quantity // * Receiving an event that removes a price level that is not in your local order book can happen and is normal. var fullBooks = new ConcurrentDictionary <string, ExchangeOrderBook>(); void innerCallback(ExchangeOrderBook freshBook) { bool foundFullBook = fullBooks.TryGetValue(freshBook.Symbol, out ExchangeOrderBook fullOrderBook); switch (api.Name) { // Fetch an initial book the first time and apply deltas on top case ExchangeName.Bittrex: case ExchangeName.Binance: case ExchangeName.Poloniex: { // If we don't have an initial order book for this symbol, fetch it if (!foundFullBook) { fullBooks[freshBook.Symbol] = fullOrderBook = api.GetOrderBook(freshBook.Symbol, 1000); fullOrderBook.Symbol = freshBook.Symbol; } // update deltas as long as the full book is at or before the delta timestamp if (fullOrderBook.SequenceId <= freshBook.SequenceId) { ApplyDelta(freshBook.Asks, fullOrderBook.Asks); ApplyDelta(freshBook.Bids, fullOrderBook.Bids); fullOrderBook.SequenceId = freshBook.SequenceId; } break; } // First response from exchange will be the full order book. // Subsequent updates will be deltas case ExchangeName.BitMEX: case ExchangeName.Okex: { if (!foundFullBook) { fullBooks[freshBook.Symbol] = fullOrderBook = freshBook; fullOrderBook.Symbol = freshBook.Symbol; } else { ApplyDelta(freshBook.Asks, fullOrderBook.Asks); ApplyDelta(freshBook.Bids, fullOrderBook.Bids); } break; } // Websocket always returns full order book case ExchangeName.Huobi: { fullBooks[freshBook.Symbol] = fullOrderBook = freshBook; break; } } callback(fullOrderBook); } IWebSocket socket = api.GetOrderBookDeltasWebSocket(innerCallback, maxCount, symbols); socket.Connected += (s) => { // when we re-connect, we must invalidate the order books, who knows how long we were disconnected // and how out of date the order books are fullBooks.Clear(); }; return(socket); }