Monte Carlo Simulation serverless using Python Shiny Live + Code!
aktieanalys
shinylive
python
interactive
valuation
Monte
Carlo
Monte Carlo Simulations are powerful. Using Shinylive with Python, you can leverage web assebely to distribute your insights with users who do not have the possibility to access your dynamic analysis otherwise.
Example of a Monte Carlo Simulation
#| standalone: true
#| layout-nrow: 1
#| viewerHeight: 820
from shiny import App, render, ui, Inputs, Outputs, Session
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def monte_carlo_simulation(years, initial_revenue, revenue_growth_range, profit_margin_range,fair_value):
final_results = []
num_simulations=10000
#fair_value=np.number(fair_value)
#print(fair_value)
for _ in range(num_simulations):
yearly_revenues = [initial_revenue]
yearly_profits = []
yearly_valuation = []
for year in range(years):
growth_rate = np.random.lognormal(revenue_growth_range[0], revenue_growth_range[1])
profit_margin = np.random.uniform(profit_margin_range[0], profit_margin_range[1])
new_revenue = yearly_revenues[-1] * (1 + growth_rate)
profit = new_revenue * profit_margin
valuation = profit*fair_value
yearly_revenues.append(new_revenue)
yearly_profits.append(profit)
yearly_valuation.append(valuation)
final_results.append({'Revenue': yearly_revenues[-1], 'Profit': yearly_profits[-1],
'Valuation': yearly_valuation[-1]})
return final_results
app_ui = ui.page_fluid(
ui.layout_sidebar(
ui.sidebar(
ui.h1("Monte Carlo Simulation"),
ui.input_slider("fair_value", "Fair P/E", min=5, max=40, value=25),
ui.input_slider("years", "Number of Years", min=1, max=10, value=3),
ui.input_numeric("initial_revenue", "Initial Revenue", value=27.5),
ui.input_slider("revenue_growth_min", "Mean Revenue Growth", min=-0.2, max=1, value=0.25, step=0.05),
ui.input_slider("revenue_growth_max", "Std Revenue Growth", min=0, max=1, value=0.1, step=0.05),
ui.input_slider("profit_margin_min", "Min Profit Margin", min=0, max=1, value=0.30, step=0.01),
ui.input_slider("profit_margin_max", "Max Profit Margin", min=0, max=1, value=0.50, step=0.01),
),
ui.layout_column_wrap(
ui.output_plot("simulation_plot")
)
)
)
def server(input: Inputs, output: Outputs, session: Session):
@output
@render.plot
def simulation_plot():
fair_value = input.fair_value()
years = input.years()
initial_revenue = input.initial_revenue()
revenue_growth_range = (input.revenue_growth_min(), input.revenue_growth_max())
profit_margin_range = (input.profit_margin_min(), input.profit_margin_max())
results = monte_carlo_simulation(years, initial_revenue, revenue_growth_range, profit_margin_range,fair_value)
Valuation = [result['Valuation'] for result in results]
Valuation_mean = round(np.mean(Valuation),1)
Valuation_std = round(np.std(Valuation),1)
plt.hist(Valuation, bins=30)
plt.title('Monte Carlo Simulation of Company Valuation over ' + str(years) + ' Years. Mean: ' + str(Valuation_mean)+'+-'+str(Valuation_std))
plt.xlabel('Valuation')
plt.ylabel('Frequency')
app = App(app_ui, server)
Code below to recreate dashboard above
-python}
```{shinylive#| standalone: true
#| layout-nrow: 1
#| viewerHeight: 820
from shiny import App, render, ui, Inputs, Outputs, Session
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def monte_carlo_simulation(years, initial_revenue, revenue_growth_range, profit_margin_range,fair_value):
= []
final_results =10000
num_simulations#fair_value=np.number(fair_value)
#print(fair_value)
for _ in range(num_simulations):
= [initial_revenue]
yearly_revenues = []
yearly_profits = []
yearly_valuation
for year in range(years):
= np.random.lognormal(revenue_growth_range[0], revenue_growth_range[1])
growth_rate = np.random.uniform(profit_margin_range[0], profit_margin_range[1])
profit_margin
= yearly_revenues[-1] * (1 + growth_rate)
new_revenue = new_revenue * profit_margin
profit = profit*fair_value
valuation
yearly_revenues.append(new_revenue)
yearly_profits.append(profit)
yearly_valuation.append(valuation)'Revenue': yearly_revenues[-1], 'Profit': yearly_profits[-1],
final_results.append({'Valuation': yearly_valuation[-1]})
return final_results
= ui.page_fluid(
app_ui
ui.layout_sidebar(
ui.sidebar("Monte Carlo Simulation"),
ui.h1("fair_value", "Fair P/E", min=5, max=40, value=25),
ui.input_slider("years", "Number of Years", min=1, max=10, value=3),
ui.input_slider("initial_revenue", "Initial Revenue", value=27.5),
ui.input_numeric("revenue_growth_min", "Mean Revenue Growth", min=-0.2, max=1, value=0.25, step=0.05),
ui.input_slider("revenue_growth_max", "Std Revenue Growth", min=0, max=1, value=0.1, step=0.05),
ui.input_slider("profit_margin_min", "Min Profit Margin", min=0, max=1, value=0.30, step=0.01),
ui.input_slider("profit_margin_max", "Max Profit Margin", min=0, max=1, value=0.50, step=0.01),
ui.input_slider(
),
ui.layout_column_wrap("simulation_plot")
ui.output_plot(
)
)
)
def server(input: Inputs, output: Outputs, session: Session):
@output
@render.plot
def simulation_plot():
= input.fair_value()
fair_value = input.years()
years = input.initial_revenue()
initial_revenue = (input.revenue_growth_min(), input.revenue_growth_max())
revenue_growth_range = (input.profit_margin_min(), input.profit_margin_max())
profit_margin_range
= monte_carlo_simulation(years, initial_revenue, revenue_growth_range, profit_margin_range,fair_value)
results
= [result['Valuation'] for result in results]
Valuation = round(np.mean(Valuation),1)
Valuation_mean = round(np.std(Valuation),1)
Valuation_std =30)
plt.hist(Valuation, bins'Monte Carlo Simulation of Company Valuation over ' + str(years) + ' Years. Mean: ' + str(Valuation_mean)+'+-'+str(Valuation_std))
plt.title('Valuation')
plt.xlabel('Frequency')
plt.ylabel(
= App(app_ui, server) ``` app