Example #1
0
        public async Task ImportAllMinutePairCandles(string fromSymbol, string toSymbol, string exchange)
        {
            ExchangePair pair = await _coreDBContext.Pairs
                                .FirstOrDefaultAsync(x =>
                                                     x.CurrencyTo.Symbol == toSymbol &&
                                                     x.CurrencyFrom.Symbol == fromSymbol &&
                                                     x.Exchange.Name == exchange);

            if (pair != null)
            {
                var command = new HistoricalCandleCommand
                {
                    Exchange   = exchange,
                    FromSymbol = fromSymbol,
                    ToSymbol   = toSymbol,
                    Period     = AlphaVantageHistoricalPeriod.OneMinute
                };
                var commandResult = await _cryptoCompareGateway.HistoricalCandle(command);

                if (commandResult?.IsSuccess == true && commandResult.Content.Count > 0)
                {
                    List <Candle> candles = _mapper.Map <List <Candle> >(commandResult.Content);
                    candles.ForEach(c => c.ExchangePairId = pair.Id);
                    if (candles?.Count > 0)
                    {
                        await _coreDBContext.AddRangeAsync(candles);

                        await _coreDBContext.SaveChangesAsync();
                    }
                }
            }
        }
    public void ExchangePairShouldBeSame()
    {
        // Todo: fix this duplicates. Code smell's !!!!!!!!!!!! ASAP
        var pair1 = new ExchangePair(TestsInput.Binance, TestsInput.BtcToUsd);
        var pair2 = new ExchangePair(TestsInput.Binance, TestsInput.BtcToUsd);

        pair1.Should().Be(pair2);
    }
    public void OnlyValidPairsCanBeCreated()
    {
        //Explanation:

        //The key here is probably PAIR ??
        //We Accept probably ANY exchange
        //but check only Pair validity there
        //this is first bell's about Pair type

        var shouldNeverHappenPair = new ExchangePair(TestsInput.Binance, TestsInput.BtcToUsdInvalid);
    }
    public void ExchangePairShouldBeSame()
    {
        //Todo: fix this duplicates. Code smell's
        var pair1 = new ExchangePair()
        {
            Exchange = TestsInput.Binance, Pair = TestsInput.BtcToUsd
        };
        var pair2 = new ExchangePair()
        {
            Exchange = TestsInput.Binance, Pair = TestsInput.BtcToUsd
        };

        pair1.Should().Be(pair2);
    }
        private async Task <decimal> DefineAmountToTrade(ExchangePair crossBittrex, decimal amountBtc, decimal amountEth)
        {
            string firtsCurInChain = crossBittrex.PurchasePath.ToUpper().Split('-')[0];

            if (firtsCurInChain == "BTC")
            {
                return(amountBtc > 0 ? amountBtc : (decimal)0.00051);
            }
            else if (firtsCurInChain == "ETH")
            {
                return(amountEth > 0 ? amountEth : (decimal)0.0082);
            }
            else
            {
                return((decimal)0.00055 / allPairs[$"BTC-{firtsCurInChain}"].PurchasePrice);
            }

            decimal curBalance = (decimal)(await GetBalance(firtsCurInChain)).Result["Available"];

            lock (allPairs) {
                if (firtsCurInChain == "BTC")
                {
                    if ((decimal)0.00051 <= curBalance)
                    {
                        return((decimal)0.00051);
                    }
                }
                else if (firtsCurInChain == "USDT")
                {
                    if ((decimal)0.00051 <= curBalance / allPairs["USDT-BTC"].PurchasePrice)
                    {
                        return((decimal)0.00051 * allPairs["USDT-BTC"].SellPrice);
                    }
                }
                else
                {
                    if ((decimal)0.00055 <= curBalance * allPairs[$"BTC-{firtsCurInChain}"].SellPrice)
                    {
                        return((decimal)0.00051 / allPairs[$"BTC-{firtsCurInChain}"].PurchasePrice);
                    }
                }
            }
            return(0);
        }
Example #6
0
        public async Task ImportAllExchangePairs()
        {
            var result = await _cryptoCompareGateway.AllExchangePairs();

            List <ExchangePairsDTO> exchangePairsDTOs = result?.Content;
            List <Exchange>         exchanges         = _coreDBContext.Exchanges.AsEnumerable().Where(e => exchangePairsDTOs?.Exists(d => d.Name == e.Name) == true).ToList();
            List <Currency>         currencies        = await _coreDBContext.Currencies.ToListAsync();

            List <ExchangePair> exchangePairs = new List <ExchangePair>();

            if (exchangePairsDTOs?.Any() == true)
            {
                foreach (var exchangeDto in exchangePairsDTOs)
                {
                    Exchange exchange = exchanges?.FirstOrDefault(e => e.Name == exchangeDto.Name);
                    if (exchange != null)
                    {
                        foreach (var pair in exchangeDto.Pairs)
                        {
                            Currency currencyFrom = currencies?.FirstOrDefault(c => c.Symbol == pair.CurrencyFrom);
                            Currency currencyTo   = currencies?.FirstOrDefault(c => c.Symbol == pair.CurrencyTo);
                            if (currencyFrom != null && currencyTo != null)
                            {
                                var exchangePair = new ExchangePair
                                {
                                    ExchangeId     = exchange.Id,
                                    CurrencyFromId = currencyFrom.Id,
                                    CurrencyToId   = currencyTo.Id,
                                };
                                exchangePairs.Add(exchangePair);
                            }
                        }
                    }
                }
            }

            if (exchangePairs.Any())
            {
                await _coreDBContext.AddRangeAsync(exchangePairs);

                await _coreDBContext.SaveChangesAsync();
            }
        }
 public static void ApplyExchangePairPrice(ExchangePair exchangePair, float price)
 {
     PairPrice[exchangePair] = price;
 }
 public static float GetPriceFor(ExchangePair exchangePair)
 {
     return(PairPrice[exchangePair]);
 }
        private async Task <(decimal, decimal, ExchangePair)> SellCurrency(decimal myAmount, string pair, decimal resultDealDone, ExchangePair crossBittrex)
        {
            decimal sellRate = allPairs[pair].SellPrice;

            Console.WriteLine($"[Try to sell] {pair}  rate: {sellRate}");

            decimal bestSellRate = 0;

            Console.WriteLine($"MyAmount: {myAmount}");
            decimal gotQuantityRemember = 0;

            while (myAmount > 0)
            {
                JArray  buyOrders        = (JArray)GetOrderBook(pair).Result.Result["buy"];
                decimal bestSellRateNew  = (decimal)buyOrders[0]["Rate"];
                decimal bestSellQuantity = (decimal)buyOrders[0]["Quantity"];
                if (bestSellRateNew == bestSellRate || bestSellRateNew < sellRate && gotQuantityRemember == 0)
                {
                    List <ExchangePair>      crossRatesByMarket1 = new List <ExchangePair>();
                    Dictionary <string, int> curStartChain1      = new Dictionary <string, int> {
                        [pair.Split('-')[1]] = 0
                    };
                    FloydWarshell.FindCrossesOnMarket(ref crossRatesByMarket1, curStartChain1, new BittrexMarket(), false);
                    if (crossRatesByMarket1.Count != 0)
                    {
                        crossBittrex = crossRatesByMarket1.FirstOrDefault();
                        if (crossBittrex?.SellPath != null && !crossBittrex.SellPath.Split('-').Contains("BTC"))
                        {
                            crossBittrex.SellPath = "BTC-" + crossBittrex?.SellPath;
                        }
                        else if (crossBittrex?.SellPath != null && crossBittrex.SellPath.Split('-').Contains("BTC"))
                        {
                            string[] splitedSellPath = crossBittrex.SellPath.Split('-');
                            crossBittrex.SellPath = "";
                            int    ind = splitedSellPath.Length - 1;
                            string cur = splitedSellPath[ind--];
                            while (cur != "BTC")
                            {
                                crossBittrex.SellPath = '-' + cur + crossBittrex.SellPath;
                                cur = splitedSellPath[ind--];
                            }

                            crossBittrex.SellPath = "BTC" + crossBittrex.SellPath;
                        }
                        Console.WriteLine($"[NEW] {crossBittrex?.PurchasePath} {crossBittrex?.SellPath} {crossBittrex?.Spread}");
                        return(0, 1, crossBittrex);
                    }
                    await Task.Delay(5000);

                    continue;
                }

                bestSellRate = bestSellRateNew;
                if (bestSellQuantity < myAmount)
                {
                    myAmount            -= bestSellQuantity;
                    gotQuantityRemember += bestSellQuantity * (bestSellRate * (1 - FeeSell));
                }
                else
                {
                    gotQuantityRemember += myAmount * (bestSellRate * (1 - FeeSell));
                    myAmount             = 0;
                }
            }
            Console.WriteLine($"gotQuantityRemember {gotQuantityRemember}");

            return(gotQuantityRemember, resultDealDone *(sellRate * (1 - FeeSell)), crossBittrex);

            decimal sellQuantity = myAmount;

            ResponseWrapper responseSellOrder = await CreateSellORder(pair, sellQuantity, sellRate);

            string orderUuid;

            try {
                orderUuid = (string)responseSellOrder.Result["uuid"];
            } catch (Exception e) {
                Console.WriteLine($"EXCEPTION BUY: {responseSellOrder.Message}");
                throw;
            }

            if (!responseSellOrder.Success)
            {
                Console.WriteLine($"[ResponseError] Pair: {pair}, mess: {responseSellOrder.Message}");
                return(0, 1, crossBittrex);
            }

            var     checkOrder = "";
            decimal quantityRemains;

            (checkOrder, quantityRemains) = await CheckOrder(orderUuid);

            List <ExchangePair>      crossRatesByMarket = new List <ExchangePair>();
            Dictionary <string, int> curStartChain      = new Dictionary <string, int> {
                [pair.Split('-')[1]] = 0
            };

            while (checkOrder != "Ok")
            {
                Console.WriteLine($"[Check order]: {checkOrder} quantityRemains: {quantityRemains}");

                /*if (checkOrder == "Fail") {
                 *  FloydWarshell.FindCrossesOnMarket(ref crossRatesByMarket, curStartChain, new BittrexMarket(), false);
                 *  if (crossRatesByMarket.Count != 0) {
                 *      crossBittrex = crossRatesByMarket.FirstOrDefault();
                 *      if (crossBittrex?.SellPath != null && !crossBittrex.SellPath.Split('-').Contains("ETH")) {
                 *          crossBittrex.SellPath = "ETH-" + crossBittrex?.SellPath;
                 *      } else if (crossBittrex?.SellPath != null && crossBittrex.SellPath.Split('-').Contains("ETH")) {
                 *          string[] splitedSellPath = crossBittrex.SellPath.Split('-');
                 *          crossBittrex.SellPath = "";
                 *          int ind = splitedSellPath.Length - 1;
                 *          string cur = splitedSellPath[ind--];
                 *          while (cur != "ETH") {
                 *              crossBittrex.SellPath = '-' + cur + crossBittrex.SellPath;
                 *              cur = splitedSellPath[ind--];
                 *          }
                 *
                 *          crossBittrex.SellPath = "ETH" + crossBittrex.SellPath;
                 *      }
                 *
                 *      bool canceled = (await CancelOrder(orderUuid)).Success;
                 *      if (canceled) {
                 *          return (0, 1, crossBittrex);
                 *      }
                 *  }
                 * }*/

                await Task.Delay(4000);

                (checkOrder, quantityRemains) = await CheckOrder(orderUuid);
            }

            return(decimal.Truncate((sellQuantity * (sellRate * (1 - FeeSell))) * 100000000) / 100000000, resultDealDone *(sellRate * (1 - FeeSell)), crossBittrex);
        }
Example #10
0
        public static void FindCrossesOnMarket(ref List <ExchangePair> crossRatesByMarket,
                                               Dictionary <string, int> curStartChain, BasicCryptoMarket market, bool needToSaveInTimeService = true)
        {
            double[,] currenciesMatrixPurchaseMin = new double[market.Currencies.Count, market.Currencies.Count];
            double[,] currenciesMatrixSellMax     = new double[market.Currencies.Count, market.Currencies.Count];

            int[, ,] visitedPurchaseMin = new int[market.Currencies.Count, market.Currencies.Count, market.Currencies.Count];
            int[, ,] visitedSellMax     = new int[market.Currencies.Count, market.Currencies.Count, market.Currencies.Count];

            int[,] nextPurchase = new int[market.Currencies.Count, market.Currencies.Count];
            int[,] nextSell     = new int[market.Currencies.Count, market.Currencies.Count];

            for (int i = 0; i < market.Currencies.Count; i++)
            {
                foreach (string cur in curStartChain.Keys.ToArray())
                {
                    if (market.Currencies[i] == cur)
                    {
                        curStartChain[cur] = i;
                    }
                }

                for (int j = 0; j < market.Currencies.Count; j++)
                {
                    nextPurchase[i, j] = i;
                    nextSell[i, j]     = i;

                    visitedPurchaseMin[i, j, i] = 1;
                    visitedPurchaseMin[i, j, j] = 1;
                    visitedSellMax[i, j, i]     = 1;
                    visitedSellMax[i, j, j]     = 1;

                    if (i == j)
                    {
                        currenciesMatrixPurchaseMin[i, j] = 1;
                        currenciesMatrixSellMax[i, j]     = 1;
                        continue;
                    }
                    currenciesMatrixPurchaseMin[i, j] = int.MaxValue;
                    currenciesMatrixSellMax[i, j]     = 0;
                }
            }

            foreach (KeyValuePair <string, ExchangePair> pair in market.Pairs)
            {
                string[] currencies = pair.Key.Split('-');
                int      index1     = market.Currencies.IndexOf(currencies[0]);
                int      index2     = market.Currencies.IndexOf(currencies[1]);

                currenciesMatrixPurchaseMin[index1, index2] = (double)pair.Value.PurchasePrice;
                currenciesMatrixPurchaseMin[index2, index1] = (double)(Math.Round(1 / pair.Value.SellPrice, 20));

                currenciesMatrixSellMax[index1, index2] = (double)pair.Value.SellPrice;
                currenciesMatrixSellMax[index2, index1] = (double)(Math.Round(1 / pair.Value.PurchasePrice, 20));
            }

            //Алгоритм Флойда-Уоршелла нахождения кратчайших путей между всеми парами вершин

            for (int k = 0; k < market.Currencies.Count; k++)
            {
                for (int i = 0; i < market.Currencies.Count; i++)
                {
                    foreach (int curIndex in curStartChain.Values)
                    {
                        if (i != curIndex && visitedPurchaseMin[curIndex, i, nextPurchase[k, i]] != 1 &&
                            currenciesMatrixPurchaseMin[curIndex, i] - currenciesMatrixPurchaseMin[curIndex, k] *
                            currenciesMatrixPurchaseMin[k, i] > 0.00000001)
                        {
                            currenciesMatrixPurchaseMin[curIndex, i]            = currenciesMatrixPurchaseMin[curIndex, k] * currenciesMatrixPurchaseMin[k, i];
                            visitedPurchaseMin[curIndex, i, nextPurchase[k, i]] = 1;
                            nextPurchase[curIndex, i] = nextPurchase[k, i];
                        }
                    }
                }
            }

            for (int k = 0; k < market.Currencies.Count; k++)
            {
                for (int i = 0; i < market.Currencies.Count; i++)
                {
                    foreach (int curIndex in curStartChain.Values)
                    {
                        if (i != curIndex && visitedSellMax[curIndex, i, nextSell[k, i]] != 1 && currenciesMatrixSellMax[curIndex, i] - currenciesMatrixSellMax[curIndex, k] * currenciesMatrixSellMax[k, i] < -0.00000001)
                        {
                            currenciesMatrixSellMax[curIndex, i]        = currenciesMatrixSellMax[curIndex, k] * currenciesMatrixSellMax[k, i];
                            visitedSellMax[curIndex, i, nextSell[k, i]] = 1;
                            nextSell[curIndex, i] = nextSell[k, i];
                        }
                    }
                }
            }

            for (int i = 0; i < market.Currencies.Count; i++)
            {
                for (int j = 0; j < market.Currencies.Count; j++)
                {
                    if (i != j && currenciesMatrixPurchaseMin[i, j] < currenciesMatrixSellMax[i, j] && curStartChain.Values.Contains(i))
                    {
                        ExchangePair crossRatePair = new ExchangePair();
                        try {
                            crossRatePair.PurchasePath = GetPath(i, j, new List <int>(), nextPurchase, market.Currencies, market.Currencies[j]);
                            crossRatePair.SellPath     = GetPath(i, j, new List <int>(), nextSell, market.Currencies, market.Currencies[j]);
                        } catch (Exception e) {
                            //Console.WriteLine($"Exception: {e.Message}");
                            continue;
                        }
                        crossRatePair.Market = market.MarketName;
                        try {
                            crossRatePair.PurchasePrice = (decimal)currenciesMatrixPurchaseMin[i, j];
                            crossRatePair.SellPrice     = (decimal)currenciesMatrixSellMax[i, j];
                            if (crossRatePair.PurchasePrice > 0 && crossRatePair.SellPrice > 0)
                            {
                                crossRatePair.IsCross = true;
                                crossRatePair.Spread  = Math.Round((crossRatePair.SellPrice - crossRatePair.PurchasePrice) / crossRatePair.PurchasePrice * 100, 4);
                                if (crossRatePair.Market == "Bittrex" && crossRatePair.PurchasePath.Split('-')[0] == "BTC" && needToSaveInTimeService)
                                {
                                    ShowRates(crossRatePair.PurchasePath.Split('-'), true, market);
                                    ShowRates(crossRatePair.SellPath.Split('-'), false, market);

                                    TimeService.AddCrossRateByMarketBittrex(crossRatePair);
                                }
                                crossRatesByMarket.Add(crossRatePair);
                            }
                        } catch (Exception e) {
                            //Console.WriteLine($"Exception! {e.Message}");
                        }
                    }
                }
            }
        }
        public async Task ImportAllExchangePairs()
        {
            //using (var cntx = Context())
            //{
            //    Currency currency = new Currency
            //    {
            //        Symbol = "BTC"
            //    };
            //    cntx.Currencies.Add(currency);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    Currency currency = new Currency
            //    {
            //        Symbol = "BTC"
            //    };
            //    cntx.Currencies.Add(currency);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    var all = cntx.Currencies.ToList();
            //}

            //using (var cntx = Context())
            //{
            //    Exchange exchange = new Exchange
            //    {
            //        Name = "DSX"
            //    };
            //    cntx.Exchanges.Add(exchange);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    Exchange exchange = new Exchange
            //    {
            //        Name = "ABCC"
            //    };
            //    cntx.Exchanges.Add(exchange);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    ExchangePair exchangePair = new ExchangePair
            //    {
            //        CurrencyFromId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "BTC").Id,
            //        CurrencyToId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "ETH").Id,
            //        ExchangeId = cntx.Exchanges.FirstOrDefault(c => c.Name == "DSX").Id,
            //    };
            //    cntx.Pairs.Add(exchangePair);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    ExchangePair exchangePair = new ExchangePair
            //    {
            //        CurrencyFromId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "BTC").Id,
            //        CurrencyToId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "ETH").Id,
            //        ExchangeId = cntx.Exchanges.FirstOrDefault(c => c.Name == "ABCC").Id,
            //    };
            //    cntx.Pairs.Add(exchangePair);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    ExchangePair exchangePair = new ExchangePair
            //    {
            //        CurrencyFromId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "ETH").Id,
            //        CurrencyToId = cntx.Currencies.FirstOrDefault(c => c.Symbol == "BTC").Id,
            //        ExchangeId = cntx.Exchanges.FirstOrDefault(c => c.Name == "ABCC").Id,
            //    };
            //    cntx.Pairs.Add(exchangePair);
            //    cntx.SaveChanges();
            //}

            //using (var cntx = Context())
            //{
            //    var pairs = cntx.Pairs
            //        .Include(x => x.CurrencyFrom)
            //        .Include(x => x.CurrencyTo)
            //        .Include(x => x.Exchange)
            //        .ToList();
            //}

            await ImportAllCurrencies();
            await ImportAllExchanges();

            await _coldImportTests.ImportAllExchangePairs();

            CoreDBContext context = Context();
            ExchangePair  pair    = await context.Pairs
                                    .Include(x => x.CurrencyFrom)
                                    .Include(x => x.CurrencyTo)
                                    .Include(x => x.Exchange)
                                    .FirstOrDefaultAsync(x => x.Exchange.Name == "DSX");

            Assert.NotNull(pair);
            Assert.NotNull(pair.Exchange);
            Assert.NotNull(pair.CurrencyFrom);
            Assert.NotNull(pair.CurrencyTo);
            Assert.Equal("DSX", pair.Exchange.Name);
        }
        public async Task ImportAllMinutePairCandles(string from, string to, string exchange)
        {
            using (var cntx = Context())
            {
                Currency currency = new Currency
                {
                    Symbol = from
                };
                cntx.Currencies.Add(currency);
                cntx.SaveChanges();
            }

            using (var cntx = Context())
            {
                Currency currency = new Currency
                {
                    Symbol = to
                };
                cntx.Currencies.Add(currency);
                cntx.SaveChanges();
            }

            using (var cntx = Context())
            {
                Exchange ex = new Exchange
                {
                    Name = exchange
                };
                cntx.Exchanges.Add(ex);
                cntx.SaveChanges();
            }

            using (var cntx = Context())
            {
                ExchangePair exchangePair = new ExchangePair
                {
                    CurrencyFromId = cntx.Currencies.FirstOrDefault(c => c.Symbol == from).Id,
                    CurrencyToId   = cntx.Currencies.FirstOrDefault(c => c.Symbol == to).Id,
                    ExchangeId     = cntx.Exchanges.FirstOrDefault(c => c.Name == exchange).Id,
                };
                cntx.Pairs.Add(exchangePair);
                cntx.SaveChanges();
            }

            Parallel.For(0, 1000, async(i) =>
            {
                await _coldImportTests.ImportAllMinutePairCandles(from, to, exchange);
            });

            var  context = Context();
            bool isAll60 = await context.Candles.AllAsync(x => x.Interval == 60);

            bool isAllMatch = await context.Candles
                              .Include(x => x.ExchangePair)
                              .AllAsync(x => x.ExchangePair.CurrencyFrom.Symbol == from &&
                                        x.ExchangePair.CurrencyFrom.Symbol == to &&
                                        x.ExchangePair.Exchange.Name == exchange);

            Assert.True(isAll60);
            Assert.True(isAllMatch);
        }
