367 lines
9.9 KiB
Python
367 lines
9.9 KiB
Python
|
|
import pandas as pd
|
|
import matplotlib.pyplot as plt
|
|
import tabulate
|
|
|
|
# it = 0
|
|
|
|
def compounding_interest(balances, rate=0.05, terms=3):
|
|
if terms <= 0:
|
|
print("Number of terms must be >0!")
|
|
return
|
|
global it
|
|
balances_over_time = []
|
|
current_balances = balances
|
|
for i in range(0, terms):
|
|
new_bal = []
|
|
for balance in current_balances:
|
|
b = balance + (balance * rate)
|
|
new_bal.append(b)
|
|
# it += 1
|
|
assert(len(new_bal) == len(balances))
|
|
balances_over_time.append(new_bal)
|
|
current_balances = new_bal
|
|
return balances_over_time
|
|
|
|
def calc_share_of_wealth(balances):
|
|
total_money = sum(balances)
|
|
shares = []
|
|
for balance in balances:
|
|
shares.append(balance/total_money)
|
|
return shares
|
|
|
|
def ubi(balances, rate=10, terms=3):
|
|
dividend = rate
|
|
balances_over_time = []
|
|
current_balances = balances
|
|
for i in range(0, terms):
|
|
new_bal = []
|
|
for balance in current_balances:
|
|
b = balance + dividend
|
|
new_bal.append(b)
|
|
assert(len(new_bal) == len(balances))
|
|
balances_over_time.append(new_bal)
|
|
current_balances = new_bal
|
|
return balances_over_time
|
|
|
|
def mining(balances, halving_frequency=1, reward=10, terms=3):
|
|
balances_over_time = []
|
|
current_balances = balances
|
|
for i in range(0, terms):
|
|
new_bal = []
|
|
for balance in current_balances:
|
|
b = balance + reward
|
|
new_bal.append(b)
|
|
assert(len(new_bal) == len(balances))
|
|
if i % halving_frequency == 0:
|
|
reward = reward/2
|
|
balances_over_time.append(new_bal)
|
|
current_balances = new_bal
|
|
return balances_over_time
|
|
|
|
def get_balances_over_time(names, balances, data):
|
|
if len(names) != len(balances):
|
|
print("Every person needs a balance.")
|
|
return
|
|
df = pd.DataFrame({
|
|
'name' : names,
|
|
'initial' : balances
|
|
})
|
|
for i in range(0, len(data)):
|
|
key = str(i+1)
|
|
df[key] = data[i]
|
|
return df
|
|
|
|
# -------------
|
|
|
|
def illustrate_share_of_wealth():
|
|
|
|
participants = ["Alice", "Bob", "Charlie"]
|
|
balances = [100,40,20]
|
|
|
|
print("In this demo, we have three participants.\n", participants)
|
|
print("They respectively have ", balances)
|
|
|
|
print("\nThe initial distribution of wealth is ")
|
|
print(calc_share_of_wealth(balances))
|
|
print("\n")
|
|
|
|
df = get_balances_over_time (
|
|
participants, balances, compounding_interest(balances)
|
|
)
|
|
# print(it)
|
|
df["share"] = [val * 100 for val in calc_share_of_wealth(df["3"]) ]
|
|
|
|
print(df.to_html())
|
|
|
|
terms = 222
|
|
print(f"How much money exists after {terms} terms?")
|
|
#### In 222 terms, even C becomes a millionaire.
|
|
nb = compounding_interest(balances, terms=terms)
|
|
print(nb[-1])
|
|
print("\n")
|
|
|
|
df = get_balances_over_time (
|
|
participants, balances, ubi(balances)
|
|
)
|
|
print(df.to_html())
|
|
|
|
print("How much money exists after 999 terms?")
|
|
u = ubi(balances, terms=999)
|
|
print(u[-1])
|
|
|
|
print("What is the share of wealth in a UBI economy?")
|
|
print(calc_share_of_wealth(u[-1]))
|
|
|
|
|
|
|
|
def visualize_ubi(terms=25):
|
|
|
|
participants = ["Alice", "Bob", "Charlie"]
|
|
balances = [100,40,20]
|
|
|
|
df = get_balances_over_time (
|
|
participants, balances, ubi(balances, terms=terms)
|
|
)
|
|
# print(df.keys)
|
|
shares = []
|
|
for key, data in df.items():
|
|
if key == "name":
|
|
continue
|
|
if key == "initial":
|
|
continue
|
|
shares.append(calc_share_of_wealth(data))
|
|
sow = pd.DataFrame(shares)
|
|
x = [i for i in range(0,terms)]
|
|
try:
|
|
assert(len(x) == len(shares))
|
|
except AssertionError:
|
|
print(len(x), len(shares))
|
|
exit()
|
|
|
|
plt.style.use('dark_background')
|
|
plt.plot(
|
|
x, sow[0], color="red", label=participants[0]
|
|
)
|
|
plt.plot(
|
|
x, sow[1], color="lightgreen", label=participants[1]
|
|
)
|
|
plt.plot(
|
|
x, sow[2], color="cyan", label=participants[2]
|
|
)
|
|
plt.axhline(
|
|
y=0.33, color='violet', linestyle='--', label="0.33"
|
|
)
|
|
|
|
plt.title("Change in Wealth Distribution With a Constant Dividend")
|
|
plt.legend()
|
|
plt.xlabel("Terms")
|
|
plt.ylabel("Share of Wealth")
|
|
plt.savefig("ubi-wealth-distribution.png")
|
|
plt.close()
|
|
# plt.show()
|
|
return
|
|
|
|
def calc_total_supply(df):
|
|
total = []
|
|
for key, data in df.items():
|
|
if key == "name":
|
|
continue
|
|
total.append(sum(data))
|
|
return total
|
|
|
|
def draw_specific_chart1(terms=50, linear_label="? (linear)"):
|
|
participants = ["Alice", "Bob", "Charlie"]
|
|
balances = [100,40,20]
|
|
|
|
df = get_balances_over_time (
|
|
participants, balances, ubi(balances, terms=terms)
|
|
)
|
|
total_supply_ubi = calc_total_supply(df)
|
|
|
|
df_si = get_balances_over_time (
|
|
participants, balances,
|
|
compounding_interest(balances, terms=terms)
|
|
)
|
|
total_supply_si = calc_total_supply(df_si)
|
|
# + 1 because the initial frame is included this time
|
|
x = [i for i in range(0,terms+1)]
|
|
try:
|
|
assert(len(x) == len(total_supply_si))
|
|
except AssertionError:
|
|
print(len(x), len(total_supply_si))
|
|
print(df_si)
|
|
exit()
|
|
|
|
plt.style.use('dark_background')
|
|
plt.plot(
|
|
x, total_supply_si, color="red", label="apy = 0.05"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
compounding_interest(balances, terms=terms, rate=0.04)
|
|
)),
|
|
color="orange", label="apy = 0.04"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
compounding_interest(balances, terms=terms, rate=0.03)
|
|
)),
|
|
color="yellow", label="apy = 0.03"
|
|
)
|
|
plt.title("Supply of Money Over Time")
|
|
plt.legend()
|
|
plt.xlabel("Terms")
|
|
plt.ylabel("Total Currency")
|
|
plt.savefig("inflation-ubi-vs-5apy.png")
|
|
plt.close()
|
|
# plt.show()
|
|
|
|
def draw_specific_chart2(terms=50):
|
|
participants = ["Alice", "Bob", "Charlie"]
|
|
balances = [100,40,20]
|
|
|
|
df = get_balances_over_time (
|
|
participants, balances, ubi(balances, terms=terms)
|
|
)
|
|
total_supply_ubi = calc_total_supply(df)
|
|
|
|
df_si = get_balances_over_time (
|
|
participants, balances,
|
|
compounding_interest(balances, terms=terms)
|
|
)
|
|
total_supply_si = calc_total_supply(df_si)
|
|
# + 1 because the initial frame is included this time
|
|
x = [i for i in range(0,terms+1)]
|
|
assert(len(x) == len(total_supply_si))
|
|
|
|
plt.style.use('dark_background')
|
|
plt.plot(
|
|
x, total_supply_ubi, color="cyan", label="dividend = 10"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
ubi(balances, rate=5, terms=terms)
|
|
)),
|
|
color="violet", label="dividend = 5"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
ubi(balances, rate=15, terms=terms)
|
|
)),
|
|
color="lightgreen", label="dividend = 15"
|
|
)
|
|
plt.plot(
|
|
x, total_supply_si, color="red", label="apy = 0.05"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
compounding_interest(balances, rate=0.04, terms=terms)
|
|
)),
|
|
color="orange", label="apy = 0.04"
|
|
)
|
|
plt.plot(
|
|
x,
|
|
calc_total_supply(get_balances_over_time(
|
|
participants,
|
|
balances,
|
|
compounding_interest(balances, rate=0.03, terms=terms),
|
|
)),
|
|
color="yellow", label="apy = 0.03"
|
|
)
|
|
plt.title("Supply of Money Over Time")
|
|
plt.legend()
|
|
plt.xlabel("Terms")
|
|
plt.ylabel("Total Currency")
|
|
plt.savefig("inflation-ubi-vs-apy2.png")
|
|
plt.close()
|
|
# plt.show()
|
|
|
|
def visualize_inflation(df, title="Inflation", filename="inflation.png"):
|
|
supply_over_time = calc_total_supply(df)
|
|
time_span = len(supply_over_time)
|
|
x = [i for i in range(time_span)]
|
|
assert(len(x) == time_span)
|
|
|
|
plt.style.use('dark_background')
|
|
plt.plot(
|
|
x, supply_over_time, color="red")
|
|
plt.title(title)
|
|
plt.xlabel("Terms")
|
|
plt.ylabel("Total Currency")
|
|
plt.savefig(filename)
|
|
plt.close()
|
|
|
|
def visualize_wealth_dist(df, title="Wealth Distribution", filename="wealth-distribution.png"):
|
|
participants = df["name"]
|
|
shares = []
|
|
for key, data in df.items():
|
|
if key == "name":
|
|
continue
|
|
if key == "initial":
|
|
continue
|
|
shares.append(calc_share_of_wealth(data))
|
|
sow = pd.DataFrame(shares)
|
|
# print(sow.keys())
|
|
terms = sow.shape[0] + 1
|
|
x = [i for i in range(1,terms)]
|
|
print(len(x))
|
|
print(len(shares))
|
|
assert(len(x) == len(shares))
|
|
|
|
plt.style.use('dark_background')
|
|
plt.plot(
|
|
x, sow[0], color="red", label=participants[0]
|
|
)
|
|
plt.plot(
|
|
x, sow[1], color="lightgreen", label=participants[1]
|
|
)
|
|
plt.plot(
|
|
x, sow[2], color="cyan", label=participants[2]
|
|
)
|
|
plt.axhline(
|
|
y=0.33, color='violet', linestyle='--', label="0.33"
|
|
)
|
|
|
|
plt.title(title)
|
|
plt.legend()
|
|
plt.xlabel("Terms")
|
|
plt.ylabel("Share of Wealth")
|
|
plt.savefig(filename)
|
|
plt.close()
|
|
|
|
if __name__ == "__main__":
|
|
|
|
illustrate_share_of_wealth()
|
|
visualize_ubi(terms=50)
|
|
draw_specific_chart1(terms=75)
|
|
draw_specific_chart1(terms=75, linear_label="dividend = 10")
|
|
draw_specific_chart2(terms=75)
|
|
|
|
participants = ["Alice", "Bob", "Charlie"]
|
|
balances = [100,40,20]
|
|
m = get_balances_over_time(
|
|
participants, balances,
|
|
mining(balances, halving_frequency=1, terms=10)
|
|
)
|
|
print(m)
|
|
print(m.shape[1])
|
|
visualize_inflation(m, title="Inflation Given block_reward = 10 and Halving Every Term", filename="inflation-pow.png")
|
|
# print(m.iloc[:,:5].to_markdown())
|
|
visualize_wealth_dist(m, filename="wealth-distribution-pow.png")
|