Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix GetFullOrderBookWebSocketAsync data inconsistency #714

Merged
merged 1 commit into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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