Example #13
0
        public async Task ImportAllMinutePairCandles_Old(string fromSymbol, string toSymbol, string exchange)
        {
            if (string.IsNullOrEmpty(fromSymbol) == false && string.IsNullOrEmpty(toSymbol) == false && string.IsNullOrEmpty(exchange) == false)
            {
                ExchangePair pair = await _coreDBContext.Pairs
                                    .FirstOrDefaultAsync(x =>
                                                         x.CurrencyTo.Symbol == toSymbol &&
                                                         x.CurrencyFrom.Symbol == fromSymbol &&
                                                         x.Exchange.Name == exchange);


                bool isActive = true;

                if (pair != null)
                {
                    int           currentRequestNumber = 0;
                    int           maxRequestNumber     = 10000;
                    long          currentTimestamp     = DateTime.Now.ToUnixTimeStamp();
                    List <Candle> candles = new List <Candle>(2000);

                    while (isActive && currentRequestNumber < maxRequestNumber)
                    {
                        long interval = 60;
                        //var result = await _cryptoCompareGateway.MinuteCandle(fromSymbol, toSymbol, exchange, currentTimestamp, 3);
                        var command = new HistoricalCandleCommand
                        {
                            FromSymbol      = fromSymbol,
                            ToSymbol        = toSymbol,
                            Exchange        = exchange,
                            BeforeTimestamp = currentTimestamp,
                            Limit           = 3,
                            Period          = AlphaVantageHistoricalPeriod.OneMinute
                        };

                        var result = await _cryptoCompareGateway.HistoricalCandle(command);


                        if (result?.IsSuccess == true)
                        {
                            List <CandleDTO> candleDTOs = result?.Content;
                            currentRequestNumber++;
                            candles.Clear();

                            if (candleDTOs?.Count > 0)
                            {
                                if (currentRequestNumber > 1)
                                {
                                    candleDTOs = candleDTOs.Take(candleDTOs.Count - 1).ToList();
                                }
                                foreach (var candleDTO in candleDTOs)
                                {
                                    Candle candle = _mapper.Map <Candle>(candleDTO);
                                    candle.ExchangePairId = pair.Id;
                                    candle.TimeClose      = candle.TimeOpen + interval;
                                    candle.Interval       = interval;

                                    candles.Add(candle);
                                }

                                currentTimestamp = candleDTOs.First().Time;

                                try
                                {
                                    var dif = _coreDBContext.Candles
                                              .Include(x => x.ExchangePair)
                                              .AsEnumerable()
                                              .Where(c => c.ExchangePairId == pair.Id && candles.Any(x => x.TimeOpen == c.TimeOpen && x.TimeClose == c.TimeClose))
                                              .ToList();

                                    await _coreDBContext.AddRangeAsync(candles);

                                    await _coreDBContext.SaveChangesAsync();

                                    _logger.Information($"Load {candles.Count} candles for {fromSymbol}-{toSymbol} from {exchange}");
                                }
                                catch (DbUpdateException ex)
                                {
                                    _logger.Error(ex.GetBaseException(), ex?.InnerException?.Message ?? ex.Message);
                                }
                                catch (InvalidOperationException ex)
                                {
                                    var dif = _coreDBContext.Candles
                                              .Include(x => x.ExchangePair)
                                              .AsEnumerable()
                                              .Where(c => c.ExchangePairId == pair.Id && candles.Any(x => x.TimeOpen == c.TimeOpen && x.TimeClose == c.TimeClose))
                                              .ToList();
                                    //var c = candles.GroupBy(x => new { x.TimeOpen, x.TimeClose, x.PairId }).ToArray().Count();
                                    _logger.Error(ex, "");
                                }
                                catch (Exception ex)
                                {
                                    //var c = candles.GroupBy(x => new { x.TimeOpen, x.TimeClose, x.PairId }).ToArray().Count();
                                    _logger.Error(ex, "");
                                }
                            }
                            else
                            {
                                isActive = false;
                            }
                        }
                    }
                }
                else
                {
                    //пара отсутствует на бирже
                }
            }
        }