Skip to content

Commit

Permalink
fix GetFullOrderBookWebSocketAsync data inconsistency (#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
BZ-CO authored Jan 10, 2022
1 parent a1c8ef0 commit 855600f
Show file tree
Hide file tree
Showing 17 changed files with 51 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ protected override async Task<IWebSocket> OnGetDeltaOrderBookWebSocketAsync(Acti
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken obj = await MakeJsonRequestAsync<JToken>($"/depth?symbol={marketSymbol}&limit={maxCount}", BaseUrlApi);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj, sequence: "lastUpdateId", maxCount: maxCount);
return obj.ParseOrderBookFromJTokenArrays(sequence: "lastUpdateId");
}

protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ protected override async Task<IEnumerable<KeyValuePair<string, ExchangeTicker>>>
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
var data = await MakeRequestBithumbAsync(marketSymbol, "/public/orderbook/$SYMBOL$");
return ExchangeAPIExtensions.ParseOrderBookFromJTokenDictionaries(data.Item1, amount: "quantity", sequence: "timestamp", maxCount: maxCount);
return data.Item1.ParseOrderBookFromJTokenDictionaries(amount: "quantity", sequence: "timestamp");
}

protected override async Task<IEnumerable<KeyValuePair<string, ExchangeOrderBook>>> OnGetOrderBooksAsync(int maxCount = 100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ protected override async Task<ExchangeTicker> OnGetTickerAsync(string marketSymb
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken token = await MakeBitstampRequestAsync("/order_book/" + marketSymbol);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token, maxCount: maxCount);
return token.ParseOrderBookFromJTokenArrays();
}

protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down Expand Up @@ -254,7 +254,7 @@ protected override async Task<ExchangeOrderResult> OnGetOrderDetailsAsync(string
// status can be 'Canceled', 'Open' or 'Finished'
var statusCode = result.Value<string>("status");
var status = GetOrderResultFromStatus(statusCode, anyTransaction);

// empty transaction array means that order is InQueue or Open and AmountFilled == 0
// return empty order in this case. no any additional info available at this point
if (!anyTransaction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
}

JToken token = await MakeJsonRequestAsync<JToken>("/markets/" + marketSymbol + "/orderbook" + "?depth=" + maxCount);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenDictionaries(token, "ask", "bid", "rate", "quantity", maxCount: maxCount);
return token.ParseOrderBookFromJTokenDictionaries("ask", "bid", "rate", "quantity");
}

/// <summary>Gets the deposit history for a symbol</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
{
string url = "/products/" + marketSymbol.ToUpperInvariant() + "/book?level=2";
JToken token = await MakeJsonRequestAsync<JToken>(url);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token, maxCount: maxCount);
return token.ParseOrderBookFromJTokenArrays();
}

protected override async Task<IEnumerable<MarketCandle>> OnGetCandlesAsync(string marketSymbol, int periodSeconds, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down Expand Up @@ -661,7 +661,7 @@ protected override async Task<Dictionary<string, decimal>> OnGetFeesAsync()
JObject token = await MakeJsonRequestAsync<JObject>("/fees", null, await GetNoncePayloadAsync(), "GET");
/*
* We can chose between maker and taker fee, but currently ExchangeSharp only supports 1 fee rate per symbol.
* Here, we choose taker fee, which are usually higher
* Here, we choose taker fee, which are usually higher
*/
decimal makerRate = token["taker_fee_rate"].Value<decimal>(); //percentage between 0 and 1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ protected override async Task<ExchangeTicker> OnGetTickerAsync(string marketSymb
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken obj = await MakeJsonRequestAsync<JToken>($"/order_book?symbol={marketSymbol}&limit={maxCount}");
var result = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj, sequence: "date", maxCount: maxCount);
var result = obj.ParseOrderBookFromJTokenArrays(sequence: "date");
result.LastUpdatedUtc = CryptoUtility.UnixTimeStampToDateTimeSeconds(obj["date"].ConvertInvariant<long>());
result.MarketSymbol = marketSymbol;
return result;
Expand Down
10 changes: 5 additions & 5 deletions src/ExchangeSharp/API/Exchanges/FTX/ExchangeFTXAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ protected async override Task<IEnumerable<ExchangeOrderResult>> OnGetOpenOrderDe
{
continue;
}

markets.Add(ParseOrder(token));
}

return markets;
}

Expand All @@ -282,7 +282,7 @@ protected async override Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
{
JToken response = await MakeJsonRequestAsync<JToken>($"/markets/{marketSymbol}/orderbook?depth={maxCount}");

return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(response, maxCount: maxCount);
return response.ParseOrderBookFromJTokenArrays();
}

