Skip to content

Commit 4973501

Browse files
authored
fixed GetHistoricalTradesAsync/GetRecentTradesAsync() issues (#511)
- added `int? limit` as a parameter - added/fixed GetRecentTradesAsync on multiple exchanges (Binance, HitBTC, Bitfinex and numerous others) - for GetRecentTradesAsync, the sort order will be Descending (ie newest trades first) - resolves #510
1 parent 37bd197 commit 4973501

19 files changed

+1060
-997
lines changed

src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ protected override async Task<ExchangeOrderBook> OnGetOrderBookAsync(string mark
332332
return ExchangeAPIExtensions.ParseOrderBookFromJTokenArrays(obj, sequence: "lastUpdateId", maxCount: maxCount);
333333
}
334334

335-
protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null)
335+
protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
336336
{
337337
/* [ {
338338
"a": 26129, // Aggregate tradeId
@@ -345,17 +345,44 @@ protected override async Task OnGetHistoricalTradesAsync(Func<IEnumerable<Exchan
345345
"M": true // Was the trade the best price match?
346346
} ] */
347347

348-
ExchangeHistoricalTradeHelper state = new ExchangeHistoricalTradeHelper(this)
348+
//if(startDate == null && endDate == null) {
349+
// await OnGetRecentTradesAsync(marketSymbol, limit);
350+
//}
351+
//else {
352+
//System.Windows.Forms.MessageBox.Show("Duplicate MessageId " + MessageId, "HMMMM RETURN?");
353+
354+
355+
ExchangeHistoricalTradeHelper state = new ExchangeHistoricalTradeHelper(this)
349356
{
350-
Callback = callback,
351-
EndDate = endDate,
352-
ParseFunction = (JToken token) => token.ParseTrade("q", "p", "m", "T", TimestampType.UnixMilliseconds, "a", "false"),
353-
StartDate = startDate,
354-
MarketSymbol = marketSymbol,
355-
TimestampFunction = (DateTime dt) => ((long)CryptoUtility.UnixTimestampFromDateTimeMilliseconds(dt)).ToStringInvariant(),
356-
Url = "/aggTrades?symbol=[marketSymbol]&startTime={0}&endTime={1}",
357-
};
358-
await state.ProcessHistoricalTrades();
357+
Callback = callback,
358+
EndDate = endDate,
359+
ParseFunction = (JToken token) => token.ParseTrade("q", "p", "m", "T", TimestampType.UnixMilliseconds, "a", "false"),
360+
StartDate = startDate,
361+
MarketSymbol = marketSymbol,
362+
TimestampFunction = (DateTime dt) => ((long)CryptoUtility.UnixTimestampFromDateTimeMilliseconds(dt)).ToStringInvariant(),
363+
Url = "/aggTrades?symbol=[marketSymbol]&startTime={0}&endTime={1}",
364+
};
365+
await state.ProcessHistoricalTrades();
366+
//}
367+
}
368+
369+
protected override async Task<IEnumerable<ExchangeTrade>> OnGetRecentTradesAsync(string marketSymbol, int? limit = null)
370+
{
371+
List<ExchangeTrade> trades = new List<ExchangeTrade>();
372+
//var maxRequestLimit = 1000; //hard coded for now, should add limit as an argument
373+
//https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
374+
int maxRequestLimit = (limit == null || limit < 1 || limit > 1000) ? 1000 : (int)limit;
375+
376+
JToken obj = await MakeJsonRequestAsync<JToken>($"/aggTrades?symbol={marketSymbol}&limit={maxRequestLimit}");
377+
//JToken obj = await MakeJsonRequestAsync<JToken>("/public/trades/" + marketSymbol + "?limit=" + maxRequestLimit + "?sort=DESC");
378+
if(obj.HasValues) { //
379+
foreach(JToken token in obj) {
380+
var trade = token.ParseTrade("q", "p", "m", "T", TimestampType.UnixMilliseconds, "a", "false");
381+
trades.Add(trade);
382+
}
383+
}
384+
return trades.AsEnumerable().Reverse(); //Descending order (ie newest trades first)
385+
//return trades;
359386
}
360387

361388
public async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, long startId, long? endId = null)
@@ -407,6 +434,56 @@ public async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bo
407434
} while (callback(trades) && trades.Count > 0);
408435
}
409436

437+
public async Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, int limit = 100)
438+
{
439+
/* [ {
440+
"a": 26129, // Aggregate tradeId
441+
"p": "0.01633102", // Price
442+
"q": "4.70443515", // Quantity
443+
"f": 27781, // First tradeId
444+
"l": 27781, // Last tradeId
445+
"T": 1498793709153, // Timestamp
446+
"m": true, // Was the buyer the maker?
447+
"M": true // Was the trade the best price match?
448+
} ] */
449+
450+
// TODO : Refactor into a common layer once more Exchanges implement this pattern
451+
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
452+
if(limit > 1000) limit = 1000; //Binance max = 1000
453+
var maxRequestLimit = 1000;
454+
var trades = new List<ExchangeTrade>();
455+
var processedIds = new HashSet<long>();
456+
marketSymbol = NormalizeMarketSymbol(marketSymbol);
457+
458+
do {
459+
//if(fromId > endId)
460+
// break;
461+
462+
trades.Clear();
463+
//var limit = Math.Min(endId - fromId ?? maxRequestLimit, maxRequestLimit);
464+
var obj = await MakeJsonRequestAsync<JToken>($"/aggTrades?symbol={marketSymbol}&limit={limit}");
465+
466+
foreach(var token in obj) {
467+
var trade = token.ParseTrade("q", "p", "m", "T", TimestampType.UnixMilliseconds, "a", "false");
468+
//long tradeId = (long)trade.Id.ConvertInvariant<ulong>();
469+
//if(tradeId < fromId)
470+
// continue;
471+
//if(tradeId > endId)
472+
// continue;
473+
//if(!processedIds.Add(tradeId))
474+
// continue;
475+
476+
trades.Add(trade);
477+
//fromId = tradeId;
478+
}
479+
480+
//fromId++;
481+
} while(callback(trades) && trades.Count > 0);
482+
}
483+
484+
485+
486+
410487
protected override async Task<IEnumerable<MarketCandle>> OnGetCandlesAsync(string marketSymbol, int periodSeconds, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
411488
{
412489
/* [

src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ protected override async Task<IEnumerable<MarketCandle>> OnGetCandlesAsync(strin
125125

126126
protected override async Task<Dictionary<string, decimal>> OnGetAmountsAsync() => await OnGetAmountsAsyncCore("onhand_amount");
127127

128-
protected override Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null)
128+
protected override Task OnGetHistoricalTradesAsync(Func<IEnumerable<ExchangeTrade>, bool> callback, string marketSymbol, DateTime? startDate = null, DateTime? endDate = null, int? limit = null)
129129
{
130130
throw new NotImplementedException();
131131
}

0 commit comments

Comments
 (0)