diff --git a/simulation/calculator.py b/simulation/calculator.py index a1609a3..c76c082 100644 --- a/simulation/calculator.py +++ b/simulation/calculator.py @@ -5,6 +5,10 @@ class Calculator(metaclass=abc.ABCMeta): def __init__(self, configuration): self.configuration = configuration + @property + def rate(self): + return self.configuration.rate + def cost_per_hour(self, h): return h.watt * (self.configuration.kwh / 1000) diff --git a/simulation/egalitarianism.py b/simulation/egalitarianism.py index 3b9dd14..986993e 100644 --- a/simulation/egalitarianism.py +++ b/simulation/egalitarianism.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt from matplotlib import rc from matplotlib.backends.backend_pdf import PdfPages -from simulator import Simulator, GreedyTechnologyFirst, GreedyElectricityFirst, DP, Reinvested +from simulator import Simulator, GreedyTechnologyFirst, GreedyElectricityFirst, DP, Reinvested, DPReinvested from helpers import slugify, MultiArgument, Plot from mining_hardware import Hardware from configuration import Configuration @@ -65,7 +65,7 @@ def create_differencies(args, diff_args, hardware): def main(): parser = argparse.ArgumentParser(description='Cryptocurrency egalitarianism: A quantitative approach') parser.add_argument('-c', '--currency', default='btc', choices=['btc', 'eth', 'xmr', 'ltc', 'dcr'], help='Currency (default: %(default)s)') - parser.add_argument('-s', '--strategy', default='dp', choices=['tech', 'electricity', 'dp', 'reinvest'], help='Strategy of invenstment (default: %(default)s)') + parser.add_argument('-s', '--strategy', default='dp', choices=['tech', 'electricity', 'dp', 'reinvest', 'dp-reinvest'], help='Strategy of invenstment (default: %(default)s)') parser.add_argument('-d', '--difficulty', required=True, type=float, nargs='+', help='Block difficulty (required)') parser.add_argument('-b', '--coinbase', required=True, type=float, help='Coinbase (required)') parser.add_argument('-k', '--kwh', required=True, type=float, nargs='+', help='Price per kilowatt per hour (required)') @@ -79,7 +79,7 @@ def main(): args = parser.parse_args() calculators = {'btc': BTCCalculator, 'eth': ETHCalculator, 'xmr': XMRCalculator, 'ltc': BTCCalculator, 'dcr': BTCCalculator} - strategies = {'tech': GreedyTechnologyFirst, 'electricity': GreedyElectricityFirst, 'dp': DP, 'reinvest': Reinvested} + strategies = {'tech': GreedyTechnologyFirst, 'electricity': GreedyElectricityFirst, 'dp': DP, 'reinvest': Reinvested, 'dp-reinvest': DPReinvested} currencies = {'btc': ['Bitcoin'], 'eth': ['Ethereum'], 'xmr': ['Monero'], 'ltc': ['Litecoin'], 'dcr': ['Decred']} hardware = [] diff --git a/simulation/simulator.py b/simulation/simulator.py index 73462d9..782897f 100644 --- a/simulation/simulator.py +++ b/simulation/simulator.py @@ -126,14 +126,10 @@ def simulate(self, capital, hardware, calculator): class DP(Strategy): def construct_solution(self, capital, gain_velocity, items): solution = [] - initial_capital = capital - for i in range(capital, 0, -1): - if gain_velocity[i - 1] < gain_velocity[i]: - initial_capital -= int(items[i].price) - - if items[i] and initial_capital >= 0: - solution.append(items[i]) + while items[capital] and items[capital].price <= capital: + solution.append(items[capital]) + capital -= int(items[capital].price) return solution @@ -167,3 +163,43 @@ def simulate(self, initial_capital, hardware, calculator): r[x] = gain_velocity[x] * self._hours_of_operation return (r) + + +class DPReinvested(DP): + def simulate(self, initial_capital, hardware, calculator): + r = [0 for _ in range(initial_capital + 1)] + sorted_hardware = [h for h in sorted(hardware, key=lambda h: calculator.net(h), reverse=True) if calculator.net(h) > 0] + g = self.gain_velocity(initial_capital, sorted_hardware, calculator) + solution = [] + revenue_velocity = [] + cost_velocity = [] + price = [] + + total_gain_velocity = g[0] + total_items = g[1] + + for capital in range(initial_capital + 1): + solution.append(self.construct_solution(capital, total_gain_velocity, total_items)) + revenue_velocity.append(sum(calculator.expected_income(h) * calculator.rate for h in solution[capital])) + cost_velocity.append(sum(calculator.cost_per_hour(h) for h in solution[capital])) + price.append(int(sum(h.price for h in solution[capital]))) + + for capital in range(initial_capital + 1): + optimal_income = 0 + + for v_tech in range(capital + 1): + + if not solution[v_tech]: + continue + + v_pocket = capital - price[v_tech] + gain_velocity = total_gain_velocity[v_tech] + available_hours = v_pocket / cost_velocity[v_tech] + available_hours = min(self._hours_of_operation, available_hours) + + income = available_hours * revenue_velocity[v_tech] + (self._hours_of_operation - available_hours) * gain_velocity + optimal_income = max(optimal_income, income) + + r[capital] = optimal_income + + return (r)