Skip to content

Instantly share code, notes, and snippets.

@dzid26
Last active January 2, 2023 23:02
Show Gist options
  • Save dzid26/fa66d374e09890c0876245f44918c899 to your computer and use it in GitHub Desktop.
Save dzid26/fa66d374e09890c0876245f44918c899 to your computer and use it in GitHub Desktop.
Compare bitcoin supply exponentially decaying rewards with a hypothetical linear one. Which one decays faster and when?
# Compare bitcoin supply exponentially decaying rewards with a hypothetical linear one
# Linear reward decay coefficient has been calibrated to produce 21 million bitcoins after 32 adjustments as in normal bitcoin
#%% parameters
reward_adjustments = 32
blocks_between_adjustment = 210000
minutes_every_block = 10
# metrics
years_per_adjustment = round(blocks_between_adjustment * minutes_every_block / 60 / 24 / 365) # ~4 years
all_rewarded_years = years_per_adjustment * reward_adjustments # ~128 years
print("Years per halving: %d" % years_per_adjustment)
#%% calculate bitcoin supply curve - exponential decay - current bitcoin design
initial_reward = 50
halving_block_reward_exp = []
yearly_rewards_exp = []
reward_decay_exp = []
yearly_block_reward_exp = []
supply_exp = []
print("Exponetial halving block reward:")
for halving in range(reward_adjustments):
halving_block_reward_exp.append(initial_reward / 2 ** halving)
print("%f" % halving_block_reward_exp[-1])
if halving > 0:
reward_decay_exp.append(halving_block_reward_exp[-1] - halving_block_reward_exp[-2])
years = range(all_rewarded_years)
for year in years:
yearly_block_reward_exp.append(halving_block_reward_exp[year // years_per_adjustment])
yearly_rewards_exp.append(yearly_block_reward_exp[-1] * blocks_between_adjustment / years_per_adjustment)
supply_exp.append(yearly_rewards_exp[-1] + (supply_exp[-1] if supply_exp else 0))
print("Total supply: %f" % supply_exp[-1])
#%% calculate bitcoin supply curve - linear decay
#backcalculate linear decay reward coefficient
initial_reward_lin = 6.05 #adjusted so that total supply is roughly equal to exponential decay total supply
halving_block_reward_lin = []
yearly_block_reward_lin = []
reward_decay_lin = []
yearly_rewards_lin = []
supply_lin = []
print("Linear halving block reward:")
for halving in range(reward_adjustments):
halving_block_reward_lin.append(initial_reward_lin*(1-(halving)/32) )
print("%f" % halving_block_reward_lin[-1])
if halving > 0:
reward_decay_lin.append(halving_block_reward_lin[-1] - halving_block_reward_lin[-2])
for year in years:
yearly_block_reward_lin.append(halving_block_reward_lin[year // years_per_adjustment])
yearly_rewards_lin.append(yearly_block_reward_lin[-1] * blocks_between_adjustment / years_per_adjustment)
supply_lin.append(yearly_rewards_lin[-1] + (supply_lin[-1] if supply_lin else 0))
print("Total supply: %f" % supply_lin[-1])
#%% crossover year
crossover_year = 0
print("\t\t Exponential vs linear \t\t Exponential vs linear")
halving=0
print(" %d: rewards %f vs %f" % (2009, halving_block_reward_exp[halving], halving_block_reward_lin[halving]))
for halving in range(0, reward_adjustments):
print("Halving %d: rewards %f vs %f, \t decay: %f vs %f" % ((halving+1) * years_per_adjustment+2008, halving_block_reward_exp[halving+1], halving_block_reward_lin[halving+1], reward_decay_exp[halving], reward_decay_lin[halving]))
if abs(reward_decay_lin[halving]) > abs(reward_decay_exp[halving]):
crossover_year = (halving+1) * years_per_adjustment
print("Crossover halving: %dth" % (halving))
break
crossover_year = 2008 + crossover_year
print("Crossover year: %d" % (crossover_year))
#%% plot the supply curves
import matplotlib.pyplot as plt
years2009 = [2008 + year for year in years]
plt.plot(years2009, supply_exp, label="Exponential")
plt.plot(years2009, supply_lin, label="Linear")
plt.ticklabel_format(axis="y", style="sci", scilimits=(6,6))
plt.text(2126, 21500000, "21mln", va='center')
plt.plot([crossover_year-1, crossover_year-1], [1111111, 22000000], label="Crossover year", linestyle="--")
plt.text(crossover_year, 5555555, f'{crossover_year}', va='center')
plt.legend()
plt.xlabel("Years")
plt.ylabel("Bitcoin Supply")
plt.title("Bitcoin Exponential Supply Curve vs alterative Linear Supply Curve")
plt.show()
#%% plot the yearly block reward
plt.step(years2009, yearly_block_reward_exp, label="Exponential")
plt.step(years2009, yearly_block_reward_lin, label="Linear")
plt.plot([crossover_year-1, crossover_year-1], [0, 50], label="Crossover year", linestyle="--")
plt.text(crossover_year, 11, f'{crossover_year}', va='center')
plt.legend()
plt.title("Bitcoin Yearly Block Reward")
plt.xlabel("Years")
plt.ylabel("Bitcoin Reward")
plt.show()
#%% reward decay
plt.plot(years2009[years_per_adjustment::years_per_adjustment], reward_decay_exp, label="Exponential", linestyle="", marker=".")
plt.plot(years2009[years_per_adjustment::years_per_adjustment], reward_decay_lin, label="Linear", linestyle="", marker=".")
plt.plot([crossover_year, crossover_year], [0, -25], label="Crossover year", linestyle="--")
plt.text(crossover_year, -22, f'{crossover_year}', va='center')
plt.legend()
plt.title("Bitcoin Block Reward decay (difference between years)")
plt.xlabel("Years")
plt.ylabel("Bitcoin decay")
plt.show()
# %%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment