Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,19 +7,23 @@ from datetime import datetime, timedelta
|
|
| 7 |
|
| 8 |
# Fetch stock data
|
| 9 |
def get_stock_data(ticker, start_date, end_date):
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# Bootstrapping simulation function
|
| 14 |
def bootstrap_simulation(data, days, n_iterations=10000):
|
| 15 |
daily_returns = data.pct_change().dropna()
|
| 16 |
-
|
| 17 |
-
daily_returns = daily_returns.values.flatten()
|
| 18 |
simulations = np.zeros((n_iterations, days))
|
|
|
|
| 19 |
|
| 20 |
for i in range(n_iterations):
|
| 21 |
sample = np.random.choice(daily_returns, size=days, replace=True)
|
| 22 |
-
simulations[i] = np.cumprod(1 + sample) *
|
| 23 |
|
| 24 |
return simulations
|
| 25 |
|
|
@@ -29,7 +33,6 @@ def calculate_probabilities(simulations, thresholds):
|
|
| 29 |
below = np.mean(final_prices < thresholds[0])
|
| 30 |
above = np.mean(final_prices > thresholds[1])
|
| 31 |
between = np.mean((final_prices >= thresholds[0]) & (final_prices <= thresholds[1]))
|
| 32 |
-
|
| 33 |
return {'below': below, 'between': between, 'above': above}
|
| 34 |
|
| 35 |
# Calculate percentiles
|
|
@@ -37,99 +40,62 @@ def calculate_percentiles(simulations):
|
|
| 37 |
percentiles = np.percentile(simulations, [2.5, 16, 50, 84, 97.5], axis=0)
|
| 38 |
return percentiles
|
| 39 |
|
|
|
|
| 40 |
def plot_distributions(bootstrap_simulations, data, thresholds, bootstrap_probabilities):
|
| 41 |
final_bootstrap_prices = bootstrap_simulations[:, -1]
|
| 42 |
-
|
| 43 |
mean_bootstrap_price = np.mean(final_bootstrap_prices)
|
| 44 |
median_bootstrap_price = np.median(final_bootstrap_prices)
|
| 45 |
ci_68_bootstrap = np.percentile(final_bootstrap_prices, [16, 84])
|
| 46 |
ci_95_bootstrap = np.percentile(final_bootstrap_prices, [2.5, 97.5])
|
| 47 |
-
latest_price = data.iloc[-1].item() #
|
| 48 |
|
| 49 |
fig = go.Figure()
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
fig.add_trace(go.
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
# Replace add_vline with add_trace for vertical lines with legends
|
| 56 |
-
fig.add_trace(go.Scatter(
|
| 57 |
-
x=[mean_bootstrap_price, mean_bootstrap_price],
|
| 58 |
-
y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()],
|
| 59 |
-
mode='lines',
|
| 60 |
-
line=dict(color='red', dash='dash'),
|
| 61 |
-
name=f'Mean: {mean_bootstrap_price:.2f}'
|
| 62 |
-
))
|
| 63 |
-
|
| 64 |
-
fig.add_trace(go.Scatter(
|
| 65 |
-
x=[median_bootstrap_price, median_bootstrap_price],
|
| 66 |
-
y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()],
|
| 67 |
-
mode='lines',
|
| 68 |
-
line=dict(color='orange', dash='dash'),
|
| 69 |
-
name=f'Median: {median_bootstrap_price:.2f}'
|
| 70 |
-
))
|
| 71 |
-
|
| 72 |
-
fig.add_trace(go.Scatter(
|
| 73 |
-
x=[latest_price, latest_price],
|
| 74 |
-
y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()],
|
| 75 |
-
mode='lines',
|
| 76 |
-
line=dict(color='green', dash='dash'),
|
| 77 |
-
name=f'Latest Price: {latest_price:.2f}'
|
| 78 |
-
))
|
| 79 |
-
|
| 80 |
-
# Add confidence intervals as vertical shaded regions
|
| 81 |
fig.add_vrect(x0=ci_68_bootstrap[0], x1=ci_68_bootstrap[1], fillcolor='yellow', opacity=0.2, layer="below", line_width=0)
|
| 82 |
fig.add_vrect(x0=ci_95_bootstrap[0], x1=ci_95_bootstrap[1], fillcolor='grey', opacity=0.2, layer="below", line_width=0)
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
fig.add_annotation(xref='paper', yref='paper', x=0.98, y=0.02, text=textstr, showarrow=False,
|
| 89 |
-
bordercolor="black", borderwidth=1, borderpad=4, bgcolor="white", opacity=0.4, font=dict(color="black"))
|
| 90 |
-
|
| 91 |
-
# Update layout
|
| 92 |
-
fig.update_layout(
|
| 93 |
-
title='Bootstrapping Simulation',
|
| 94 |
-
xaxis_title='Final Price',
|
| 95 |
-
yaxis_title='Frequency',
|
| 96 |
-
showlegend=True
|
| 97 |
-
)
|
| 98 |
|
|
|
|
| 99 |
return fig, mean_bootstrap_price, median_bootstrap_price, ci_68_bootstrap, ci_95_bootstrap, latest_price
|
| 100 |
|
| 101 |
-
|
| 102 |
# Plot price data with simulation cones
|
| 103 |
def plot_price_with_cones(data, bootstrap_percentiles, days, thresholds, bootstrap_probabilities):
|
| 104 |
last_date = data.index[-1]
|
| 105 |
future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=days, freq='D')
|
| 106 |
|
| 107 |
fig = go.Figure()
|
| 108 |
-
|
| 109 |
-
# Plot historical prices
|
| 110 |
fig.add_trace(go.Scatter(x=data.index, y=data, mode='lines', name='Historical Prices', line=dict(color='white')))
|
| 111 |
-
|
| 112 |
-
#
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
| 120 |
fig.add_hline(y=thresholds[0], line=dict(color='blue', dash='dash'), annotation_text=f'Threshold 1: {thresholds[0]}', annotation_position="top left")
|
| 121 |
fig.add_hline(y=thresholds[1], line=dict(color='green', dash='dash'), annotation_text=f'Threshold 2: {thresholds[1]}', annotation_position="top left")
|
| 122 |
|
| 123 |
-
#
|
| 124 |
-
textstr_bootstrap = f'Bootstrap Probabilities:<br>Below {thresholds[0]}: {bootstrap_probabilities["below"]:.2%}<br>'
|
| 125 |
-
f'Between {thresholds[0]} and {thresholds[1]}: {bootstrap_probabilities["between"]:.2%}<br>'
|
| 126 |
-
f'Above {thresholds[1]}: {bootstrap_probabilities["above"]:.2%}'
|
| 127 |
-
fig.add_annotation(xref='paper', yref='paper', x=0.98, y=0.02, text=textstr_bootstrap, showarrow=False,
|
| 128 |
-
bordercolor="black", borderwidth=1, borderpad=4, bgcolor="white", opacity=0.4, font=dict(color="black"))
|
| 129 |
|
| 130 |
fig.update_layout(title='Bootstrapping Simulation Cone', xaxis_title='Date', yaxis_title='Price', showlegend=True)
|
| 131 |
fig.update_xaxes(type='date')
|
| 132 |
-
|
| 133 |
return fig
|
| 134 |
|
| 135 |
# Streamlit app
|
|
@@ -138,7 +104,6 @@ st.title('Future Asset Prices Bootstrap Simulation')
|
|
| 138 |
|
| 139 |
st.sidebar.header('Input Parameters')
|
| 140 |
|
| 141 |
-
# How to use (in sidebar, closed by default)
|
| 142 |
with st.sidebar.expander("How to Use", expanded=False):
|
| 143 |
st.write("""
|
| 144 |
1. Enter the stock ticker or crypto pair (e.g., 'AAPL' or 'BTC-USD') in the 'Ticker' field.
|
|
@@ -149,7 +114,6 @@ with st.sidebar.expander("How to Use", expanded=False):
|
|
| 149 |
6. Analyze the resulting charts and statistics.
|
| 150 |
""")
|
| 151 |
|
| 152 |
-
# Ticker and dates in an expander (open by default)
|
| 153 |
with st.sidebar.expander("Symbol and Dates", expanded=True):
|
| 154 |
ticker = st.text_input('Enter Asset Symbol', 'ASML.AS', help="Enter a stock ticker (e.g., AAPL) or a crypto pair (e.g., BTC-USD)")
|
| 155 |
start_date = st.date_input('Start Date', pd.to_datetime('2020-01-01'), help="Select the start date for historical data")
|
|
@@ -168,7 +132,6 @@ This application simulates future asset prices using bootstrapping simulation me
|
|
| 168 |
You can specify the stock ticker or crypto pair, the date range, the number of simulation days, the number of simulations, and price thresholds.
|
| 169 |
The simulation results will show the probability of the price falling below, between, or above the specified thresholds.""")
|
| 170 |
|
| 171 |
-
|
| 172 |
with st.expander("Click here to read the description"):
|
| 173 |
st.write("""
|
| 174 |
### Description
|
|
@@ -203,8 +166,6 @@ with st.expander("Click here to read the description"):
|
|
| 203 |
4. **Estimate**: Use the bootstrap statistics to estimate the mean, standard error, and confidence intervals of \( \theta \).
|
| 204 |
""")
|
| 205 |
|
| 206 |
-
|
| 207 |
-
|
| 208 |
st.write("""**Results:**
|
| 209 |
The app will display two charts:
|
| 210 |
1. The distribution of the final simulated prices with key statistical measures.
|
|
@@ -212,42 +173,55 @@ The app will display two charts:
|
|
| 212 |
""")
|
| 213 |
|
| 214 |
if st.sidebar.button('Run Simulation'):
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
|
| 252 |
hide_streamlit_style = """
|
| 253 |
<style>
|
|
@@ -257,7 +231,6 @@ footer {visibility: hidden;}
|
|
| 257 |
"""
|
| 258 |
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
|
| 259 |
|
| 260 |
-
|
| 261 |
st.markdown("""
|
| 262 |
<style>
|
| 263 |
.stSelectbox, .stNumberInput {
|
|
|
|
| 7 |
|
| 8 |
# Fetch stock data
|
| 9 |
def get_stock_data(ticker, start_date, end_date):
|
| 10 |
+
data = yf.download(ticker, start=start_date, end=end_date, auto_adjust=False) # Unadjusted prices
|
| 11 |
+
if isinstance(data.columns, pd.MultiIndex): # Flatten multi-index columns
|
| 12 |
+
data.columns = data.columns.get_level_values(0)
|
| 13 |
+
if data.empty:
|
| 14 |
+
raise ValueError(f"No data found for {ticker} from {start_date} to {end_date}")
|
| 15 |
+
return data['Close']
|
| 16 |
|
| 17 |
# Bootstrapping simulation function
|
| 18 |
def bootstrap_simulation(data, days, n_iterations=10000):
|
| 19 |
daily_returns = data.pct_change().dropna()
|
| 20 |
+
daily_returns = daily_returns.values.flatten() # Ensure 1D array
|
|
|
|
| 21 |
simulations = np.zeros((n_iterations, days))
|
| 22 |
+
last_price = data.iloc[-1].item() # Scalar last price
|
| 23 |
|
| 24 |
for i in range(n_iterations):
|
| 25 |
sample = np.random.choice(daily_returns, size=days, replace=True)
|
| 26 |
+
simulations[i] = np.cumprod(1 + sample) * last_price
|
| 27 |
|
| 28 |
return simulations
|
| 29 |
|
|
|
|
| 33 |
below = np.mean(final_prices < thresholds[0])
|
| 34 |
above = np.mean(final_prices > thresholds[1])
|
| 35 |
between = np.mean((final_prices >= thresholds[0]) & (final_prices <= thresholds[1]))
|
|
|
|
| 36 |
return {'below': below, 'between': between, 'above': above}
|
| 37 |
|
| 38 |
# Calculate percentiles
|
|
|
|
| 40 |
percentiles = np.percentile(simulations, [2.5, 16, 50, 84, 97.5], axis=0)
|
| 41 |
return percentiles
|
| 42 |
|
| 43 |
+
# Plot distribution of final prices
|
| 44 |
def plot_distributions(bootstrap_simulations, data, thresholds, bootstrap_probabilities):
|
| 45 |
final_bootstrap_prices = bootstrap_simulations[:, -1]
|
|
|
|
| 46 |
mean_bootstrap_price = np.mean(final_bootstrap_prices)
|
| 47 |
median_bootstrap_price = np.median(final_bootstrap_prices)
|
| 48 |
ci_68_bootstrap = np.percentile(final_bootstrap_prices, [16, 84])
|
| 49 |
ci_95_bootstrap = np.percentile(final_bootstrap_prices, [2.5, 97.5])
|
| 50 |
+
latest_price = data.iloc[-1].item() # Scalar for plotting
|
| 51 |
|
| 52 |
fig = go.Figure()
|
| 53 |
+
fig.add_trace(go.Histogram(x=final_bootstrap_prices, nbinsx=50, name='Simulated Final Prices', marker_color='blue', opacity=0.7))
|
| 54 |
+
fig.add_trace(go.Scatter(x=[mean_bootstrap_price, mean_bootstrap_price], y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()], mode='lines', line=dict(color='red', dash='dash'), name=f'Mean: {mean_bootstrap_price:.2f}'))
|
| 55 |
+
fig.add_trace(go.Scatter(x=[median_bootstrap_price, median_bootstrap_price], y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()], mode='lines', line=dict(color='orange', dash='dash'), name=f'Median: {median_bootstrap_price:.2f}'))
|
| 56 |
+
fig.add_trace(go.Scatter(x=[latest_price, latest_price], y=[0, np.histogram(final_bootstrap_prices, bins=50)[0].max()], mode='lines', line=dict(color='green', dash='dash'), name=f'Latest Price: {latest_price:.2f}'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
fig.add_vrect(x0=ci_68_bootstrap[0], x1=ci_68_bootstrap[1], fillcolor='yellow', opacity=0.2, layer="below", line_width=0)
|
| 58 |
fig.add_vrect(x0=ci_95_bootstrap[0], x1=ci_95_bootstrap[1], fillcolor='grey', opacity=0.2, layer="below", line_width=0)
|
| 59 |
|
| 60 |
+
textstr = (f'P(>{thresholds[1]:.2f}): {bootstrap_probabilities["above"]:.2%}<br>'
|
| 61 |
+
f'P(<{thresholds[0]:.2f}): {bootstrap_probabilities["below"]:.2%}<br>'
|
| 62 |
+
f'P({thresholds[0]:.2f} - {thresholds[1]:.2f}): {bootstrap_probabilities["between"]:.2%}')
|
| 63 |
+
fig.add_annotation(xref='paper', yref='paper', x=0.98, y=0.02, text=textstr, showarrow=False, bordercolor="black", borderwidth=1, borderpad=4, bgcolor="white", opacity=0.4)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
+
fig.update_layout(title='Bootstrapping Simulation', xaxis_title='Final Price', yaxis_title='Frequency', showlegend=True)
|
| 66 |
return fig, mean_bootstrap_price, median_bootstrap_price, ci_68_bootstrap, ci_95_bootstrap, latest_price
|
| 67 |
|
|
|
|
| 68 |
# Plot price data with simulation cones
|
| 69 |
def plot_price_with_cones(data, bootstrap_percentiles, days, thresholds, bootstrap_probabilities):
|
| 70 |
last_date = data.index[-1]
|
| 71 |
future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=days, freq='D')
|
| 72 |
|
| 73 |
fig = go.Figure()
|
| 74 |
+
# Historical prices
|
|
|
|
| 75 |
fig.add_trace(go.Scatter(x=data.index, y=data, mode='lines', name='Historical Prices', line=dict(color='white')))
|
| 76 |
+
|
| 77 |
+
# Simulation cone (check for valid percentiles)
|
| 78 |
+
if bootstrap_percentiles.shape[1] == len(future_dates):
|
| 79 |
+
fig.add_trace(go.Scatter(x=future_dates, y=bootstrap_percentiles[2], mode='lines', name='Bootstrap Median', line=dict(color='red', dash='dash')))
|
| 80 |
+
fig.add_trace(go.Scatter(x=future_dates, y=bootstrap_percentiles[0], fill=None, mode='lines', line=dict(color='lightgrey'), showlegend=False))
|
| 81 |
+
fig.add_trace(go.Scatter(x=future_dates, y=bootstrap_percentiles[4], fill='tonexty', mode='lines', line=dict(color='lightgrey'), name='Bootstrap 95% CI'))
|
| 82 |
+
fig.add_trace(go.Scatter(x=future_dates, y=bootstrap_percentiles[1], fill=None, mode='lines', line=dict(color='lightyellow'), showlegend=False))
|
| 83 |
+
fig.add_trace(go.Scatter(x=future_dates, y=bootstrap_percentiles[3], fill='tonexty', mode='lines', line=dict(color='lightyellow'), name='Bootstrap 68% CI'))
|
| 84 |
+
else:
|
| 85 |
+
st.warning("Simulation percentiles length does not match future dates. Check simulation output.")
|
| 86 |
+
|
| 87 |
+
# Thresholds
|
| 88 |
fig.add_hline(y=thresholds[0], line=dict(color='blue', dash='dash'), annotation_text=f'Threshold 1: {thresholds[0]}', annotation_position="top left")
|
| 89 |
fig.add_hline(y=thresholds[1], line=dict(color='green', dash='dash'), annotation_text=f'Threshold 2: {thresholds[1]}', annotation_position="top left")
|
| 90 |
|
| 91 |
+
# Probability annotations
|
| 92 |
+
textstr_bootstrap = (f'Bootstrap Probabilities:<br>Below {thresholds[0]}: {bootstrap_probabilities["below"]:.2%}<br>'
|
| 93 |
+
f'Between {thresholds[0]} and {thresholds[1]}: {bootstrap_probabilities["between"]:.2%}<br>'
|
| 94 |
+
f'Above {thresholds[1]}: {bootstrap_probabilities["above"]:.2%}')
|
| 95 |
+
fig.add_annotation(xref='paper', yref='paper', x=0.98, y=0.02, text=textstr_bootstrap, showarrow=False, bordercolor="black", borderwidth=1, borderpad=4, bgcolor="white", opacity=0.4)
|
|
|
|
| 96 |
|
| 97 |
fig.update_layout(title='Bootstrapping Simulation Cone', xaxis_title='Date', yaxis_title='Price', showlegend=True)
|
| 98 |
fig.update_xaxes(type='date')
|
|
|
|
| 99 |
return fig
|
| 100 |
|
| 101 |
# Streamlit app
|
|
|
|
| 104 |
|
| 105 |
st.sidebar.header('Input Parameters')
|
| 106 |
|
|
|
|
| 107 |
with st.sidebar.expander("How to Use", expanded=False):
|
| 108 |
st.write("""
|
| 109 |
1. Enter the stock ticker or crypto pair (e.g., 'AAPL' or 'BTC-USD') in the 'Ticker' field.
|
|
|
|
| 114 |
6. Analyze the resulting charts and statistics.
|
| 115 |
""")
|
| 116 |
|
|
|
|
| 117 |
with st.sidebar.expander("Symbol and Dates", expanded=True):
|
| 118 |
ticker = st.text_input('Enter Asset Symbol', 'ASML.AS', help="Enter a stock ticker (e.g., AAPL) or a crypto pair (e.g., BTC-USD)")
|
| 119 |
start_date = st.date_input('Start Date', pd.to_datetime('2020-01-01'), help="Select the start date for historical data")
|
|
|
|
| 132 |
You can specify the stock ticker or crypto pair, the date range, the number of simulation days, the number of simulations, and price thresholds.
|
| 133 |
The simulation results will show the probability of the price falling below, between, or above the specified thresholds.""")
|
| 134 |
|
|
|
|
| 135 |
with st.expander("Click here to read the description"):
|
| 136 |
st.write("""
|
| 137 |
### Description
|
|
|
|
| 166 |
4. **Estimate**: Use the bootstrap statistics to estimate the mean, standard error, and confidence intervals of \( \theta \).
|
| 167 |
""")
|
| 168 |
|
|
|
|
|
|
|
| 169 |
st.write("""**Results:**
|
| 170 |
The app will display two charts:
|
| 171 |
1. The distribution of the final simulated prices with key statistical measures.
|
|
|
|
| 173 |
""")
|
| 174 |
|
| 175 |
if st.sidebar.button('Run Simulation'):
|
| 176 |
+
try:
|
| 177 |
+
st.write(f"Fetching data for {ticker}...")
|
| 178 |
+
data = get_stock_data(ticker, start_date, end_date)
|
| 179 |
+
|
| 180 |
+
# Debug data
|
| 181 |
+
st.write(f"Data shape: {data.shape}")
|
| 182 |
+
st.write(f"Last few rows: {data.tail()}")
|
| 183 |
+
|
| 184 |
+
bootstrap_simulations = bootstrap_simulation(data, days, n_iterations)
|
| 185 |
+
bootstrap_probabilities = calculate_probabilities(bootstrap_simulations, thresholds)
|
| 186 |
+
bootstrap_percentiles = calculate_percentiles(bootstrap_simulations)
|
| 187 |
+
|
| 188 |
+
# Debug simulation output
|
| 189 |
+
st.write(f"Simulations shape: {bootstrap_simulations.shape}")
|
| 190 |
+
st.write(f"Percentiles shape: {bootstrap_percentiles.shape}")
|
| 191 |
+
|
| 192 |
+
fig1, mean_bootstrap_price, median_bootstrap_price, ci_68_bootstrap, ci_95_bootstrap, latest_price = plot_distributions(bootstrap_simulations, data, thresholds, bootstrap_probabilities)
|
| 193 |
+
fig2 = plot_price_with_cones(data, bootstrap_percentiles, days, thresholds, bootstrap_probabilities)
|
| 194 |
+
|
| 195 |
+
st.plotly_chart(fig1)
|
| 196 |
+
if bootstrap_percentiles.shape[1] == days:
|
| 197 |
+
st.plotly_chart(fig2)
|
| 198 |
+
else:
|
| 199 |
+
st.error("Time series plot failed: Percentiles length does not match simulation days.")
|
| 200 |
+
|
| 201 |
+
st.write(f"""
|
| 202 |
+
### Interpretation of Results
|
| 203 |
+
|
| 204 |
+
**Distribution of Final Simulated Prices:**
|
| 205 |
+
- **Mean Final Price:** {mean_bootstrap_price:.2f}
|
| 206 |
+
- **Median Final Price:** {median_bootstrap_price:.2f}
|
| 207 |
+
- **68% Confidence Interval (CI):** [{ci_68_bootstrap[0]:.2f}, {ci_68_bootstrap[1]:.2f}]
|
| 208 |
+
- **95% Confidence Interval (CI):** [{ci_95_bootstrap[0]:.2f}, {ci_95_bootstrap[1]:.2f}]
|
| 209 |
+
- **Latest Price:** {latest_price:.2f}
|
| 210 |
+
|
| 211 |
+
**Bootstrapping Simulation Cone:**
|
| 212 |
+
- **Bootstrap Median:** The median of the simulated future prices for each day.
|
| 213 |
+
- **Bootstrap 68% CI:** The 68% confidence interval for the simulated future prices.
|
| 214 |
+
- **Bootstrap 95% CI:** The 95% confidence interval for the simulated future prices.
|
| 215 |
+
- **Threshold 1 and Threshold 2:** {threshold1:.2f}, {threshold2:.2f}
|
| 216 |
+
- **Probability Annotations:**
|
| 217 |
+
- The probability of the price being below Threshold 1: {bootstrap_probabilities["below"]:.2%}
|
| 218 |
+
- The probability of the price being between Threshold 1 and Threshold 2: {bootstrap_probabilities["between"]:.2%}
|
| 219 |
+
- The probability of the price being above Threshold 2: {bootstrap_probabilities["above"]:.2%}
|
| 220 |
+
|
| 221 |
+
These results help in understanding the potential future movements of the stock or cryptocurrency price based on historical data and bootstrapping simulation.
|
| 222 |
+
""")
|
| 223 |
+
except Exception as e:
|
| 224 |
+
st.error(f"Error: {str(e)}. Check ticker, date range, or try again.")
|
| 225 |
|
| 226 |
hide_streamlit_style = """
|
| 227 |
<style>
|
|
|
|
| 231 |
"""
|
| 232 |
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
|
| 233 |
|
|
|
|
| 234 |
st.markdown("""
|
| 235 |
<style>
|
| 236 |
.stSelectbox, .stNumberInput {
|