QuantumLearner commited on
Commit
18ba6fe
·
verified ·
1 Parent(s): df9d831

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -0
app.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ import yfinance as yf
4
+ import plotly.graph_objects as go
5
+ import streamlit as st
6
+
7
+ #st.title('Analyzing Future Stock Price Movements with Monte Carlo Simulations')
8
+ st.set_page_config(page_title = "Analyzing Future Stock Price Movements with Monte Carlo Simulations", layout = "wide")
9
+
10
+ # Sidebar inputs
11
+ st.sidebar.header('Input Parameters')
12
+ ticker = st.sidebar.text_input('Enter Stock Ticker', 'AFX.DE')
13
+ start_date = st.sidebar.date_input('Start Date', pd.to_datetime('2020-01-01'))
14
+ end_date = st.sidebar.date_input('End Date', pd.to_datetime('2025-12-30'))
15
+ days_to_forecast = st.sidebar.slider('Time Horizon (Days)', min_value=1, max_value=60, value=30)
16
+ num_simulations = st.sidebar.number_input('Number of Simulations', min_value=100, max_value=100000, value=1000, step=100)
17
+ lower_threshold = st.sidebar.number_input('Lower Threshold', min_value=0, max_value=200, value=90)
18
+ upper_threshold = st.sidebar.number_input('Upper Threshold', min_value=0, max_value=200, value=110)
19
+ volatility_bsm = st.sidebar.number_input('BSM Volatility (Annualized)', min_value=0.01, max_value=10.0, value=0.29, step=0.01)
20
+
21
+ st.write("""
22
+ This analysis estimates potential price movements of a selected stock over a specified time horizon. The estimates are based on historical volatility and the implied volatility derived fromthe Black-Scholes-Merton model. You can adjust the time horizon, number of simulations, and implied volatility measure to explore different scenarios of price dynamics.
23
+ """)
24
+
25
+ st.markdown("""
26
+ ### How to Use This App
27
+ 1. **Input Parameters**: Use the sidebar to enter the stock ticker, date range, and other parameters for the analyses.
28
+ 2. **Run the Analysis**: Click the "Run" button to perform the analyses and visualize the results.
29
+ Each analysis is accompanied by a detailed explanation and visual representation, providing insights into the stock's price behavior and helping traders make informed decisions regarding potential price movements.
30
+ """)
31
+
32
+ # Adding LaTeX formatted formulas
33
+ # Display the main formula for Monte Carlo simulations with clear, basic LaTeX
34
+ st.latex(r'''
35
+ P_t = P_0 \times e^{(\mu - \frac{1}{2} \sigma^2) \times t + \sigma \times \sqrt{t} \times Z}
36
+ ''')
37
+
38
+ # Provide detailed explanations using plain text
39
+ st.markdown("""
40
+ **Monte Carlo Simulation Explained:**
41
+ - **(P_t)**: Estimated stock price at time (t).
42
+ - **(P_0)**: Current stock price.
43
+ - **(mu)**: Mean of the log returns.
44
+ - **(sigma)**: Standard deviation of the log returns, representing historical volatility.
45
+ - **(t)**: Time horizon in days.
46
+ - **(Z)**: Random variable from the standard normal distribution.
47
+ This formula models future stock prices using a stochastic process known as the Monte Carlo simulation. It considers both the average return and the variability in returns to project future price movements. The random component (Z) introduces randomness reflecting the unpredictable nature of stock price movements.
48
+ """)
49
+
50
+ # Note on usage
51
+ st.markdown("""
52
+ Use this tool to simulate different scenarios by varying the number of simulations and observing the distribution of possible future prices. Adjust the time horizon and volatility to see how these factors influence the projected price range. This analysis is crucial for assessing potential investment risks and rewards.
53
+ """)
54
+
55
+ st.write(f"""
56
+ ### Monte Carlo Simulations
57
+ These simulations project multiple potential future price paths for the stock based on the volatility models described. By running {num_simulations} simulations, the tool generates a distribution of possible future prices, allowing us to calculate confidence intervals and probabilities for various price levels.
58
+ """)
59
+
60
+ if st.sidebar.button('Run'):
61
+ stock_data = yf.download(ticker, start=start_date, end=end_date)
62
+
63
+ if not stock_data.empty:
64
+ stock_data['Returns'] = stock_data['Close'].pct_change()
65
+ log_returns = np.log(stock_data['Close'] / stock_data['Close'].shift(1))
66
+ current_price = stock_data.iloc[-1]['Close']
67
+
68
+ def run_simulation(volatility, dt, annualized=False):
69
+ simulated_prices = np.zeros((days_to_forecast, num_simulations))
70
+ simulated_prices[0] = current_price
71
+
72
+ if annualized:
73
+ volatility = volatility / np.sqrt(252)
74
+
75
+ for t in range(1, days_to_forecast):
76
+ random_walk = np.random.normal(loc=log_returns.mean() * dt,
77
+ scale=volatility * np.sqrt(dt),
78
+ size=num_simulations)
79
+ simulated_prices[t] = simulated_prices[t - 1] * np.exp(random_walk)
80
+ return simulated_prices
81
+
82
+ simulated_prices_historical = run_simulation(log_returns.std(), 1)
83
+ simulated_prices_bsm = run_simulation(volatility_bsm, 1, annualized=True)
84
+
85
+ fig1 = go.Figure()
86
+ fig2 = go.Figure()
87
+
88
+ for simulated_prices, fig, title in zip([simulated_prices_historical, simulated_prices_bsm],
89
+ [fig1, fig2], ['Historical Volatility', 'BSM Volatility']):
90
+ mean_price_path = np.mean(simulated_prices, axis=1)
91
+ median_price_path = np.median(simulated_prices, axis=1)
92
+ lower_bound_68 = np.percentile(simulated_prices, 16, axis=1)
93
+ upper_bound_68 = np.percentile(simulated_prices, 84, axis=1)
94
+ lower_bound_95 = np.percentile(simulated_prices, 2.5, axis=1)
95
+ upper_bound_95 = np.percentile(simulated_prices, 97.5, axis=1)
96
+
97
+ for i in range(min(num_simulations, 100)): # Plot a subset of paths for clarity
98
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=simulated_prices[:, i], mode='lines', line=dict(color='lightgray', width=0.5), opacity=0.3, showlegend=False))
99
+
100
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=mean_price_path, mode='lines', name='Mean Price Path', line=dict(color='black')))
101
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=median_price_path, mode='lines', name='Median Price Path', line=dict(color='blue')))
102
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=lower_bound_68, mode='lines', name='68% confidence interval (Lower)', line=dict(color='green', dash='dash')))
103
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=upper_bound_68, mode='lines', name='68% confidence interval (Upper)', line=dict(color='green', dash='dash')))
104
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=lower_bound_95, mode='lines', name='95% confidence interval (Lower)', line=dict(color='blue', dash='dash')))
105
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=upper_bound_95, mode='lines', name='95% confidence interval (Upper)', line=dict(color='red', dash='dash')))
106
+
107
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=[upper_threshold] * days_to_forecast, mode='lines', name='Upper Threshold', line=dict(color='purple')))
108
+ fig.add_trace(go.Scatter(x=np.arange(days_to_forecast), y=[lower_threshold] * days_to_forecast, mode='lines', name='Lower Threshold', line=dict(color='orange')))
109
+
110
+ above_upper_threshold_prob = (simulated_prices[-1] > upper_threshold).sum() / num_simulations
111
+ below_lower_threshold_prob = (simulated_prices[-1] < lower_threshold).sum() / num_simulations
112
+ between_thresholds_prob = 1 - above_upper_threshold_prob - below_lower_threshold_prob
113
+
114
+ fig.update_layout(
115
+ title=f'Monte Carlo Confidence Cone for {ticker} using {title}',
116
+ xaxis_title='Days',
117
+ yaxis_title='Stock Price',
118
+ legend_title='Legend'
119
+ )
120
+
121
+
122
+ fig.add_annotation(text=f'P(>{upper_threshold:.2f}): {above_upper_threshold_prob:.2%}<br>'
123
+ f'P(<{lower_threshold:.2f}): {below_lower_threshold_prob:.2%}<br>'
124
+ f'P({lower_threshold:.2f} - {upper_threshold:.2f}): {between_thresholds_prob:.2%}',
125
+ xref='paper', yref='paper', x=0.02, y=0.95, showarrow=False, bordercolor="black", borderwidth=1)
126
+
127
+ # Add elaboration text below each graph
128
+ st.plotly_chart(fig)
129
+ st.markdown(f"""
130
+ <h4 style='font-size: 16px;'>Interpretation of Results</h4>
131
+ <ul style='font-size: 14px;'>
132
+ <li><strong>Mean Price Path:</strong> The average simulated stock price path over the forecast period.</li>
133
+ <li><strong>Median Price Path:</strong> The median simulated stock price path over the forecast period.</li>
134
+ <li><strong>68% Confidence Interval:</strong> The range within which 68% of the simulated stock prices fall.</li>
135
+ <li><strong>95% Confidence Interval:</strong> The range within which 95% of the simulated stock prices fall.</li>
136
+ <li><strong>Probability of Exceeding Upper Threshold ({upper_threshold}):</strong> {above_upper_threshold_prob:.2%}</li>
137
+ <li><strong>Probability of Falling Below Lower Threshold ({lower_threshold}):</strong> {below_lower_threshold_prob:.2%}</li>
138
+ <li><strong>Probability of Staying Between Thresholds ({lower_threshold} - {upper_threshold}):</strong> {between_thresholds_prob:.2%}</li>
139
+ </ul>
140
+ """, unsafe_allow_html=True)
141
+
142
+ else:
143
+ st.write("No data found for the given ticker and date range.")
144
+
145
+
146
+ hide_streamlit_style = """
147
+ <style>
148
+ #MainMenu {visibility: hidden;}
149
+ footer {visibility: hidden;}
150
+ </style>
151
+ """
152
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)