/// <inheritdoc />
Expand Down Expand Up @@ -519,8 +519,8 @@ private ExchangeOrderResult ParseOrder(JToken token)
AmountFilled = token["filledSize"].ConvertInvariant<decimal>(),
ClientOrderId = token["clientId"].ToStringInvariant(),
Result = token["status"].ToStringInvariant().ToExchangeAPIOrderResult(token["size"].ConvertInvariant<decimal>() - token["filledSize"].ConvertInvariant<decimal>()),
ResultCode = token["status"].ToStringInvariant()
};
ResultCode = token["status"].ToStringInvariant()
};
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string symb
}
*/

var orderBook = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(json, sequence: "current", maxCount: maxCount);
var orderBook = json.ParseOrderBookFromJTokenArrays(sequence: "current");
orderBook.LastUpdatedUtc = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(json["current"].ConvertInvariant<long>());
return orderBook;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ protected override async Task<ExchangeTicker> OnGetTickerAsync(string marketSymb
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken obj = await MakeJsonRequestAsync<JToken>("/book/" + marketSymbol + "?limit_bids=" + maxCount + "&limit_asks=" + maxCount);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenDictionaries(obj, maxCount: maxCount);
return obj.ParseOrderBookFromJTokenDictionaries();
}

protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down
8 changes: 4 additions & 4 deletions src/ExchangeSharp/API/Exchanges/Hitbtc/ExchangeHitbtcAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ protected override async Task<IEnumerable<ExchangeTrade>> OnGetRecentTradesAsync
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken token = await MakeJsonRequestAsync<JToken>("/public/orderbook/" + marketSymbol + "?limit=" + maxCount.ToStringInvariant());
return ExchangeAPIExtensions.ParseOrderBookFromJTokenDictionaries(token, asks: "ask", bids: "bid", amount: "size", maxCount: maxCount);
return token.ParseOrderBookFromJTokenDictionaries(asks: "ask", bids: "bid", amount: "size");
}

protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand All @@ -195,11 +195,11 @@ protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<Exchan
// TODO: Can't get Hitbtc to return other than the last 50 trades even though their API says it should (by orderid or timestamp). When passing either of these parms, it still returns the last 50
// So until there is an update, that's what we'll go with
// UPDATE: 2020/01/19 https://api.hitbtc.com/ GET /api/2/public/trades/{symbol} limit default: 100 max value:1000
//
//
//var maxRequestLimit = 1000; //hard coded for now, should add limit as an argument
var maxRequestLimit = (limit == null || limit < 1 || limit > 1000) ? 1000 : (int)limit;
var maxRequestLimit = (limit == null || limit < 1 || limit > 1000) ? 1000 : (int)limit;
//note that sort must come after limit, else returns default 100 trades, sort default is DESC
JToken obj = await MakeJsonRequestAsync<JToken>("/public/trades/" + marketSymbol + "?limit=" + maxRequestLimit + "?sort=DESC");
JToken obj = await MakeJsonRequestAsync<JToken>("/public/trades/" + marketSymbol + "?limit=" + maxRequestLimit + "?sort=DESC");
//JToken obj = await MakeJsonRequestAsync<JToken>("/public/trades/" + marketSymbol);
if (obj.HasValues)
{
Expand Down
4 changes: 2 additions & 2 deletions src/ExchangeSharp/API/Exchanges/Huobi/ExchangeHuobiAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ protected override async Task<IWebSocket> OnGetDeltaOrderBookWebSocketAsync(Acti
var ch = token["ch"].ToStringInvariant();
var sArray = ch.Split('.');
var marketSymbol = sArray[1].ToStringInvariant();
ExchangeOrderBook book = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token["tick"], maxCount: maxCount);
ExchangeOrderBook book = token["tick"].ParseOrderBookFromJTokenArrays();
book.MarketSymbol = marketSymbol;
callback(book);
}, async (_socket) =>
Expand Down Expand Up @@ -433,7 +433,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
[7995, 0.88],
*/
JToken obj = await MakeJsonRequestAsync<JToken>("/market/depth?symbol=" + marketSymbol + "&type=step0", BaseUrl, null);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj["tick"], sequence: "ts", maxCount: maxCount);
return obj["tick"].ParseOrderBookFromJTokenArrays(sequence: "ts");
}

protected override async Task<IEnumerable<MarketCandle>> OnGetCandlesAsync(string marketSymbol, int periodSeconds, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down
4 changes: 2 additions & 2 deletions src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ protected override async Task<IEnumerable<string>> OnGetMarketSymbolsAsync(bool
}

protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketSymbolsMetadataAsync()
{
{
var markets = new List<ExchangeMarket>();
JToken allPairs = await MakeJsonRequestAsync<JToken>("/0/public/AssetPairs");
var res = (from prop in allPairs.Children<JProperty>() select prop).ToArray();
Expand Down Expand Up @@ -546,7 +546,7 @@ protected override Task OnInitializeAsync()
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken obj = await MakeJsonRequestAsync<JToken>("/0/public/Depth?pair=" + marketSymbol + "&count=" + maxCount);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj[marketSymbol], maxCount: maxCount);
return obj[marketSymbol].ParseOrderBookFromJTokenArrays();
}

protected override async Task<IEnumerable<ExchangeTrade>> OnGetRecentTradesAsync(string marketSymbol, int? limit = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketS
protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string marketSymbol, int maxCount = 100)
{
JToken token = await MakeJsonRequestAsync<JToken>("/market/orderbook/level2_" + maxCount + "?symbol=" + marketSymbol);
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token, asks: "asks", bids: "bids", maxCount: maxCount);
return token.ParseOrderBookFromJTokenArrays(asks: "asks", bids: "bids");
}

