Hi Awesome Miner Miners,
I just wanted to share something I've used to provide a slight more versatility to the profit switcher and how it's done, via Excel with little to no coding backgrounds.
What it does:
It is setting an external rule to fit the condition that
Initiate Profit Switching IF miner hashrate is >
xx% of profile defined hashrate
AND
Profit / Day / GPU is <
y.yyAND
Mining session is >
zz seconds.
What you need:
Awesome Miner Premium Edition or Greater (for API access)
Excel (I use office 365)
***
I'm not going into detailed step by step on how this is done. I'll just paste the (little modified) code here, for those interested but no programming background, you can just explore around and use the code below as a starting point.
Part 1 - Queries
Profile_ID (for identifying which profile miner is currently using)
let
Source = Xml.Tables(File.Contents("C:\Users\Username\AppData\Roaming\AwesomeMiner\ConfigData.xml")),
MinerSettings = Source{0}[MinerSettings],
#"Changed Type" = Table.TransformColumnTypes(MinerSettings,{{"ExternalMinerList", type text}}),
ManagedMinerList = #"Changed Type"{0}[ManagedMinerList],
#"Expanded ManagedMiner" = Table.ExpandTableColumn(ManagedMinerList, "ManagedMiner", {"ID", "ProfitProfileId"}, {"ManagedMiner.ID", "ManagedMiner.ProfitProfileId"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded ManagedMiner",{{"ManagedMiner.ID", "MinerID"}, {"ManagedMiner.ProfitProfileId", "ProfitProfileId"}}),
#"Changed Type1" = Table.TransformColumnTypes(#"Renamed Columns",{{"MinerID", type number}, {"ProfitProfileId", type number}})
in
#"Changed Type1"
ProfitProfile_HR_Table (Hashrate for each algos defined in every profit profile)
let
Source = Xml.Tables(File.Contents("C:\Users\Username\AppData\Roaming\AwesomeMiner\ConfigData.xml")),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"LogLevel", type text}, {"IsFirstRun", type logical}, {"IsFirstTimeMinimize", type logical}, {"AutoStart", type logical}, {"AutoStartMinimized", type logical}, {"AlwaysStartMinimized", type logical}, {"DevelopmentMode", type logical}, {"PerformanceMode", type logical}, {"CheckUpdates", type logical}, {"LongerConnectionTimeout", type logical}, {"AlternativeConnection", type logical}, {"DotNetVersionReminderDisplayed2", type logical}, {"PerformanceModeReminderDisplayed", type logical}, {"BenchmarkOffline", type logical}, {"ConfigurationCreatedUtc", type datetime}}),
ProfitSwitchingSettings = #"Changed Type"{0}[ProfitSwitchingSettings],
#"Changed Type1" = Table.TransformColumnTypes(ProfitSwitchingSettings,{{"EnabledPools", type text}, {"UseCustom", type logical}, {"CustomPoolId", Int64.Type}, {"CustomPoolType", type text}, {"NicehashWorker", type text}, {"NicehashRegion", type text}, {"ZpoolWorker", type text}, {"GranatGasWorker", type text}, {"GranatGasRegion", type text}, {"HashRefineryWorker", type text}, {"AHashPoolWorker", type text}, {"ZergPoolWorker", type text}, {"MiningDutchWorker", type text}, {"BlazepoolWorker", type text}, {"BlockMastersWorker", type text}, {"MiningPoolHubWorker", type text}, {"MiningPoolHubRegion", type text}, {"EnableManaged", type logical}, {"PredefinedVisible", type logical}, {"Interval", Int64.Type}, {"PowerCost", type number}, {"UseProfitThreshold", type logical}, {"ProfitThresholdPercent", Int64.Type}, {"NicehashUserUrl", type text}, {"ZpoolUserUrl", type text}, {"GranatGasUserUrl", type text}, {"HashRefineryUserUrl", type text}, {"AHashPoolUserUrl", type text}, {"MiningPoolHubUserUrl", type text}, {"ZergPoolAlgoUserUrl", type text}, {"MiningDutchAlgoUserUrl", type text}, {"BlazepoolUserUrl", type text}, {"BlockMastersUserUrl", type text}, {"SelectBtcPayout", type logical}, {"IgnoreFailedPools", type logical}, {"IgnoreFailedPoolsTime", Int64.Type}, {"RequiredAcceptTime", Int64.Type}}),
ProfitProfileList = #"Changed Type1"{0}[ProfitProfileList],
ProfitProfile = ProfitProfileList{0}[ProfitProfile],
#"Changed Type2" = Table.TransformColumnTypes(ProfitProfile,{{"ID", Int64.Type}, {"Description", type text}, {"PredefinedType", type text}, {"OverridePools", type logical}, {"EnableIgnorePools", type logical}, {"ProfileBatchCommands", type text}}),
#"Expanded AlgorithmSettingsList" = Table.ExpandTableColumn(#"Changed Type2", "AlgorithmSettingsList", {"AlgorithmSettings"}, {"AlgorithmSettings"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded AlgorithmSettingsList",{"PredefinedType", "OverridePools", "EnableIgnorePools", "SwitchingProfile", "ProfileBatchCommands", "ProfitEngineList"}),
#"Expanded AlgorithmSettings" = Table.ExpandTableColumn(#"Filtered Rows", "AlgorithmSettings", {"Algorithm", "HashrateValue"}, {"Algorithm", "HashrateValue"}),
#"Changed Type3" = Table.TransformColumnTypes(#"Expanded AlgorithmSettings",{{"HashrateValue", type number}, {"Algorithm", type text}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type3",{{"ID", "ProfitProfileId"}})
in
#"Renamed Columns"
miners (Joining the miners API call with the previous 2 queries, then do the calculation and determine if Profit Switching condition is met (example here, if hashrate > 85% defined hashrate and each GPU device (not miner) earns less than 0.05 USD, then switch condition is met), set this to auto refresh every minute or however long you see fit.
let
Source = Json.Document(Web.Contents("http://mypc:17790/api/miners")),
groupList = Source[groupList],
groupList1 = groupList{0},
minerList = groupList1[minerList],
#"Converted to Table" = Table.FromList(minerList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"id", "name", "statusInfo", "speedInfo", "coinInfo", "gpuList", "hasValidStatus"}, {"Column1.id", "Column1.name", "Column1.statusInfo", "Column1.speedInfo", "Column1.coinInfo", "Column1.gpuList", "Column1.hasValidStatus"}),
#"Expanded Column1.speedInfo" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1.speedInfo", {"hashrate"}, {"Column1.speedInfo.hashrate"}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Expanded Column1.speedInfo", "Column1.speedInfo.hashrate", Splitter.SplitTextByDelimiter(" ", QuoteStyle.Csv), {"Column1.speedInfo.hashrate.1", "Column1.speedInfo.hashrate.2"}),
#"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Column1.speedInfo.hashrate.1", type number}}),
#"Added Custom1" = Table.AddColumn(#"Changed Type", "GPU Count", each List.Count([Column1.gpuList])),
#"Expanded Column1.statusInfo" = Table.ExpandRecordColumn(#"Added Custom1", "Column1.statusInfo", {"secondsSinceStart", "statusDisplay"}, {"Column1.statusInfo.secondsSinceStart", "Column1.statusInfo.statusDisplay"}),
#"Expanded Column1.coinInfo" = Table.ExpandRecordColumn(#"Expanded Column1.statusInfo", "Column1.coinInfo", {"profitPerDayValue", "algorithm"}, {"Column1.coinInfo.profitPerDayValue", "Column1.coinInfo.algorithm"}),
#"Reordered Columns" = Table.ReorderColumns(#"Expanded Column1.coinInfo",{"Column1.id", "Column1.name", "Column1.statusInfo.statusDisplay", "Column1.statusInfo.secondsSinceStart", "Column1.coinInfo.profitPerDayValue", "Column1.hasValidStatus"}),
#"Merged Queries" = Table.NestedJoin(#"Appended Query",{"Column1.id"},Profile_ID,{"MinerID"},"ProfitProfile_HR_Table",JoinKind.LeftOuter),
#"Expanded ProfitProfile_HR_Table" = Table.ExpandTableColumn(#"Merged Queries", "ProfitProfile_HR_Table", {"ProfitProfileId"}, {"ProfitProfile_HR_Table.ProfitProfileId"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded ProfitProfile_HR_Table",{{"ProfitProfile_HR_Table.ProfitProfileId", "ProfitProfileId"}}),
#"Merged Queries1" = Table.NestedJoin(#"Renamed Columns",{"ProfitProfileId", "Column1.coinInfo.algorithm"},ProfitProfile_HR_Table,{"ProfitProfileId", "Algorithm"},"ProfitProfile_HR_Table",JoinKind.LeftOuter),
#"Expanded ProfitProfile_HR_Table1" = Table.ExpandTableColumn(#"Merged Queries1", "ProfitProfile_HR_Table", {"HashrateValue"}, {"ProfitProfile_HR_Table.HashrateValue"}),
#"Renamed Columns1" = Table.RenameColumns(#"Expanded ProfitProfile_HR_Table1",{{"ProfitProfile_HR_Table.HashrateValue", "ProfitProfile_HashRate"}}),
#"Added Custom" = Table.AddColumn(#"Renamed Columns1", "Custom", each if [Column1.statusInfo.secondsSinceStart] > 60 and [Column1.coinInfo.profitPerDayValue] <= (0.05*[GPU Count]) and [Column1.speedInfo.hashrate.1] > (0.85*[ProfitProfile_HashRate]) then 1 else 0),
#"Renamed Columns2" = Table.RenameColumns(#"Added Custom",{{"Column1.id", "RigID"}, {"Column1.name", "RigName"}, {"Column1.statusInfo.statusDisplay", "RigStatus"}, {"Column1.statusInfo.secondsSinceStart", "RunTime"}, {"Column1.speedInfo.hashrate.1", "HashRate"}, {"Column1.speedInfo.hashrate.2", "HashRateUnit"}, {"Column1.coinInfo.profitPerDayValue", "ProfitPerDay"}, {"Column1.coinInfo.algorithm", "Algo"}, {"Column1.hasValidStatus", "ValidStatus"}, {"ProfitProfile_HashRate", "Profile HashRate"}, {"ProfitProfileId", "Profile ID"}, {"Custom", "Switch"}}),
#"Changed Type1" = Table.TransformColumnTypes(#"Renamed Columns2",{{"Switch", Int64.Type}}),
#"Filtered Rows" = Table.SelectRows(#"Changed Type1", each ([RigStatus] = "Mining") and ([Algo] <> null)),
#"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Switch", Order.Descending}, {"RunTime", Order.Descending}}),
#"Filtered Rows1" = Table.SelectRows(#"Sorted Rows", each true)
in
#"Filtered Rows1"
Part 2 - Excel VBA / Macro
Here's the VBA to call the Profit Switching Action (check your AM's own rule ID, modify as per YOUR AM's settings), plus 2 procedures, 1 to start, 1 to pause, assign them to 2 buttons for easy access.
Global IsTimeToStop As Boolean
Sub runProfitSwitch()
Dim objHTTP As Object
Dim URL As String
Dim Data As String
Dim replyTXT
Dim URLConcat As String
Dim timeStamp As String
If IsTimeToStop Then Exit Sub
IsTimeToStop = False
timeStamp = Format(Now(), "dd-mm-yyyy hh:mm:ss")
Debug.Print "Running - " + timeStamp
If Cells(2, 14).Value = 1 Then
URLConcat = "http://mypc:17790/api/miners/" & Cells(2, 1).Value & "?action=rule&rule_id=8"
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "POST", URLConcat, False
objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.send ("")
End If
Debug.Print "Wait for next Run"
Application.OnTime Now + TimeValue("00:01:15"), "runProfitSwitch"
End Sub
Sub PauseMacro()
IsTimeToStop = True
Debug.Print "Stopping..."
End Sub
Sub StartSwitcher()
IsTimeToStop = False
runProfitSwitch
End Sub
remember, both
mypc in VBA code and queries, should be replaced by your AM main program PC's IP address.
Example screenshot:
and you only need to create a rule in AM that does 1 action: "Run Profit Switching" and enable "Support Manual Activation"