public void StartProcess(string exchangeCurrentlyHoldingFunds, string primaryCoin, decimal investment)
        {
            _exchangeCurrentlyHoldingFunds = exchangeCurrentlyHoldingFunds;
            _primaryCoin = primaryCoin;
            _investment  = investment;

            ExchangePairParam param = null;

            _mainTimer = new Timer((object o) =>
            {
                if (!_initializing && !_initialized)
                {
                    _initializing = true;
                    param         = Initialize();
                }
                if (_initialized && !_moving && !_moved)
                {
                    _moving = true;
                    MoveAssetsToOptimalExchange(param);
                }
                if (_initialized && _moved && !_running)
                {
                    _running = true;
                    Trade(param);
                }
            }, null, 0, 1000 * 60 * 5);
            while (true)
            {
                Task.Delay(1000 * 60).Wait();
            }
        }
        public ExchangePairParam Initialize()
        {
            try
            {
                Console.Write($"Getting top volume coins for {_primaryCoin}...");
                _eligibleSymbols = _cryptoCompareDataService.GetTopVolumeSymbols(_primaryCoin).ToList();
                _eligibleSymbols = _eligibleSymbols.Where(m => m != "BTG" && m != "HSR").ToList();
                Console.WriteLine("Done.");
                //_exchanges = _cryptoCompareDataService.GetTopExchangesForPair(_primaryCoin, _valueCoin);
                //_cryptoCompareDataService.GetExchangeCoins(_primaryCoin, _valueCoin, _exchanges, _eligibleSymbols);
                //TEMP use
                //_exchanges = _cryptoCompareDataService.GetAllExchanges();
                //_cryptoCompareDataService.GetExchangeCoins(_primaryCoin, null, _exchanges, _eligibleSymbols);

                Console.Write("Loading API config file...");
                _exchanges = _configService.GetConfiguredExchanges();
                Console.WriteLine("Done.");

                Console.Write("Getting coins for exchanges...");
                _exchanges.ForEach(exchange => { _apiServiceFactory.Create(exchange).GetProducts(exchange, _eligibleSymbols); });
                Console.WriteLine("Done.");

                _exchanges.ForEach(exchange =>
                {
                    var fees = _apiServiceFactory.Create(exchange).GetWithdrawalFees();
                    exchange.Coins.ForEach(coin =>
                    {
                        if (!fees.Any(m => m.Symbol == coin.Symbol))
                        {
                            Colorful.Console.WriteLine($"Missing withdawal fee for {coin.Symbol} on {exchange.Name}. Average will be used.", Color.Red);
                        }
                    });
                });

                CleanupDatabase();

                var exchangePairParam = new ExchangePairParam(_primaryCoin, _exchangeCurrentlyHoldingFunds, _eligibleSymbols, _exchanges);
                //var exchangePairParam = new ExchangePairParam(_primaryCoin, _valueCoin, _exchangeCurrentlyHoldingFunds, null, _exchanges);

                StartPricingAndPrimeDataIfNeeded(exchangePairParam);

                LocateAllTradableAssets(exchangePairParam);
                _initialized  = true;
                _initializing = false;
                return(exchangePairParam);
            }
            catch (Exception ex)
            {
                Colorful.Console.WriteLine(ex.Message, Color.Red);
                _initializing = false;
                _initialized  = false;
            }
            return(null);
        }
        //TODO: after finding all tradable assets find optimal starting exchange and move assets there.
        //      figure out the appropriate threshold for direct move vs trackback based on primary coin
        //      price difference, transfer fees, and exchange fees.
        public void MoveAssetsToOptimalExchange(ExchangePairParam exchangePairParam)
        {
            try
            {
                _pricingService.UpdateExchangeCoinPrices(exchangePairParam.Exchanges);
                var tempExchangePairParam = exchangePairParam.DeepClone();
                FindOptimalExchangePair(tempExchangePairParam, true);
                var startingExchange = tempExchangePairParam.LowestExchange;
                if (startingExchange?.Name == null)
                {
                    throw new NoOptimalExchangeException($"An optimal exchange path was not found for {tempExchangePairParam.PrimaryCoin}. Will try again in 5 minutes...");
                }
                if (tempExchangePairParam.ExchangeCurrentlyHoldingFunds != startingExchange.Name)
                {
                    //var bestDirectExchangePairParam = exchangePairParam.DeepClone();
                    //FindBestDirectMove(bestDirectExchangePairParam);
                    //var bestTrackBackExchangePairParam = exchangePairParam.DeepClone();
                    //bestTrackBackExchangePairParam.HighestExchange = bestDirectExchangePairParam.LowestExchange;
                    //bestTrackBackExchangePairParam.LowestExchange = startingExchange;
                    //FindBestTrackbackMove(bestTrackBackExchangePairParam);

                    //string verbage;
                    //if (bestDirectExchangePairParam.TotalPercentDiff <= bestTrackBackExchangePairParam.TotalPercentDiff)
                    //{
                    //    verbage = $"as a direct transfer on {exchangePairParam.PrimaryCoin}";
                    //}
                    //else
                    //{
                    //    verbage = $"as a trackback with {bestTrackBackExchangePairParam.TrackbackFromCoin.Symbol}";
                    //}

                    //Console.Write($"For optimal trading, assets are being moved from {tempExchangePairParam.ExchangeCurrentlyHoldingFunds} to {startingExchange.Name} {verbage}...");

                    Console.Write($"For optimal trading, assets are being moved from {tempExchangePairParam.ExchangeCurrentlyHoldingFunds} to {startingExchange.Name}...");

                    exchangePairParam.ExchangeCurrentlyHoldingFunds = startingExchange.Name;
                    Console.WriteLine("Done.");
                }
                else
                {
                    Console.WriteLine($"Assets already in optimal position at {startingExchange.Name}.");
                    //exchangePairParam.ExchangeCurrentlyHoldingFunds = exchangePairParam.ExchangeCurrentlyHoldingFunds;
                }
                _moving = false;
                _moved  = true;
            }
            catch (Exception ex)
            {
                Colorful.Console.WriteLine(ex.Message, Color.Red);
                _moving = false;
                _moved  = false;
            }
        }
        public void StartPricingDataThreads(ExchangePairParam exchangePairParam)
        {
            Console.Write("Getting historical data from exchanges...");
            //var counter = 0;
            foreach (var exchange in exchangePairParam.Exchanges)
            {
                //counter++;
                //foreach (var coin in exchange.Coins.Where(m => !SymbolConstants.FiatCurrency.Contains(m.Symbol) ))
                //{
                //    foreach (var childCoin in coin.Coins.Where(m => !SymbolConstants.FiatCurrency.Contains(m.Symbol)))
                //    {
                //        //Console.WriteLine($"{exchange.Name}_{coin.Symbol}_{childCoin.Symbol}");
                //        //GetPriceHistory(exchange.Name, coin.Symbol, childCoin.Symbol, ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds());
                //    }
                //}

                var apiService   = _exchangeApiServiceFactory.Create(exchange);
                var priceMonitor = apiService.MonitorPrices();
                if (priceMonitor.GetType() != typeof(NullMonitorService) && apiService.PricingApiType == PricingApiType.WebSocket)
                {
                    //var threadName = $"PricingThreadFor{exchange.Name}";
                    //if (DoesThreadExist(threadName) == false)
                    //{
                    //    var thread = new Thread(() => priceMonitor.Monitor());
                    //    thread.IsBackground = true;
                    //    thread.Name = threadName;
                    //    _threads.Add(thread);
                    //    thread.Start();
                    //}
                    priceMonitor.Monitor();
                }
            }

            CheckpricingForRestfulExchanges(exchangePairParam.Exchanges);
            _timer          = new System.Timers.Timer(1000 * 60);
            _timer.Elapsed += (sender, e) => CheckpricingForRestfulExchanges(exchangePairParam.Exchanges);
            _timer.Start();

            //var ccThreadName = $"PricingThreadForCryptoCompare";
            //if (DoesThreadExist(ccThreadName) == false)
            //{
            //    var cryptoThread = new Thread(() => ListenToCryptoCompareTicker(exchangePairParam.Exchanges));
            //cryptoThread.IsBackground = true;
            //cryptoThread.Name = ccThreadName;
            //_threads.Add(cryptoThread);
            //cryptoThread.Start();
            //}


            //ListenToCryptoCompareTicker(exchangePairParam.Exchanges);

            Console.WriteLine("Done.");
        }
 private void StartPricingAndPrimeDataIfNeeded(ExchangePairParam exchangePairParam)
 {
     _pricingService.StartPricingDataThreads(exchangePairParam);
     _pricingService.PrimeWithdrawalFeeList(exchangePairParam.Exchanges);
     if (_needsPriming)
     {
         var primeTimeout = DateTime.Now.AddMinutes(1);
         while (DateTime.Now < primeTimeout)
         {
             Console.Write($"Letting exchange data prime for {(primeTimeout - DateTime.Now):mm\\:ss}\r");
             Task.Delay(1000).Wait();
         }
         _pricingService.PrintPrimingReport(exchangePairParam.Exchanges);
         _needsPriming = false;
     }
 }
        //public void FindBestDirectMove(ExchangePairParam param)
        //{
        //    decimal? holdPrimaryPercentDiff = null;
        //    var currentExchange = param.Exchanges.First(m => m.Name == param.ExchangeCurrentlyHoldingFunds);
        //    var possibleHighestList = param.Exchanges
        //        .Where(m=>m.Name != currentExchange.Name)
        //        .OrderByDescending(m => m.Coins.First(n => n.Symbol == param.PrimaryCoin).Coins.First(n => param.ValueCoin.Contains(n.Symbol)).Price).ToList();
        //    foreach (var possibleHighest in possibleHighestList)
        //    {
        //        foreach (var highestTrackBackCoin in possibleHighest.Coins.Where(m => m.Symbol != param.PrimaryCoin))
        //        {
        //            var lowestTrackBackCoin = currentExchange.Coins.FirstOrDefault(m =>
        //                m.Symbol == highestTrackBackCoin.Symbol &&
        //                m.Coins.Any(n => n.Symbol == param.PrimaryCoin));
        //            if (lowestTrackBackCoin != null &&
        //                lowestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin) &&
        //                highestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin))
        //            {
        //                var primaryFromValue = currentExchange.Coins.First(m => m.Symbol == param.PrimaryCoin).Coins.First(m => param.ValueCoin.Contains(m.Symbol)).Price;
        //                var primaryToValue = possibleHighest.Coins.First(m => m.Symbol == param.PrimaryCoin).Coins.First(m => param.ValueCoin.Contains(m.Symbol)).Price;
        //                var checkPrimaryPercentDiff = _mathService.PercentDiff(primaryFromValue, primaryToValue);

        //                //var trackbackFromValue = highestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Price;
        //                //var trackbackToValue = lowestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Price;
        //                //var checkTrackBackPercentDiff = _mathService.PercentDiff(trackbackFromValue, trackbackToValue);

        //                //var checkTotalPercentDiff = checkPrimaryPercentDiff + checkTrackBackPercentDiff;

        //                if (holdPrimaryPercentDiff == null || checkPrimaryPercentDiff < holdPrimaryPercentDiff.Value)
        //                {
        //                    param.LowestExchange = currentExchange;
        //                    param.HighestExchange = possibleHighest;
        //                    param.PrimaryPercentDiff = checkPrimaryPercentDiff;

        //                    //param.TrackbackToCoin = lowestTrackBackCoin;
        //                    //param.TrackbackFromCoin = highestTrackBackCoin;
        //                    //param.TrackbackPercentDiff = checkTrackBackPercentDiff;

        //                    //param.TotalPercentDiff = checkTotalPercentDiff;
        //                    holdPrimaryPercentDiff = checkPrimaryPercentDiff;
        //                }
        //            }
        //        }
        //    }
        //}

        public void FindBestTrackbackMove(ExchangePairParam param)
        {
            var weight = 0m;

            foreach (var highestTrackBackCoin in param.HighestExchange.Coins.Where(m => m.Symbol != param.PrimaryCoin))
            {
                var lowestTrackBackCoin = param.LowestExchange.Coins.FirstOrDefault(m =>
                                                                                    m.Symbol == highestTrackBackCoin.Symbol &&
                                                                                    m.Coins.Any(n => n.Symbol == param.PrimaryCoin));
                if (lowestTrackBackCoin != null &&
                    lowestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin) &&
                    highestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin))
                {
                    //var primaryFromValue = param.HighestExchange.Coins.First(m => m.Symbol == param.PrimaryCoin).Coins.First(m => m.Symbol == param.ValueCoin).Price;
                    //var primaryToValue = param.LowestExchange.Coins.First(m => m.Symbol == param.PrimaryCoin).Coins.First(m => m.Symbol == param.ValueCoin).Price;
                    //var checkPrimaryPercentDiff = PercentDiff(primaryFromValue, primaryToValue);

                    var trackbackFromValue        = highestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Price;
                    var trackbackToValue          = lowestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Price;
                    var checkTrackBackPercentDiff = _mathService.PercentDiff(trackbackFromValue, trackbackToValue);

                    var checkTotalPercentDiff = param.PrimaryPercentDiff + checkTrackBackPercentDiff;
                    var checkWeight           = _pricingService.CalculateTrackbackWeight(param.HighestExchange.Name, param.LowestExchange.Name, highestTrackBackCoin.Symbol, param.PrimaryCoin, checkTrackBackPercentDiff);

                    if (param.PrimaryPercentDiff < -0.05m &&
                        checkTrackBackPercentDiff < 0.01m &&
                        checkTrackBackPercentDiff > -0.1m &&
                        checkTotalPercentDiff < -0.05m &&
                        ((checkTotalPercentDiff < param.TotalPercentDiff && checkWeight >= weight) || param.TrackbackPercentDiff == 0))
                    {
                        //param.LowestExchange = param.LowestExchange;
                        //param.HighestExchange = param.HighestExchange;
                        //param.PrimaryPercentDiff = checkPrimaryPercentDiff;

                        param.TrackbackToCoin      = lowestTrackBackCoin;
                        param.TrackbackFromCoin    = highestTrackBackCoin;
                        param.TrackbackPercentDiff = checkTrackBackPercentDiff;

                        param.TotalPercentDiff = checkTotalPercentDiff;

                        weight = checkWeight;
                    }
                }
            }
        }
 public void LocateAllTradableAssets(ExchangePairParam param)
 {
     Console.Write("Locating tradable assets...");
     if (string.IsNullOrEmpty(param.ExchangeCurrentlyHoldingFunds))
     {
         var largest = 0m;
         foreach (var exchange in param.Exchanges)
         {
             var amount = _apiServiceFactory.Create(exchange).GetBalances(param.PrimaryCoin);
             if (amount > largest)
             {
                 largest = amount;
                 param.ExchangeCurrentlyHoldingFunds = exchange.Name;
             }
         }
     }
     Console.WriteLine("Done.");
 }
        public void UpdateStatsAfterTrackback(ExchangePairParam param)
        {
            _pricingService.UpdateExchangeCoinPrices(
                param.Exchanges,
                new List <string> {
                param.LowestExchange.Name, param.HighestExchange.Name
            },
                new List <string> {
                param.PrimaryCoin, param.TrackbackFromCoin.Symbol
            });

            param.ExchangeCurrentlyHoldingFunds = param.LowestExchange.Name;
            var trackbackFromValue = param.Exchanges.First(m => m.Name == param.HighestExchange.Name).Coins.First(m => m.Symbol == param.TrackbackFromCoin.Symbol).Coins.First(m => m.Symbol == param.PrimaryCoin).Price;
            var trackbackToValue   = param.Exchanges.First(m => m.Name == param.LowestExchange.Name).Coins.First(m => m.Symbol == param.TrackbackToCoin.Symbol).Coins.First(m => m.Symbol == param.PrimaryCoin).Price;

            param.TrackbackPercentDiff = _mathService.PercentDiff(trackbackFromValue, trackbackToValue);
            if (param.TrackbackPercentDiff != 0)
            {
                param.TotalPercentDiff = param.PrimaryPercentDiff + param.TrackbackPercentDiff;
            }
        }
        public void UpdateStatsAfterDirectMove(ExchangePairParam param)
        {
            _pricingService.UpdateExchangeCoinPrices(
                param.Exchanges,
                new List <string> {
                param.LowestExchange.Name, param.HighestExchange.Name
            },
                null);

            param.ExchangeCurrentlyHoldingFunds = param.HighestExchange.Name;
            //var primaryFromValue = param.Exchanges
            //    .First(m => m.Name == param.LowestExchange.Name).Coins
            //    .First(m => m.Symbol == param.PrimaryCoin).Coins
            //    .First(m => param.ValueCoin.Contains(m.Symbol)).Price;
            //var primaryToValue = param.Exchanges
            //    .First(m => m.Name == param.HighestExchange.Name).Coins
            //    .First(m => m.Symbol == param.PrimaryCoin).Coins
            //    .First(m => param.ValueCoin.Contains(m.Symbol)).Price;
            //param.PrimaryPercentDiff = _mathService.PercentDiff(primaryFromValue, primaryToValue);
            //if (param.TrackbackPercentDiff != 0)
            //{
            //    param.TotalPercentDiff = param.PrimaryPercentDiff + param.TrackbackPercentDiff;
            //}
        }
