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); }
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); }
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); }
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 { //пара отсутствует на бирже } } }