private static void SwichMostProfitableGroupUpMethod(object sender, SmaUpdateEventArgs e) { _ = NormalizedProfitsUpdate(e.NormalizedProfits); }
private static async void SwichMostProfitableGroupUpMethod(object sender, SmaUpdateEventArgs e) { await SwichMostProfitableGroupUpMethodTask(sender, e); }
private static async Task SwichMostProfitableGroupUpMethodTask(object sender, SmaUpdateEventArgs e) { CalculateAndUpdateMiningDevicesProfits(e.NormalizedProfits); var(currentProfit, prevStateProfit) = GetCurrentAndPreviousProfits(); // log profits scope { var stringBuilderFull = new StringBuilder(); stringBuilderFull.AppendLine("Current device profits:"); foreach (var device in _miningDevices) { var stringBuilderDevice = new StringBuilder(); stringBuilderDevice.AppendLine($"\tProfits for {device.Device.Uuid} ({device.Device.GetFullName()}):"); foreach (var algo in device.Algorithms) { stringBuilderDevice.AppendLine( $"\t\tPROFIT = {algo.CurrentProfit.ToString(DoubleFormat)}" + $"\t(SPEED = {algo.AvaragedSpeed:e5}" + $"\t\t| NHSMA = {algo.CurNhmSmaDataVal:e5})" + $"\t[{algo.AlgorithmStringID}]" ); if (algo is PluginAlgorithm dualAlg && dualAlg.IsDual) { stringBuilderDevice.AppendLine( $"\t\t\t\t\t Secondary:\t\t {dualAlg.SecondaryAveragedSpeed:e5}" + $"\t\t\t\t {dualAlg.SecondaryCurNhmSmaDataVal:e5}" ); } } // most profitable stringBuilderDevice.AppendLine( $"\t\tMOST PROFITABLE ALGO: {device.GetMostProfitableString()}, PROFIT: {device.GetCurrentMostProfitValue.ToString(DoubleFormat)}"); stringBuilderFull.AppendLine(stringBuilderDevice.ToString()); } Logger.Info(Tag, stringBuilderFull.ToString()); } // check if should mine // Only check if profitable inside this method when getting SMA data, cheching during mining is not reliable if (CheckIfShouldMine(currentProfit) == false) { foreach (var device in _miningDevices) { device.SetNotMining(); } await PauseAllMiners(); return; } // check profit threshold Logger.Info(Tag, $"PrevStateProfit {prevStateProfit}, CurrentProfit {currentProfit}"); if (prevStateProfit > 0 && currentProfit > 0) { var a = Math.Max(prevStateProfit, currentProfit); var b = Math.Min(prevStateProfit, currentProfit); //double percDiff = Math.Abs((PrevStateProfit / CurrentProfit) - 1); var percDiff = ((a - b)) / b; if (percDiff < ConfigManager.GeneralConfig.SwitchProfitabilityThreshold) { // don't switch Logger.Info(Tag, $"Will NOT switch profit diff is {percDiff}, current threshold {ConfigManager.GeneralConfig.SwitchProfitabilityThreshold}"); // RESTORE OLD PROFITS STATE foreach (var device in _miningDevices) { device.RestoreOldProfitsState(); } return; } Logger.Info(Tag, $"Will SWITCH profit diff is {percDiff}, current threshold {ConfigManager.GeneralConfig.SwitchProfitabilityThreshold}"); } await _semaphore.WaitAsync(); var hasChanged = false; try { // group new miners var newGroupedMiningPairs = GroupingUtils.GetGroupedMiningPairs(GetProfitableMiningPairs()); // check newGroupedMiningPairs and running Groups to figure out what to start/stop and keep running var currentRunningGroups = _runningMiners.Keys.ToArray(); // check which groupMiners should be stopped and which ones should be started and which to keep running var noChangeGroupMinersKeys = newGroupedMiningPairs.Where(pair => currentRunningGroups.Contains(pair.Key)).Select(pair => pair.Key).OrderBy(uuid => uuid).ToArray(); var toStartMinerGroupKeys = newGroupedMiningPairs.Where(pair => !currentRunningGroups.Contains(pair.Key)).Select(pair => pair.Key).OrderBy(uuid => uuid).ToArray(); var toStopMinerGroupKeys = currentRunningGroups.Where(runningKey => !newGroupedMiningPairs.Keys.Contains(runningKey)).OrderBy(uuid => uuid).ToArray(); // first stop currently running foreach (var stopKey in toStopMinerGroupKeys) { var stopGroup = _runningMiners[stopKey]; _runningMiners.Remove(stopKey); await stopGroup.StopTask(); stopGroup.End(); } // start new var miningLocation = StratumService.SelectedServiceLocation; foreach (var startKey in toStartMinerGroupKeys) { var miningPairs = newGroupedMiningPairs[startKey]; var toStart = MinerFactory.CreateMinerForMining(miningPairs, startKey); if (toStart == null) { Logger.Error(Tag, $"CreateMinerForMining for key='{startKey}' returned <null>"); continue; } _runningMiners[startKey] = toStart; await toStart.StartTask(miningLocation, _username); } // log scope { var stopLog = toStopMinerGroupKeys.Length > 0 ? string.Join(",", toStopMinerGroupKeys) : "EMTPY"; Logger.Info(Tag, $"Stop Old Mining: ({stopLog})"); var startLog = toStartMinerGroupKeys.Length > 0 ? string.Join(",", toStartMinerGroupKeys) : "EMTPY"; Logger.Info(Tag, $"Start New Mining : ({startLog})"); var sameLog = noChangeGroupMinersKeys.Length > 0 ? string.Join(",", noChangeGroupMinersKeys) : "EMTPY"; Logger.Info(Tag, $"No change : ({sameLog})"); } hasChanged = toStartMinerGroupKeys.Length > 0 || toStopMinerGroupKeys.Length > 0; } finally { _semaphore.Release(); } // There is a change in groups, change GUI if (hasChanged) { ApplicationStateManager.ClearRatesAll(); await MinerStatsCheck(); } }
private void SwichMostProfitableGroupUpMethod(object sender, SmaUpdateEventArgs e) { #if (SWITCH_TESTING) MiningDevice.SetNextTest(); #endif var profitableDevices = new List <MiningPair>(); var currentProfit = 0.0d; var prevStateProfit = 0.0d; foreach (var device in _miningDevices) { // calculate profits device.CalculateProfits(e.NormalizedProfits); // check if device has profitable algo if (device.HasProfitableAlgo()) { profitableDevices.Add(device.GetMostProfitablePair()); currentProfit += device.GetCurrentMostProfitValue; prevStateProfit += device.GetPrevMostProfitValue; } } var stringBuilderFull = new StringBuilder(); stringBuilderFull.AppendLine("Current device profits:"); foreach (var device in _miningDevices) { var stringBuilderDevice = new StringBuilder(); stringBuilderDevice.AppendLine($"\tProfits for {device.Device.Uuid} ({device.Device.GetFullName()}):"); foreach (var algo in device.Algorithms) { stringBuilderDevice.AppendLine( $"\t\tPROFIT = {algo.CurrentProfit.ToString(DoubleFormat)}" + $"\t(SPEED = {algo.AvaragedSpeed:e5}" + $"\t\t| NHSMA = {algo.CurNhmSmaDataVal:e5})" + $"\t[{algo.AlgorithmStringID}]" ); if (algo is DualAlgorithm dualAlg) { stringBuilderDevice.AppendLine( $"\t\t\t\t\t Secondary:\t\t {dualAlg.SecondaryAveragedSpeed:e5}" + $"\t\t\t\t {dualAlg.SecondaryCurNhmSmaDataVal:e5}" ); } } // most profitable stringBuilderDevice.AppendLine( $"\t\tMOST PROFITABLE ALGO: {device.GetMostProfitableString()}, PROFIT: {device.GetCurrentMostProfitValue.ToString(DoubleFormat)}"); stringBuilderFull.AppendLine(stringBuilderDevice.ToString()); } Helpers.ConsolePrint(Tag, stringBuilderFull.ToString()); // check if should mine // Only check if profitable inside this method when getting SMA data, cheching during mining is not reliable if (CheckIfShouldMine(currentProfit) == false) { foreach (var device in _miningDevices) { device.SetNotMining(); } return; } // check profit threshold Helpers.ConsolePrint(Tag, $"PrevStateProfit {prevStateProfit}, CurrentProfit {currentProfit}"); if (prevStateProfit > 0 && currentProfit > 0) { var a = Math.Max(prevStateProfit, currentProfit); var b = Math.Min(prevStateProfit, currentProfit); //double percDiff = Math.Abs((PrevStateProfit / CurrentProfit) - 1); var percDiff = ((a - b)) / b; if (percDiff < ConfigManager.GeneralConfig.SwitchProfitabilityThreshold) { // don't switch Helpers.ConsolePrint(Tag, $"Will NOT switch profit diff is {percDiff}, current threshold {ConfigManager.GeneralConfig.SwitchProfitabilityThreshold}"); // RESTORE OLD PROFITS STATE foreach (var device in _miningDevices) { device.RestoreOldProfitsState(); } return; } Helpers.ConsolePrint(Tag, $"Will SWITCH profit diff is {percDiff}, current threshold {ConfigManager.GeneralConfig.SwitchProfitabilityThreshold}"); } // group new miners var newGroupedMiningPairs = new Dictionary <string, List <MiningPair> >(); // group devices with same supported algorithms { var currentGroupedDevices = new List <GroupedDevices>(); for (var first = 0; first < profitableDevices.Count; ++first) { var firstDev = profitableDevices[first].Device; // check if is in group var isInGroup = currentGroupedDevices.Any(groupedDevices => groupedDevices.Contains(firstDev.Uuid)); // if device is not in any group create new group and check if other device should group if (isInGroup == false) { var newGroup = new GroupedDevices(); var miningPairs = new List <MiningPair>() { profitableDevices[first] }; newGroup.Add(firstDev.Uuid); for (var second = first + 1; second < profitableDevices.Count; ++second) { // check if we should group var firstPair = profitableDevices[first]; var secondPair = profitableDevices[second]; if (GroupingLogic.ShouldGroup(firstPair, secondPair)) { var secondDev = profitableDevices[second].Device; newGroup.Add(secondDev.Uuid); miningPairs.Add(profitableDevices[second]); } } currentGroupedDevices.Add(newGroup); newGroupedMiningPairs[CalcGroupedDevicesKey(newGroup)] = miningPairs; } } } //bool IsMinerStatsCheckUpdate = false; { // check which groupMiners should be stopped and which ones should be started and which to keep running var toStopGroupMiners = new Dictionary <string, GroupMiner>(); var toRunNewGroupMiners = new Dictionary <string, GroupMiner>(); var noChangeGroupMiners = new Dictionary <string, GroupMiner>(); // check what to stop/update foreach (var runningGroupKey in _runningGroupMiners.Keys) { if (newGroupedMiningPairs.ContainsKey(runningGroupKey) == false) { // runningGroupKey not in new group definately needs to be stopped and removed from curently running toStopGroupMiners[runningGroupKey] = _runningGroupMiners[runningGroupKey]; } else { // runningGroupKey is contained but needs to check if mining algorithm is changed var miningPairs = newGroupedMiningPairs[runningGroupKey]; var newAlgoType = GetMinerPairAlgorithmType(miningPairs); if (newAlgoType != AlgorithmType.NONE && newAlgoType != AlgorithmType.INVALID) { // Check if dcri optimal value has changed var dcriChanged = false; foreach (var mPair in _runningGroupMiners[runningGroupKey].Miner.MiningSetup.MiningPairs) { if (mPair.Algorithm is DualAlgorithm algo && algo.TuningEnabled && algo.MostProfitableIntensity != algo.CurrentIntensity) { dcriChanged = true; break; } } // if algoType valid and different from currently running update if (newAlgoType != _runningGroupMiners[runningGroupKey].DualAlgorithmType || dcriChanged) { // remove current one and schedule to stop mining toStopGroupMiners[runningGroupKey] = _runningGroupMiners[runningGroupKey]; // create new one TODO check if DaggerHashimoto GroupMiner newGroupMiner = null; if (newAlgoType == AlgorithmType.DaggerHashimoto) { if (_ethminerNvidiaPaused != null && _ethminerNvidiaPaused.Key == runningGroupKey) { newGroupMiner = _ethminerNvidiaPaused; } if (_ethminerAmdPaused != null && _ethminerAmdPaused.Key == runningGroupKey) { newGroupMiner = _ethminerAmdPaused; } } if (newGroupMiner == null) { newGroupMiner = new GroupMiner(miningPairs, runningGroupKey); } toRunNewGroupMiners[runningGroupKey] = newGroupMiner; } else { noChangeGroupMiners[runningGroupKey] = _runningGroupMiners[runningGroupKey]; } } } } // check brand new foreach (var kvp in newGroupedMiningPairs) { var key = kvp.Key; var miningPairs = kvp.Value; if (_runningGroupMiners.ContainsKey(key) == false) { var newGroupMiner = new GroupMiner(miningPairs, key); toRunNewGroupMiners[key] = newGroupMiner; } } if ((toStopGroupMiners.Values.Count > 0) || (toRunNewGroupMiners.Values.Count > 0)) { var stringBuilderPreviousAlgo = new StringBuilder(); var stringBuilderCurrentAlgo = new StringBuilder(); var stringBuilderNoChangeAlgo = new StringBuilder(); // stop old miners foreach (var toStop in toStopGroupMiners.Values) { stringBuilderPreviousAlgo.Append($"{toStop.DevicesInfoString}: {toStop.AlgorithmType}, "); toStop.Stop(); _runningGroupMiners.Remove(toStop.Key); // TODO check if daggerHashimoto and save if (toStop.AlgorithmType == AlgorithmType.DaggerHashimoto) { if (toStop.DeviceType == DeviceType.NVIDIA) { _ethminerNvidiaPaused = toStop; } else if (toStop.DeviceType == DeviceType.AMD) { _ethminerAmdPaused = toStop; } } } // start new miners foreach (var toStart in toRunNewGroupMiners.Values) { stringBuilderCurrentAlgo.Append($"{toStart.DevicesInfoString}: {toStart.AlgorithmType}, "); toStart.Start(_miningLocation, _btcAdress, _worker); _runningGroupMiners[toStart.Key] = toStart; } // which miners dosen't change foreach (var noChange in noChangeGroupMiners.Values) { stringBuilderNoChangeAlgo.Append($"{noChange.DevicesInfoString}: {noChange.AlgorithmType}, "); } if (stringBuilderPreviousAlgo.Length > 0) { Helpers.ConsolePrint(Tag, $"Stop Mining: {stringBuilderPreviousAlgo}"); } if (stringBuilderCurrentAlgo.Length > 0) { Helpers.ConsolePrint(Tag, $"Now Mining : {stringBuilderCurrentAlgo}"); } if (stringBuilderNoChangeAlgo.Length > 0) { Helpers.ConsolePrint(Tag, $"No change : {stringBuilderNoChangeAlgo}"); } } } // stats quick fix code //if (_currentAllGroupedDevices.Count != _previousAllGroupedDevices.Count) { //await MinerStatsCheck(); //} _mainFormRatesComunication?.ForceMinerStatsUpdate(); }