Exemple #10
0
        public void FindOptimalExchangePair(ExchangePairParam param, bool disregardSittingExchange)
        {
            _pricingService.UpdateExchangeCoinPrices(param.Exchanges);

            //var possibleLowestList = param.Exchanges.OrderBy(m => m.Coins.FirstOrDefault(n => n.Symbol == param.PrimaryCoin)?.Coins.FirstOrDefault(n => param.ValueCoin.Contains(n.Symbol))?.Price ?? 99999999999).ToList();
            var possibleLowestList = param.Exchanges.OrderBy(m => m.Name).ToList();

            if (disregardSittingExchange == false)
            {
                MoveAssetsToOptimalExchange(param);
                //var cloneParam = param.DeepClone();
                //FindOptimalExchangePair(cloneParam, true);
                possibleLowestList = possibleLowestList.Where(m => m.Name == param.ExchangeCurrentlyHoldingFunds).ToList();
                //if (cloneParam.LowestExchange.Name != param.ExchangeCurrentlyHoldingFunds)
                //{
                //    Colorful.Console.WriteLine($"Transfering from {cloneParam.LowestExchange.Name} to {cloneParam.HighestExchange.Name} on {cloneParam.TrackbackToCoin.Symbol} at {_mathService.FormatPercent(cloneParam.TrackbackPercentDiff)} is the optimal route at this time but your funds are at {param.ExchangeCurrentlyHoldingFunds}. Think about restarting to funds can be routed to the optimal exchange.", Color.Yellow);
                //    //Colorful.Console.WriteLine($"Transfering from {cloneParam.LowestExchange.Name} to {cloneParam.HighestExchange.Name} on {cloneParam.TrackbackToCoin.Symbol} at {_mathService.FormatPercent(cloneParam.TrackbackPercentDiff)} is the optimal route at this time but your funds are at {param.ExchangeCurrentlyHoldingFunds}. Moving funds to {cloneParam.LowestExchange.Name}.", Color.Yellow);
                //}
            }

            var pricingChecks       = new List <PriceCheckDto>();
            var possibleHighestList = param.Exchanges.OrderByDescending(m => m.Name).ToList();

            foreach (var possibleLowest in possibleLowestList)
            {
                foreach (var possibleHighest in possibleHighestList.Where(m => m.Name != possibleLowest.Name))
                {
                    foreach (var highestTrackBackCoin in possibleHighest.Coins.Where(m => m.Symbol != param.PrimaryCoin))
                    {
                        var lowestTrackBackCoin = possibleLowest.Coins.FirstOrDefault(m =>
                                                                                      m.Symbol == highestTrackBackCoin.Symbol &&
                                                                                      m.Coins.Any(n => n.Symbol == param.PrimaryCoin));
                        if (lowestTrackBackCoin != null &&
                            lowestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin && m.Ask != 0 && m.Bid != 0) &&
                            highestTrackBackCoin.Coins.Any(m => m.Symbol == param.PrimaryCoin && m.Ask != 0 && m.Bid != 0))
                        {
                            var trackbackFromValue   = lowestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Ask;
                            var trackbackToValue     = highestTrackBackCoin.Coins.First(m => m.Symbol == param.PrimaryCoin).Bid;
                            var trackBackPercentDiff = _mathService.PercentDiff(trackbackFromValue, trackbackToValue);
                            var primaryFromValue     = possibleLowest.Coins.FirstOrDefault(m => m.Symbol == highestTrackBackCoin.Symbol)?.Coins?.FirstOrDefault(m => m.Symbol == param.PrimaryCoin)?.Bid ?? decimal.MaxValue;
                            var primaryToValue       = possibleHighest.Coins.FirstOrDefault(m => m.Symbol == highestTrackBackCoin.Symbol)?.Coins?.FirstOrDefault(m => m.Symbol == param.PrimaryCoin)?.Ask ?? decimal.MaxValue;
                            var primaryPercentDiff   = _mathService.PercentDiff(primaryFromValue, primaryToValue);
                            var totalPercentDiff     = primaryPercentDiff + trackBackPercentDiff;

                            var priceCheckDto = new PriceCheckDto
                            {
                                TrackbackFromValue   = trackbackFromValue,
                                TrackbackToValue     = trackbackToValue,
                                TrackBackPercentDiff = trackBackPercentDiff,
                                PrimaryFromValue     = primaryFromValue,
                                PrimaryToValue       = primaryToValue,
                                PrimaryPercentDiff   = primaryPercentDiff,
                                TotalPercentDiff     = totalPercentDiff,
                                PossibleLowest       = possibleLowest,
                                PossibleHighest      = possibleHighest,
                                LowestTrackBackCoin  = lowestTrackBackCoin,
                                HighestTrackBackCoin = highestTrackBackCoin,
                            };
                            pricingChecks.Add(priceCheckDto);
                        }
                    }
                }
            }

            //decimal initialCoinAmount = _investment;
            //decimal buyTrackbackTakerFee = _apiServiceFactory.Create(exchangePairParam.LowestExchange).TakerFee;
            //decimal initialCoinAmountMinusTakerFee = initialCoinAmount - buyTrackbackTakerFee;
            //decimal purchasedTrackbackAmount = initialCoinAmountMinusTakerFee / exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Price;
            //decimal firstNetworkTransferFee = PricingService.Instance.GetWithdrawalFeesForExchangeAndSymbol(exchangePairParam.LowestExchange, exchangePairParam.TrackbackFromCoin.Symbol);
            //decimal purchasedTrackbackAmountMinusTransferFee = purchasedTrackbackAmount - firstNetworkTransferFee;
            //decimal buyPrimaryTakerFee = _apiServiceFactory.Create(exchangePairParam.HighestExchange).TakerFee;
            //decimal trackBackAmountMinusTakerFee = purchasedTrackbackAmountMinusTransferFee - buyPrimaryTakerFee;
            //decimal purchasePrimaryAmount = trackBackAmountMinusTakerFee * exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Price;

            //primaryFromValue != decimal.MaxValue && primaryToValue != decimal.MaxValue

            var orderedPriceChecks = pricingChecks
                                     .Where(m =>
                                            m.PrimaryFromValue != decimal.MaxValue &&
                                            m.PrimaryToValue != decimal.MaxValue)
                                     .OrderByDescending(m => m.TrackBackPercentDiff)
                                     //.ThenByDescending(m => m.TrackBackPercentDiff)
                                     .ToList();

            var filteredPriceChecks = orderedPriceChecks
                                      .Where(m =>
                                             m.TrackBackPercentDiff <0.15m &&
                                                                     m.TrackBackPercentDiff> 0.01m &&
                                             m.TrackbackFromValue <m.TrackbackToValue &&
                                                                   m.TrackbackFromValue> 0.0005m) //TODO: check for available volume here.
                                                                                                  //.OrderBy(m => m.TrackBackPercentDiff)
                                      .ToList();

            var bestPriceCheck = filteredPriceChecks.FirstOrDefault();

            //if (//checkPrimaryPercentDiff < 0.00m &&
            //    checkTrackBackPercentDiff < -0.015m &&
            //    checkTrackBackPercentDiff > -0.10m &&
            //    //checkTotalPercentDiff < -0.05m &&
            //    (checkTrackBackPercentDiff < param.TrackbackPercentDiff || param.TrackbackPercentDiff == 0))
            if (bestPriceCheck != null)
            {
                param.LowestExchange       = bestPriceCheck.PossibleLowest;
                param.HighestExchange      = bestPriceCheck.PossibleHighest;
                param.PrimaryPercentDiff   = bestPriceCheck.PrimaryPercentDiff;
                param.TrackbackFromCoin    = bestPriceCheck.LowestTrackBackCoin;
                param.TrackbackToCoin      = bestPriceCheck.HighestTrackBackCoin;
                param.TrackbackPercentDiff = bestPriceCheck.TrackBackPercentDiff;
                param.TotalPercentDiff     = bestPriceCheck.TotalPercentDiff;
                param.Profitable           = true;
            }
            else
            {
                param.Profitable = false;
                //if (disregardSittingExchange)
                //{
                //    var infoRecord = orderedPriceChecks.First();
                //    Colorful.Console.WriteLine($@"Currently the best option is buying {infoRecord.LowestTrackBackCoin.Symbol} from {infoRecord.PossibleLowest.Name} for {infoRecord.LowestTrackBackCoin.Coins.First(m => m.Symbol == _primaryCoin).Ask} then selling at {infoRecord.PossibleHighest.Name} for {infoRecord.HighestTrackBackCoin.Coins.First(m => m.Symbol == _primaryCoin).Bid} at {_mathService.FormatPercent(infoRecord.TrackBackPercentDiff)}", Color.Yellow);
                //}
            }
        }
