Esempio n. 1
0
        internal static Profit GetPoolProfitForCoin(Coin coin, Dictionary <ProfitProvider, Dictionary <string, Profit> > poolProfitsDictionary, Settings settings)
        {
            Profit profit = new Profit();
            List <ProfitProvider> orderedProfitProviders = GetPoolProfitProviders(settings, coin);
            var profitSwitchingStrategy = ProfitSwitchingStrategyFactory.GetProfitSwitchingStrategy(settings.ProfitSwitchingStrategy);

            while (profitSwitchingStrategy.GetReward(profit, coin, settings.ProfitTimeframe) == 0 && orderedProfitProviders.Count > 0)
            {
                ProfitProvider profitProvider = orderedProfitProviders[0];
                var            poolProfits    = poolProfitsDictionary.GetValueOrDefault(profitProvider, null);
                if (poolProfits != null)
                {
                    profit = poolProfits.GetValueOrDefault(coin.TickerSymbol, new Profit());
                }
                orderedProfitProviders.RemoveAt(0);
            }
            return(profit);
        }
Esempio n. 2
0
        private static Task ProfitSwitcherTaskAsync(string appFolderPath, DirectoryInfo appRootFolder, Settings settings, List <Coin> coins, List <NicehashAlgorithm> nicehashAlgorithms, CancellationToken token)
        {
            return(Task.Run(() =>
            {
                //Get pool profit data
                while (!token.IsCancellationRequested)
                {
                    var statusCts = new CancellationTokenSource();
                    var watchdogCts = new CancellationTokenSource();

                    try
                    {
                        ResetConsole();

                        // Get pool mined coins profitability

                        var timeoutCts = new CancellationTokenSource(60000);
                        var childCts = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCts.Token);

                        var profitProviders = Helpers.GetPoolProfitProviders(settings, null);
                        foreach (var coin in coins.Where(c => !String.IsNullOrEmpty(c.OverridePoolProfitProviders)))
                        {
                            foreach (var profitProviderString in coin.OverridePoolProfitProviders.Split(","))
                            {
                                ProfitProvider profitProvider;
                                if (Enum.TryParse(profitProviderString, out profitProvider))
                                {
                                    if (!profitProviders.Contains(profitProvider))
                                    {
                                        profitProviders.Add(profitProvider);
                                    }
                                }
                            }
                        }
                        var poolProfitsDictionaryUnordered = new Dictionary <ProfitProvider, Dictionary <string, Profit> >();
                        var profitProviderTasks = new List <Task>();
                        foreach (var profitProvider in profitProviders)
                        {
                            if (!poolProfitsDictionaryUnordered.ContainsKey(profitProvider))
                            {
                                profitProviderTasks.Add(Task.Run(() =>
                                {
                                    IPoolProfitProvider profitProviderClass = PoolProfitProviderFactory.GetPoolProfitProvider(profitProvider);
                                    poolProfitsDictionaryUnordered[profitProvider] = profitProviderClass.GetProfits(appRootFolder, settings, coins, childCts.Token);
                                }, childCts.Token));
                            }
                        }
#if DEBUG
                        Stopwatch sw = new Stopwatch();
                        sw.Start();
#endif
                        Task.WhenAll(profitProviderTasks).Wait(childCts.Token);
#if DEBUG
                        sw.Stop();
                        Console.WriteLine($"Fetching profit data took {(int)sw.Elapsed.TotalSeconds} seconds.");
#endif

                        //Reorder because of async
                        var poolProfitsDictionary = new Dictionary <ProfitProvider, Dictionary <string, Profit> >();
                        foreach (var profitProvider in profitProviders)
                        {
                            if (poolProfitsDictionaryUnordered.ContainsKey(profitProvider))
                            {
                                poolProfitsDictionary[profitProvider] = poolProfitsDictionaryUnordered[profitProvider];
                            }
                        }

                        IProfitSwitchingStrategy profitSwitchingStrategy = ProfitSwitchingStrategyFactory.GetProfitSwitchingStrategy(settings.ProfitSwitchingStrategy);

                        MineableReward currentReward = null;

                        // Get best pool mined coin
                        MineableReward bestPoolminedCoin = null;
                        if (!token.IsCancellationRequested)
                        {
                            var result = profitSwitchingStrategy.GetBestPoolminedCoin(coins, _currentMineable, poolProfitsDictionary, settings);
                            bestPoolminedCoin = result?.Result;
                            if (currentReward == null)
                            {
                                currentReward = result?.Current;
                            }
                            if (bestPoolminedCoin?.Mineable != null)
                            {
                                Console.WriteLine("Got best pool mined coin: " + bestPoolminedCoin.Mineable.DisplayName);
                            }
                            else
                            {
                                Console.WriteLine("Couldn't determine best pool mined coin.");
                            }
                        }

                        //Get Nicehash Profit
                        Dictionary <int, Profit> nicehashProfitsDictionary = null;
                        if (!token.IsCancellationRequested)
                        {
                            nicehashProfitsDictionary = NicehashApi.GetProfits(appRootFolder, settings, nicehashAlgorithms, childCts.Token);
                        }

                        //Get best nicehash algorithm
                        MineableReward bestNicehashAlgorithm = null;
                        if (!token.IsCancellationRequested && nicehashProfitsDictionary != null)
                        {
                            var result = profitSwitchingStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms, _currentMineable, nicehashProfitsDictionary, settings);
                            bestNicehashAlgorithm = result?.Result;
                            if (currentReward == null)
                            {
                                currentReward = result?.Current;
                            }
                            if (bestNicehashAlgorithm?.Mineable != null)
                            {
                                Console.WriteLine("Got best nicehash algorithm: " + bestNicehashAlgorithm.Mineable.DisplayName);
                            }
                            else
                            {
                                Console.WriteLine("Couldn't determine best nicehash algorithm.");
                            }
                        }

                        //Sort profit table
                        if (settings.ProfitSorting != SortingMode.None)
                        {
                            var coinProfitComparer = new CoinProfitComparer(settings.ProfitSorting, poolProfitsDictionary);
                            coins.Sort(coinProfitComparer);
                            var nicehashProfitComparer = new NicehashProfitComparer(settings.ProfitSorting, nicehashProfitsDictionary);
                            nicehashAlgorithms.Sort(nicehashProfitComparer);
                        }

                        //Print table
                        if (!token.IsCancellationRequested && nicehashProfitsDictionary != null)
                        {
                            PrintProfitTable(coins, poolProfitsDictionary, nicehashAlgorithms, nicehashProfitsDictionary, settings);
                        }

                        //Mine using best algorithm/coin
                        if (!token.IsCancellationRequested)
                        {
                            Console.WriteLine();
                            Mineable bestOverallMineable = null;
                            if (_manualSelection && _manualSelectedMineable != null)
                            {
                                bestOverallMineable = _manualSelectedMineable;
                            }
                            else
                            {
                                bestOverallMineable = profitSwitchingStrategy.GetBestMineable(bestPoolminedCoin, bestNicehashAlgorithm, currentReward, settings)?.Mineable;
                            }
                            if (bestOverallMineable != null)
                            {
                                Console.WriteLine($"Determined best mining method: {bestOverallMineable.DisplayName}");
                                if (_currentMineable == null || _currentMineable.Id != bestOverallMineable.Id)
                                {
                                    StartMiner(bestOverallMineable, settings, appFolderPath, appRootFolder);
                                }
                            }
                            else
                            {
                                Log.Information("Couldn't determine best mining method.");
                            }
                        }

                        var statusUpdaterTask = StatusUpdaterTaskAsync(DateTimeOffset.Now.AddSeconds(settings.ProfitCheckInterval), settings, appRootFolder, coins, poolProfitsDictionary, nicehashAlgorithms, nicehashProfitsDictionary, statusCts.Token);

                        if (!token.IsCancellationRequested)
                        {
                            if (settings.ProfitCheckInterval > 0)
                            {
                                Task.Delay(TimeSpan.FromSeconds(settings.ProfitCheckInterval), token).Wait(token);
                            }
                            else
                            {
                                token.WaitHandle.WaitOne();
                            }
                        }

                        statusCts.Cancel();
                    }
                    catch (TaskCanceledException)
                    {
                        Log.Information("Cancelled profit task.");
                        statusCts.Cancel();
                    }
                    catch (AggregateException)
                    {
                        Log.Information("Cancelled profit task 2.");
                        statusCts.Cancel();
                    }
                    catch (OperationCanceledException)
                    {
                        Log.Information("Cancelled profit task 3.");
                        statusCts.Cancel();
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Profit switcher task failed: " + ex);
                        statusCts.Cancel();
                    }
                }
            }, token));
        }
        private static void CheckSwitching()
        {
            try
            {
                WriteInfo(" Check switching..");
                IProfitSwitchingStrategy profitSwitchingStrategy = ProfitSwitchingStrategyFactory.GetProfitSwitchingStrategy(_profitSwitchingStrategy ?? ProfitSwitchingStrategy.MaximizeFiat);
                // Find optimal configs
                Dictionary <string, MiningConfig> optimalMiningConfigs = new Dictionary <string, MiningConfig>();
                if (_manualMode)
                {
                    foreach (var manualMininigConfig in _manualMininigConfigs)
                    {
                        MiningConfig miningConfig = new MiningConfig(manualMininigConfig.Value.DeviceConfig, manualMininigConfig.Value.Pool);
                        optimalMiningConfigs.Add(manualMininigConfig.Key, miningConfig);
                    }
                }
                else
                {
                    foreach (Algorithm algorithm in Config.Algorithms)
                    {
                        if (algorithm.Enabled)
                        {
                            foreach (DeviceConfig algorithmDeviceConfig in algorithm.DeviceConfigs)
                            {
                                if (algorithmDeviceConfig.Enabled)
                                {
                                    foreach (Pool algorithmPool in algorithm.Pools.Where(p => p.Enabled))
                                    {
                                        Profit?profit = GetAdjustedProfit(algorithmPool, algorithmDeviceConfig.ExpectedHashrate, true);
                                        if (profit.HasValue)
                                        {
                                            if (!optimalMiningConfigs.ContainsKey(algorithmDeviceConfig.FullDeviceId))
                                            {
                                                SetOptimalMiningConfigWithThreshold(profit.Value, profitSwitchingStrategy, algorithmDeviceConfig, algorithmPool, optimalMiningConfigs);
                                            }
                                            else
                                            {
                                                MiningConfig bestMiningConfig = optimalMiningConfigs[algorithmDeviceConfig.FullDeviceId];
                                                Profit?      bestProfit       = GetAdjustedProfit(bestMiningConfig.Pool, bestMiningConfig.DeviceConfig.ExpectedHashrate, true);
                                                if (!bestProfit.HasValue || profitSwitchingStrategy.IsProfitABetterThanB(profit.Value, algorithmPool.ProfitTimeframe, bestProfit.Value, bestMiningConfig.Pool.ProfitTimeframe, 0))
                                                {
                                                    SetOptimalMiningConfigWithThreshold(profit.Value, profitSwitchingStrategy, algorithmDeviceConfig, algorithmPool, optimalMiningConfigs);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Merge miners and get list of optimal miners
                List <IMiner> optimalMiners = new List <IMiner>();
                foreach (var optimalMiningConfigKeyValue in optimalMiningConfigs)
                {
                    MiningConfig miningConfig = optimalMiningConfigKeyValue.Value;
                    IMiner       miner        = MinerFactory.GetMiner(new HashSet <DeviceConfig>()
                    {
                        miningConfig.DeviceConfig
                    }, miningConfig.Pool);
                    IMiner existingMiner = optimalMiners.FirstOrDefault(m => m.Name == miner.Name && m.Pool.Equals(miner.Pool));
                    if (existingMiner != null)
                    {
                        existingMiner.DeviceConfigs.Add(miningConfig.DeviceConfig);
                        miningConfig.Miner = existingMiner;
                    }
                    else
                    {
                        miningConfig.Miner = miner;
                        optimalMiners.Add(miner);
                    }
                }

                bool displayNeedsUpdate = false;
                // Get list of current miners
                List <IMiner> currentMiners = GetCurrentMiners();

                //Check if existing miner will be kept
                foreach (IMiner currentMiner in currentMiners)
                {
                    if (optimalMiners.Any(om => om.Pool.Equals(currentMiner.Pool) && om.DeviceConfigs.SetEquals(currentMiner.DeviceConfigs)))
                    {
                        foreach (DeviceConfig currentMinerDeviceConfig in currentMiner.DeviceConfigs)
                        {
                            optimalMiningConfigs[currentMinerDeviceConfig.FullDeviceId].Miner = currentMiner;
                        }
                    }
                }

                //Check if existing miner has to be closed
                foreach (IMiner currentMiner in currentMiners.ToArray())
                {
                    if (!optimalMiners.Any(om => om.Pool.Equals(currentMiner.Pool) && om.DeviceConfigs.SetEquals(currentMiner.DeviceConfigs)))
                    {
                        displayNeedsUpdate = true;
                        currentMiner.StopMiner();
                        currentMiners.Remove(currentMiner);
                    }
                }

                //Check if new miner has to start
                foreach (IMiner optimalMiner in optimalMiners)
                {
                    if (!currentMiners.Any(cm => cm.Pool.Equals(optimalMiner.Pool) && cm.DeviceConfigs.SetEquals(optimalMiner.DeviceConfigs)))
                    {
                        displayNeedsUpdate = true;
                        foreach (DeviceConfig deviceConfig in optimalMiner.DeviceConfigs)
                        {
                            if (!string.IsNullOrEmpty(deviceConfig.PrepareScript))
                            {
                                Helpers.ExecuteScript(deviceConfig.MinerPath, AppFolderPath);
                            }
                        }
                        Task.Delay(TimeSpan.FromSeconds(Config.MinerStartDelay)).Wait();
                        optimalMiner.StartMiner(Config.StartMinerMinimized);
                    }
                }

                _currentMininigConfigs = optimalMiningConfigs;

                if (displayNeedsUpdate)
                {
                    _displayUpdaterCts?.Cancel();
                }
            }
            catch (Exception e)
            {
                Log.Debug("Check switching failed: " + e);
            }
        }