public async Task <IEnumerable <Rate> > GetRateByFilterAsync(RateFilterModel filterModel)
        {
            if (filterModel.DateTo < filterModel.DateFrom || filterModel.DateFrom.AddMonths(2) < filterModel.DateTo)
            {
                throw new ArgumentException("Invalid filter model. Date range is invalid.");
            }
            var baseIsAvailable = await _ratesRepository.CheckAvailableBaseCurrencyAsync(filterModel.BaseCurrency.Id);

            var resultsIsAvailable =
                await _ratesRepository.CheckAvailableResultCurrenciesAsync(
                    filterModel.ResultCurrencyList.Select(x => x.Id));

            if (!baseIsAvailable || !resultsIsAvailable)
            {
                throw new ArgumentException("Invalid filter model. Check your currency accessing.");
            }
            var cachingRates = await _ratesRepository.GetRatesInfoAsync(filterModel);

            if (cachingRates.Count() == filterModel.ResultCurrencyList.Count() *
                filterModel.DateFrom.GetBusinessDaysCount(filterModel.DateTo))
            {
                return(cachingRates);
            }
            else
            {
                var newRates = await GetMissingRates(filterModel, cachingRates);

                await _ratesRepository.AddRangeRatesInfoAsync(newRates);

                var result = cachingRates.ToList();
                result.AddRange(newRates);
                return(result.GroupBy(x => new { x.ResultCurrencyId, x.RateDate }).Select(x => x.First()));
            }
        }
Example #2
0
        public async Task <IEnumerable <Rate> > GetRatesInfoAsync(RateFilterModel filterModel)
        {
            var resultCurrencyIds = filterModel.ResultCurrencyList.Select(x => x.Id);

            return(await _appContext.Rates
                   .Include(x => x.BaseCurrency)
                   .Include(x => x.ResultCurrency)
                   .Where(x => x.BaseCurrencyId == filterModel.BaseCurrency.Id &&
                          resultCurrencyIds.Contains(x.ResultCurrencyId) &&
                          x.RateDate >= filterModel.DateFrom &&
                          x.RateDate <= filterModel.DateTo).ToListAsync());
        }
        private async Task <IEnumerable <Rate> > GetMissingRates(RateFilterModel filterModel,
                                                                 IEnumerable <Rate> cachingRates)
        {
            var response = new RatesResponse();

            if (!cachingRates.Any())
            {
                response = await _externalRatesService.GetRatesAsync(filterModel.DateFrom,
                                                                     filterModel.DateTo,
                                                                     filterModel.BaseCurrency.Code,
                                                                     filterModel.ResultCurrencyList.Select(x => x.Code));
            }
            else
            {
                var groupingCachingRates      = cachingRates.GroupBy(x => x.ResultCurrencyId);
                var fullMissingResultCurrency =
                    GetFullMissingResultCurrencyCodes(groupingCachingRates.Select(x => x.First().ResultCurrency.Code),
                                                      filterModel.ResultCurrencyList.Select(x => x.Code));
                var partiallyMissingResultCurrency =
                    GetPartiallyMissingResultCurrencyCodes(groupingCachingRates, filterModel.DateFrom, filterModel.DateTo);
                var minMaxUpdatingInterval = new Tuple <DateTime?, DateTime?>(null, null);
                if (!partiallyMissingResultCurrency.Any() && !fullMissingResultCurrency.Any())
                {
                    return(new List <Rate>());
                }

                if (fullMissingResultCurrency.Any())
                {
                    minMaxUpdatingInterval = new Tuple <DateTime?, DateTime?>(filterModel.DateFrom, filterModel.DateTo);
                }
                else
                {
                    if (partiallyMissingResultCurrency.Any())
                    {
                        minMaxUpdatingInterval = GetMinMaxMissingIntervalByCachingItems(cachingRates, filterModel.DateFrom, filterModel.DateTo);
                    }
                }


                if (!minMaxUpdatingInterval.Item1.HasValue || !minMaxUpdatingInterval.Item2.HasValue)
                {
                    throw new ArgumentException("Nothing to search. Min/Max interval not found");
                }

                var missingCurrencyCodes = new List <string>(fullMissingResultCurrency);
                missingCurrencyCodes.AddRange(partiallyMissingResultCurrency);
                response = await _externalRatesService.GetRatesAsync(minMaxUpdatingInterval.Item1.Value, minMaxUpdatingInterval.Item2.Value,
                                                                     filterModel.BaseCurrency.Code,
                                                                     missingCurrencyCodes);
            }
            return(await ConvertResponseToList(response));
        }
Example #4
0
        public async Task <IActionResult> GetRates([FromBody] RateFilterModel filterModel)
        {
            var result = await _ratesService.GetCalculatedRatesByFilterAsync(filterModel);

            return(Ok(result));
        }
        public async Task <IEnumerable <CalculatedRatesModel> > GetCalculatedRatesByFilterAsync(RateFilterModel filterModel)
        {
            var rates = await GetRateByFilterAsync(filterModel);

            var grouping       = rates.GroupBy(x => x.ResultCurrencyId);
            var result         = new List <CalculatedRatesModel>();
            var badBrokerPrice = _configuration.GetValue <decimal>("BadBrokerPrice");

            foreach (var item in grouping)
            {
                var      orderedRates  = item.OrderBy(x => x.RateDate).ToList();
                decimal  bestValue     = 0;
                DateTime?bestStartDate = null;
                DateTime?bestEndDate   = null;
                //Find optimal start/stop date for buy
                for (var i = 0; i < orderedRates.Count() - 1; i++)
                {
                    for (var j = i; j < orderedRates.Count(); j++)
                    {
                        var value =
                            (orderedRates[i].RateValue * filterModel.InputValueMoney / orderedRates[j].RateValue)
                            - (orderedRates[j].RateDate.Subtract(orderedRates[i].RateDate).Days) * badBrokerPrice;
                        if (value > bestValue)
                        {
                            bestValue     = value;
                            bestStartDate = orderedRates[i].RateDate;
                            bestEndDate   = orderedRates[j].RateDate;
                        }
                    }
                }
                result.Add(new CalculatedRatesModel
                {
                    ResultCurrency = orderedRates.First().ResultCurrency,
                    BaseCurrency   = orderedRates.First().BaseCurrency,
                    RatesInfoList  = orderedRates.Select(x => new CalculatedRatesInfoModel
                    {
                        Date  = x.RateDate,
                        Value = x.RateValue
                    }),
                    BestStartDate  = bestStartDate,
                    BestEndingDate = bestEndDate,
                    MaxMoneyValue  = bestValue
                });
            }

            return(result);
        }