/// <summary> /// Ordered by ASC /// </summary> public async Task <HttpCandlestickDataResponseDto> GetCandlestickDataAsync( string symbol, string candlestickInterval, DateTime?from = null, DateTime?to = null, int limit = 500 ) { limit = Math.Max(limit, 1000); // split from-to on intervals according to limit and candlestickInterval // as Binance allows max 1000 items to request, but date range could be huge (e.g. 1 year of 1h intervals) if (from.Value != null && to.Value != null) { var candlestickIntervalConfig = BinanceConfig.GetBarChartInterval(candlestickInterval); TimeSpan requestedRange = to.Value.Subtract(from.Value); int candlestickIntervalsInDateRange = Convert.ToInt32(Math.Round(requestedRange.TotalMilliseconds / candlestickIntervalConfig.TimeSpan.TotalMilliseconds, 0)); if (candlestickIntervalsInDateRange > limit) { int requestCount = Convert.ToInt32(Math.Ceiling((double)candlestickIntervalsInDateRange / (double)limit)); TimeSpan requestTimeSpan = limit * candlestickIntervalConfig.TimeSpan; // E.g. 4h * 1000 = 4000 hours var aggregatedResult = new HttpCandlestickDataResponseDto(); DateTime localFrom = from.Value; DateTime localTo = from.Value; for (int i = 0; i < requestCount; i++) { localFrom = localTo; localTo = localFrom.Add(requestTimeSpan); localTo = localTo <= DateTime.UtcNow ? localTo : DateTime.UtcNow; var intermediateResult = await _GetCandlestickDataAsync(symbol, candlestickInterval, localFrom, localTo, limit); aggregatedResult.Candles.AddRange(intermediateResult.Candles); } // order asc aggregatedResult.Candles = aggregatedResult.Candles.OrderBy(x => x.OpenTime).ToList(); return(aggregatedResult); } } return(await _GetCandlestickDataAsync(symbol, candlestickInterval, from, to, limit)); }
private async Task <HttpCandlestickDataResponseDto> _GetCandlestickDataAsync( string symbol, string candlestickInterval, DateTime?from, DateTime?to, int limit ) { string startTime = from.Value != null ? new DateTimeOffset(from.Value).ToUnixTimeMilliseconds().ToString() : string.Empty; string endTime = to.Value != null ? new DateTimeOffset(to.Value).ToUnixTimeMilliseconds().ToString() : string.Empty; var httpResponse = await _httpUtil.GetAsync($"{_binanceConfig.HttpApiUrl}/api/{_apiVersion}/klines?symbol={symbol}&interval={candlestickInterval}&startTime={startTime}&endTime={endTime}&limit={limit}"); _httpUtil.EnsureSuccessStatusCode(httpResponse); string httpContent = await httpResponse.Content.ReadAsStringAsync(); var response = JsonConvert.DeserializeObject <IEnumerable <List <object> > >(httpContent); var dto = new HttpCandlestickDataResponseDto() { Candles = response.Select(candle => { return(new HttpCandlestickDataItemResponseDto() { OpenTime = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(candle[0].ToString())).UtcDateTime, OpenPrice = decimal.Parse(candle[1].ToString()), HighPrice = decimal.Parse(candle[2].ToString()), LowPrice = decimal.Parse(candle[3].ToString()), ClosePrice = decimal.Parse(candle[4].ToString()), Volume = decimal.Parse(candle[5].ToString()), CloseTime = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(candle[6].ToString())).UtcDateTime, QuoteAssetVolume = decimal.Parse(candle[7].ToString()), NumberOfTrades = int.Parse(candle[8].ToString()), TakerBuyBaseAssetVolume = decimal.Parse(candle[9].ToString()), TakerBuyQuoteAssetVolume = decimal.Parse(candle[10].ToString()), ApiIgnoredValue = candle[11].ToString(), }); }).ToList(), }; // order asc dto.Candles = dto.Candles.OrderBy(x => x.OpenTime).ToList(); return(dto); }