smallbets / app.py
dvgodoy's picture
Update app.py
1915360 verified
import gradio as gr
from PIL import Image
from matplotlib import pyplot as plt
import numpy as np
import pickle
import gzip
import seaborn as sns
sns.set_theme()
def flip(n, t, seed=13):
np.random.seed(seed)
flips = np.random.randint(0, 2, size=(n, t))
heads = flips.cumsum(axis=1)
return heads.astype(np.uint8)
def load(filename):
# Adapted from https://gist.github.com/thearn/5424244
file = gzip.GzipFile(filename, 'rb')
data = file.read()
object = pickle.loads(data)
file.close()
return object
def calc_outcome(p_win, win, loss, leverage):
n = 1000000
t = 60
base=100
# heads = flip(n, t)
heads = load('flips.pkl.gz')
tails = np.arange(t)+1 - heads
p_loss = 1 - p_win
log_win = np.log(1+leverage*win)
log_loss = np.log(1-leverage*loss)
log_outcome = heads*log_win + tails*log_loss
outcome = base*(np.exp(log_outcome))
return outcome
def process(p_win, win, loss, leverage):
outcome = calc_outcome(p_win/100., win/100., loss/100., leverage/100.)
ensemble = fig2img(plot_ensemble(outcome)[0])
time = fig2img(plot_time(outcome)[0])
richest = fig2img(plot_richest(outcome)[0])
return ensemble, time, richest
def fig2img(fig):
"""Convert a Matplotlib figure to a PIL Image and return it"""
import io
buf = io.BytesIO()
fig.savefig(buf)
buf.seek(0)
img = Image.open(buf)
plt.close(fig)
return img
def plot_ensemble(outcome):
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
ax.plot(outcome.mean(axis=0))
ax.set_xlabel('Time')
ax.set_ylabel('Average Wealth ($)')
ax.set_title('Ensemble (Collective) Perspective')
fig.tight_layout()
return fig, ax
def plot_richest(outcome):
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
ax.plot(outcome.max(axis=0)/1e6)
ax.set_xlabel('Time')
ax.set_ylabel('Wealth ($ million)')
ax.set_title('Richest Individual')
fig.tight_layout()
return fig, ax
def plot_time(outcome):
fig, ax = plt.subplots(1, 1, figsize=(4, 4))
ax.plot(np.percentile(outcome, 50, axis=0))
ax.set_xlabel('Time')
ax.set_ylabel('Median Wealth ($)')
ax.set_title('Time (Individual) Perspective')
fig.tight_layout()
return fig, ax
css = ""
with gr.Blocks(css=css) as demo:
with gr.Column():
with gr.Row():
gr.Markdown('Choose the probability of a positive outcome.')
with gr.Row():
p_win = gr.Slider(0, 100, value=50, label='Win Prob.(%)', interactive=True)
with gr.Row():
gr.Markdown('Choose the return, in percentage, for a positive (gain) and negative (loss) outcome. For example, a 50% gain and 40% loss means a bet of $100 will either result in $150 (50% gain) or $60 (40% loss).')
win = gr.Number(value=50, label='Gain (%)', interactive=True)
loss = gr.Number(value=40, label='Loss (%)', interactive=True)
with gr.Row():
gr.Markdown('Choose the leverage, that is, the percentage of your total assets that you are willing to bet.')
leverage = gr.Slider(0, 100, value=100, label='Leverage (%)', interactive=True)
with gr.Row():
btn = gr.Button('Go!')
with gr.Column(scale=1, min_width=800):
with gr.Row():
ensemble = gr.Image(label="Ensemble Perspective", height=300, width=300, elem_id="plot_ensemble")
time = gr.Image(label="Time Perspective", height=300, width=300, elem_id="plot_time")
richest = gr.Image(label="Richest Individual", height=300, width=300, elem_id="plot_richest")
with gr.Column(scale=1, min_width=800):
with gr.Row():
gr.Markdown('The ensemble perspective shows the average wealth of an individual over time (which may be heavily affected by outliers, that is, an extremely rich individual). That is the expected value of the bet assuming ergodicity (in layman terms, "do over").')
gr.Markdown('The time perspective shows the median wealth, that is, the typical wealth of an individual. It is the likely outcome for a regular individual.')
gr.Markdown('This plot shows the wealth of the richest individual of them all, the one that got the best lucky streak out of 100,000 simulated individuals.')
btn.click(process, [p_win, win, loss, leverage], [ensemble, time, richest])
demo.launch()