コード例 #1
0
        GetCandlesAsync(string assetPairId, CandleTimeInterval interval, DateTime dateFrom, DateTime dateTo)
        {
            var midCandlesTask = _candlesHistoryRepository.GetCandlesAsync(assetPairId, interval,
                                                                           CandlePriceType.Mid, dateFrom, dateTo);
            var askCandlesTask = _candlesHistoryRepository.GetCandlesAsync(assetPairId, interval,
                                                                           CandlePriceType.Ask, dateFrom, dateTo);
            var bidCandlesTask = _candlesHistoryRepository.GetCandlesAsync(assetPairId, interval,
                                                                           CandlePriceType.Bid, dateFrom, dateTo);

            await Task.WhenAll(midCandlesTask, askCandlesTask, bidCandlesTask);

            return(bidCandles : bidCandlesTask.Result.ToList(), askCandles : askCandlesTask.Result.ToList(),
                   midCandles : midCandlesTask.Result.ToList());
        }
        public async Task <IActionResult> GetCandlesHistoryFromDb(string assetPairId, CandlePriceType priceType, CandleTimeInterval timeInterval, DateTime fromMoment, DateTime toMoment)
        {
            fromMoment = fromMoment.ToUniversalTime();
            toMoment   = toMoment.ToUniversalTime();

            if (string.IsNullOrWhiteSpace(assetPairId))
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair is required")));
            }
            if (priceType == CandlePriceType.Unspecified)
            {
                return(BadRequest(ErrorResponse.Create(nameof(timeInterval), $"Price type should not be {CandlePriceType.Unspecified}")));
            }
            if (timeInterval == CandleTimeInterval.Unspecified)
            {
                return(BadRequest(ErrorResponse.Create(nameof(timeInterval), $"Time interval should not be {CandleTimeInterval.Unspecified}")));
            }
            if (fromMoment > toMoment)
            {
                return(BadRequest(ErrorResponse.Create("From date should be early or equal than To date")));
            }
            if (!_candleHistoryAssetConnections.ContainsKey(assetPairId))
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair is not configured")));
            }
            if (await _assetPairsManager.TryGetAssetPairAsync(assetPairId) == null)
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair not found")));
            }

            var candles = await _candlesHistoryRepository.GetCandlesAsync(assetPairId, timeInterval, priceType, fromMoment, toMoment);

            return(Ok(new CandlesHistoryResponseModel
            {
                History = candles.Select(c => new CandlesHistoryResponseModel.Candle
                {
                    DateTime = c.Timestamp,
                    Open = c.Open,
                    Close = c.Close,
                    High = c.High,
                    Low = c.Low,
                    TradingVolume = c.TradingVolume,
                    TradingOppositeVolume = c.TradingOppositeVolume,
                    LastTradePrice = c.LastTradePrice
                })
            }));
        }
コード例 #3
0
        private async Task CacheAssetPairCandlesAsync(AssetPair assetPair, DateTime now, SlotType slotType)
        {
            try
            {
                _log.Info(nameof(InitializeCacheAsync), $"Caching {assetPair.Id} candles history...");

                foreach (CandlePriceType priceType in Constants.StoredPriceTypes)
                {
                    foreach (CandleTimeInterval timeInterval in Constants.InitFromDbIntervals)
                    {
                        DateTime alignedToDate   = now.TruncateTo(timeInterval).AddIntervalTicks(1, timeInterval);
                        DateTime alignedFromDate = alignedToDate.AddIntervalTicks(-_amountOfCandlesToStore[timeInterval] - 1, timeInterval);

                        if (alignedFromDate < _minDate)
                        {
                            alignedFromDate = _minDate.TruncateTo(timeInterval);
                        }

                        ICandle[] candles = (await _candlesHistoryRepository.GetCandlesAsync(assetPair.Id, timeInterval, priceType, alignedFromDate, alignedToDate)).ToArray();

                        if (!candles.Any())
                        {
                            continue;
                        }

                        var intervals = _candlesCacheService.GetRedisCacheIntervals(timeInterval);

                        foreach (var interval in intervals)
                        {
                            ICandle[] intervalCandles = interval != timeInterval
                                ? CandlesMerger.MergeIntoBiggerIntervals(candles, interval).ToArray()
                                : candles;

                            await _candlesCacheService.InitializeAsync(assetPair.Id, priceType, interval, intervalCandles, slotType);
                        }
                    }
                }

                _log.Info($"{assetPair.Id} candles history is cached.");
            }
            catch (Exception ex)
            {
                _log.Error(nameof(CacheAssetPairCandlesAsync), ex);
            }
        }
コード例 #4
0
        private async Task CacheAssetPairCandlesAsync(IAssetPair assetPair, DateTime toDate)
        {
            await _log.WriteInfoAsync(nameof(CandlesCacheInitalizationService), nameof(InitializeCacheAsync), null, $"Caching {assetPair.Id} candles history...");

            foreach (var priceType in Constants.StoredPriceTypes)
            {
                foreach (var timeInterval in Constants.StoredIntervals)
                {
                    var alignedToDate   = toDate.TruncateTo(timeInterval);
                    var alignedFromDate = alignedToDate.AddIntervalTicks(-_amountOfCandlesToStore, timeInterval);
                    var candles         = await _candlesHistoryRepository.GetCandlesAsync(assetPair.Id, timeInterval, priceType, alignedFromDate, alignedToDate);

                    await _candlesCacheService.InitializeAsync(assetPair.Id, priceType, timeInterval, candles.ToArray());
                }
            }

            await _log.WriteInfoAsync(nameof(CandlesCacheInitalizationService), nameof(InitializeCacheAsync), null, $"{assetPair.Id} candles history is cached");
        }
コード例 #5
0
        public async Task <IReadOnlyList <ICandle> > TryGetExtremeCandlesAsync(string assetPairId, CandlePriceType priceType, double limitLow, double limitHigh, double epsilon)
        {
            var(dateFrom, dateTo) = await GetDateTimeRangeAsync(assetPairId, priceType);

            // May be, we have got fake DateTime range. If so, this means there are no candles for the specified asset
            // pair at all and we should skip its filtration in the caller code. Return null.
            if (dateFrom == DateTime.MinValue || dateTo == DateTime.MinValue)
            {
                return(new List <ICandle>());
            }

            var currentMonthBeginingDateTime = dateTo; // We will use it several times below for data query limiting.

            // The list of extreme candles for all stored time periods (there will be not so disastrous amount of them
            // to run out of memory).
            var            extremeCandles = new List <ICandle>();
            List <ICandle> lastCandles    = null;

            // Now we will go through the candle storage deeps from the biggest candle time interval to the smallest one.
            // We can take in mind that if there was an extreme quote (or trade price), it will lead to generation of the
            // faulty (extreme) candles from Second to Month. But we have much less month candles than those for seconds.
            // So, the fastest way to find all the extreme second candles is to find all the extreme month candles first.
            // Then, having the list, we need to iterate it to find an extreme week candles, corresponding to each month,
            // and then a list of day candles, and so on. At the finish, we will obtain all the second candles with wrong
            // prices, and thus, we will be ready to delete 'em and go back through the stored time period list, from the
            // smallest to the biggest, producing the updated (corrected) candles for each of them.

            for (var i = Constants.DbStoredIntervals.Length - 1; i >= 0; i--)
            {
                List <ICandle> currentCandles;

                var interval = Constants.DbStoredIntervals[i];
                if (i == Constants.DbStoredIntervals.Length - 1)
                {
                    var candles = await _candlesHistoryRepository.GetCandlesAsync(assetPairId, interval,
                                                                                  priceType, dateFrom, dateTo);

                    currentCandles = candles
                                     .Where(c => IsExtremeCandle(c, limitLow, limitHigh, epsilon))
                                     .ToList();

                    // There are no incorrect candles at all - returning.
                    if (!currentCandles.Any())
                    {
                        return(extremeCandles); // Empty collection here.
                    }
                }
                else
                {
                    currentCandles = new List <ICandle>();
                    // ReSharper disable once PossibleNullReferenceException
                    foreach (var candle in lastCandles)
                    {
                        dateFrom = candle.Timestamp.TruncateTo(interval); // Truncating is important when searching weeks by months: the first week of month may start earlier than the month. In other cases, TruncateTo is redundant.
                        dateTo   = candle.Timestamp.AddIntervalTicks(1, GetBiggerInterval(interval));
                        if (dateTo > currentMonthBeginingDateTime)
                        {
                            dateTo = currentMonthBeginingDateTime;
                        }

                        var candles = await _candlesHistoryRepository.GetCandlesAsync(assetPairId, interval, priceType, dateFrom, dateTo);

                        currentCandles.AddRange(candles
                                                .Where(c => IsExtremeCandle(c, limitLow, limitHigh, epsilon)));
                    }
                }

                lastCandles = currentCandles;
                extremeCandles.AddRange(currentCandles);
            }

            return(extremeCandles);
        }