protected override async Task<ExchangeTicker> OnGetTickerAsync(string marketSymbol)
Expand Down
2 changes: 1 addition & 1 deletion src/ExchangeSharp/API/Exchanges/LBank/ExchangeLBankAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string symb
maxCount = Math.Min(maxCount, ORDER_BOOK_MAX_SIZE);
JToken resp = await this.MakeJsonRequestAsync<JToken>($"/depth.do?symbol={symbol}&size={maxCount}&merge=0");
CheckResponseToken(resp);
ExchangeOrderBook book = ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(resp, maxCount: maxCount);
ExchangeOrderBook book = resp.ParseOrderBookFromJTokenArrays();
book.SequenceId = resp["timestamp"].ConvertInvariant<long>();
return book;
}
Expand Down
4 changes: 2 additions & 2 deletions src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
{
var token = await MakeJsonRequestAsync<JToken>($"/market/books?instId={marketSymbol}&sz={maxCount}",
BaseUrlV5);
return token[0].ParseOrderBookFromJTokenArrays(maxCount: maxCount);
return token[0].ParseOrderBookFromJTokenArrays();
}

protected override async Task<IEnumerable<MarketCandle>> OnGetCandlesAsync(string marketSymbol,
Expand Down Expand Up @@ -420,7 +420,7 @@ protected override async Task<IWebSocket> OnGetDeltaOrderBookWebSocketAsync(Acti
marketSymbols = await AddMarketSymbolsToChannel(_socket, "books-l2-tbt", marketSymbols);
}, (_socket, symbol, sArray, token) =>
{
ExchangeOrderBook book = token.ParseOrderBookFromJTokenArrays(maxCount: maxCount);
ExchangeOrderBook book = token.ParseOrderBookFromJTokenArrays();
book.MarketSymbol = symbol;
callback(book);
return Task.CompletedTask;
Expand Down
2 changes: 1 addition & 1 deletion src/ExchangeSharp/API/Exchanges/OKGroup/OKGroupCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
{
var token = await MakeRequestOkexAsync(marketSymbol, $"/spot/v3/instruments/{marketSymbol}/book", BaseUrlV3);

return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(token.Item1, maxCount: maxCount);
return token.Item1.ParseOrderBookFromJTokenArrays();
}

protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
Expand Down
48 changes: 23 additions & 25 deletions src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPIExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ The above copyright notice and this permission notice shall be included in all c
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ExchangeSharp.Kraken;
using ExchangeSharp.BinanceGroup;
Expand Down Expand Up @@ -155,9 +156,26 @@ async Task innerCallback(ExchangeOrderBook newOrderBook)
}

fullOrderBook.LastUpdatedUtc = CryptoUtility.UtcNow;
trimFullOrderBook(fullOrderBook);
callback(fullOrderBook);
}

void trimFullOrderBook(ExchangeOrderBook fBook)
{
var asks = fBook.Asks.Take(maxCount).ToList();
var bids = fBook.Bids.Take(maxCount).ToList();
fBook.Asks.Clear();
fBook.Bids.Clear();
foreach (var kvp in asks)
{
fBook.Asks.Add(kvp.Key, kvp.Value);
}
foreach (var kvp in bids)
{
fBook.Bids.Add(kvp.Key, kvp.Value);
}
}

IWebSocket socket = await api.GetDeltaOrderBookWebSocketAsync(async (b) =>
{
try
Expand Down Expand Up @@ -335,36 +353,26 @@ public static async Task<ExchangeOrderResult> PlaceSafeMarketOrderAsync(this Exc
/// <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
string sequence = "ts"
)
{
var book = new ExchangeOrderBook { SequenceId = token[sequence].ConvertInvariant<long>() };
foreach (JArray array in token[asks])
foreach (var 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])
foreach (var 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;
Expand All @@ -378,7 +386,6 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenArrays
/// <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
(
Expand All @@ -387,29 +394,20 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenDictionaries
string bids = "bids",
string price = "price",
string amount = "amount",
string sequence = "ts",
int maxCount = 100
string sequence = "ts"
)
{
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;
Expand Down Expand Up @@ -727,7 +725,7 @@ internal static MarketCandle ParseCandle(this INamed named, JToken token, string
{
candle.WeightedAverage = token[weightedAverageKey].ConvertInvariant<decimal>();
}
if( countKey != null)
if( countKey != null)
{
candle.Count = token[countKey].ConvertInvariant<int>();
}
Expand Down

0 comments on commit 855600f

Please sign in to comment.