Exemple #11
0
        public void Trade(ExchangePairParam exchangePairParam)
        {
            try
            {
                var iteration = 1;
                while (true)
                {
                    Colorful.Console.WriteLine("---------------------------------------------------------------", Color.White);
                    Colorful.Console.WriteLine($"Investing {_investment} on iteration {iteration}...", Color.White);
                    FindOptimalExchangePair(exchangePairParam, false);
                    if (exchangePairParam.LowestExchange == null ||
                        exchangePairParam.HighestExchange == null ||
                        exchangePairParam.Profitable == false)
                    {
                        //Console.WriteLine($"An optimal exchange path was not found for {_primaryCoin}. Will try again in 1 minute.");
                        //Task.Delay(1000 * 60 * 1).Wait();
                        //continue;
                        throw new Exception($"An optimal exchange path was not found for {_primaryCoin}. Will try again.");
                    }

                    var line1 = $"Buying {exchangePairParam.TrackbackFromCoin.Symbol} from {exchangePairParam.LowestExchange.Name} for {exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Ask} then selling at {exchangePairParam.HighestExchange.Name} for {exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Bid} at {_mathService.FormatPercent(exchangePairParam.TrackbackPercentDiff)}";
                    Colorful.Console.WriteLine(line1, Color.White);

                    decimal initialCoinAmount                        = _investment;
                    decimal buyTrackbackTakerFee                     = _apiServiceFactory.Create(exchangePairParam.LowestExchange).TakerFee;
                    decimal initialCoinAmountMinusTakerFee           = initialCoinAmount - buyTrackbackTakerFee;
                    decimal purchasedTrackbackAmount                 = initialCoinAmountMinusTakerFee / exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Ask;
                    decimal firstNetworkTransferFee                  = _pricingService.GetWithdrawalFeesForExchangeAndSymbol(exchangePairParam.LowestExchange, exchangePairParam.TrackbackFromCoin.Symbol);
                    decimal purchasedTrackbackAmountMinusTransferFee = purchasedTrackbackAmount - firstNetworkTransferFee;
                    decimal buyPrimaryTakerFee                       = _apiServiceFactory.Create(exchangePairParam.HighestExchange).TakerFee;
                    decimal trackBackAmountMinusTakerFee             = purchasedTrackbackAmountMinusTransferFee - buyPrimaryTakerFee;
                    decimal purchasePrimaryAmount                    = trackBackAmountMinusTakerFee * exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Bid;
                    decimal secondNetworkTransferFee                 = _pricingService.GetWithdrawalFeesForExchangeAndSymbol(exchangePairParam.HighestExchange, _primaryCoin);
                    decimal purchasePrimaryAmountMinusTransferFee    = purchasePrimaryAmount - secondNetworkTransferFee;
                    decimal resultingCoinAmount                      = purchasePrimaryAmountMinusTransferFee;

                    var line2 = $"\t{initialCoinAmountMinusTakerFee} {_primaryCoin} converted to {purchasedTrackbackAmount} {exchangePairParam.TrackbackFromCoin.Symbol} for {buyTrackbackTakerFee} fee.";
                    var line3 = $"\tTransfering {purchasedTrackbackAmountMinusTransferFee} {exchangePairParam.TrackbackFromCoin.Symbol} to {exchangePairParam.HighestExchange.Name} for a {firstNetworkTransferFee} fee";
                    var line4 = $"\t{trackBackAmountMinusTakerFee} {exchangePairParam.TrackbackFromCoin.Symbol} converted back to {purchasePrimaryAmount} {_primaryCoin} for {buyPrimaryTakerFee} fee.";
                    var line5 = $"\tTransfering {purchasePrimaryAmountMinusTransferFee} {_primaryCoin} back to {exchangePairParam.LowestExchange.Name} for a {secondNetworkTransferFee} fee.";
                    var line6 = $"\tEnding Balance: {resultingCoinAmount} {_primaryCoin}";
                    Colorful.Console.WriteLine(line2, Color.White);
                    Colorful.Console.WriteLine(line3, Color.White);
                    Colorful.Console.WriteLine(line4, Color.White);
                    Colorful.Console.WriteLine(line5, Color.White);
                    Colorful.Console.WriteLine(line6, (resultingCoinAmount > initialCoinAmount) ? Color.White : Color.Red);
                    Colorful.Console.WriteLine($"\tWaiting for next cycle.", Color.White);
                    _investment = resultingCoinAmount;

                    //if (resultingCoinAmount > initialCoinAmount)
                    //{
                    //    _emailService.Send($"{line1}{line2}{line3}{line4}{line5}{line6}");
                    //}

                    //Console.WriteLine($"Projected gain from buying {exchangePairParam.TrackbackFromCoin.Symbol} from {exchangePairParam.LowestExchange.Name} ({exchangePairParam.LowestExchange.Coins.First(m => m.Symbol == _primaryCoin).Coins.First(m => _valueCoin.Contains(m.Symbol)).Price}) to {exchangePairParam.HighestExchange.Name} ({exchangePairParam.HighestExchange.Coins.First(m => m.Symbol == _primaryCoin).Coins.First(m => _valueCoin.Contains(m.Symbol)).Price}) is {decimal.Round(exchangePairParam.PrimaryPercentDiff * -100, 2, MidpointRounding.ToEven)}%");
                    //Console.Write($"Waiting on transfer if {exchangePairParam.PrimaryCoin} from {exchangePairParam.LowestExchange.Name} to {exchangePairParam.HighestExchange.Name}...");
                    ////Thread.Sleep(1000 * 60 * 55);
                    //Thread.Sleep(1000 * 60);
                    //Console.WriteLine("Done.");

                    ////Console.WriteLine("Press any key to continue.");
                    ////Console.ReadKey();

                    //UpdateStatsAfterDirectMove(exchangePairParam);
                    //Console.WriteLine($"Actual gain {exchangePairParam.LowestExchange.Coins.First(m => m.Symbol == _primaryCoin).Coins.First(m => _valueCoin.Contains(m.Symbol)).Price} --> {exchangePairParam.HighestExchange.Coins.First(m => m.Symbol == _primaryCoin).Coins.First(m => _valueCoin.Contains(m.Symbol)).Price} = {decimal.Round(exchangePairParam.PrimaryPercentDiff * -100, 2, MidpointRounding.ToEven)}%");

                    //decimal differenceAfterTransferToHigh = initalCoinPurchaseMinusFee * (exchangePairParam.PrimaryPercentDiff * -1);
                    //decimal valueAfterTransferToHigh = initalCoinPurchaseMinusFee + differenceAfterTransferToHigh;

                    //FindBestTrackbackMove(exchangePairParam);
                    //Console.WriteLine($"Projected gain from tracking back {exchangePairParam.TrackbackFromCoin.Symbol} from {exchangePairParam.HighestExchange.Name} ({exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Price}) to {exchangePairParam.LowestExchange.Name} ({exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Price}) is {decimal.Round(exchangePairParam.TrackbackPercentDiff * -100, 2, MidpointRounding.ToEven)}%");
                    //decimal convertionToTrackback = valueAfterTransferToHigh / exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Price;
                    //decimal firstTakerFee = convertionToTrackback * PricingService.Instance.GetTakerFeeForExchange(exchangePairParam.HighestExchange);
                    //decimal secondNetworkTransferFee = PricingService.Instance.GetWithdrawalFeesForExchangeAndSymbol(exchangePairParam.HighestExchange, exchangePairParam.TrackbackFromCoin.Symbol);
                    //decimal trackbackSansFees = convertionToTrackback - firstTakerFee - secondNetworkTransferFee;

                    //Console.Write($"Waiting on transfer if {exchangePairParam.TrackbackFromCoin.Symbol} --> {exchangePairParam.HighestExchange.Name} to {exchangePairParam.LowestExchange.Name}...");
                    ////Thread.Sleep(1000 * 60 * 20);
                    //Thread.Sleep(1000 * 60);
                    //Console.WriteLine("Done.");

                    ////Console.WriteLine("Press any key to continue.");
                    ////Console.ReadKey();

                    //UpdateStatsAfterTrackback(exchangePairParam);
                    //Console.WriteLine($"Actual gain {exchangePairParam.TrackbackFromCoin.Coins.First(m => m.Symbol == _primaryCoin).Price} --> {exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Price} = {decimal.Round(exchangePairParam.TrackbackPercentDiff * -100, 2, MidpointRounding.ToEven)}%");

                    //decimal differenceAfterTransferToLow = trackbackSansFees * (-1 * exchangePairParam.TrackbackPercentDiff);
                    //decimal valueAfterTransferToLow = trackbackSansFees + differenceAfterTransferToLow;
                    //decimal convertionToPrimary = valueAfterTransferToLow * exchangePairParam.TrackbackToCoin.Coins.First(m => m.Symbol == _primaryCoin).Price;
                    //decimal secondTakerFee = convertionToPrimary * PricingService.Instance.GetTakerFeeForExchange(exchangePairParam.LowestExchange);
                    //decimal primaryFinalSansFees = convertionToPrimary - secondTakerFee;
                    //decimal gainsAfterRoundTrip = primaryFinalSansFees - initialCoinAmount;
                    //decimal usdGains = gainsAfterRoundTrip * exchangePairParam.LowestExchange.Coins.First(m => m.Symbol == _primaryCoin).Coins.First(m => m.Symbol == SymbolConstants.Usd || m.Symbol == SymbolConstants.Usdt).Price;
                    //decimal usdTotal = _investment + usdGains;

                    //_investment = decimal.Round(usdTotal, 2, MidpointRounding.ToEven);
                    //Console.WriteLine($"Investment grew {decimal.Round(gainsAfterRoundTrip / initialCoinAmount * 100, 2, MidpointRounding.ToEven)}% to ${_investment}!");
                    Task.Delay(1000 * 60 * 15).Wait();
                    iteration++;

                    //Console.WriteLine("Press any key to continue.");
                    //Console.ReadKey();
                }
            }
            catch (Exception ex)
            {
                Colorful.Console.WriteLine(ex.Message, Color.Red);
                _running = false;
                //Task.Delay(1000 * 60 * 5).Wait();
                //Trade();
            }
        }