QuantumLearner commited on
Commit
c152d1f
·
verified ·
1 Parent(s): 3dd5a85

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -101
app.py CHANGED
@@ -1,11 +1,3 @@
1
- #import numpy as np
2
- #np.core.multiarray # Ensure numpy's C API is loaded
3
- #np._import_array() # Force initialization of numpy's C API
4
- #import numpy.core.multiarray
5
-
6
- # app.py
7
- import init # Ensure numpy's C API is initialized
8
-
9
  import numpy as np
10
  import streamlit as st
11
  import pandas as pd
@@ -26,93 +18,70 @@ It simulates various market scenarios to analyze the dependencies between differ
26
  Users can assess potential outcomes in terms of best, worst, and mean case scenarios.
27
  """)
28
 
29
- st.sidebar.subheader("How to Use")
30
- st.sidebar.write("""
31
- 1. Select the date range for the analysis.
32
- 2. Adjust the market drop percentage.
33
- 3. Enter the tickers and their respective weights.
34
- 4. Select the ticker for the drop scenario.
35
- 5. Click on 'Run Analysis' to execute.
36
- """)
37
-
38
- # Sidebar inputs
39
- st.sidebar.header("Input Parameters")
40
-
41
- st.sidebar.subheader("Portfolio Allocation")
42
- portfolio_tickers = st.sidebar.text_area("Enter Tickers (comma-separated)", "^GSPC,MSFT,AAPL,GOOGL,ASML").split(',')
43
- portfolio_weights = st.sidebar.text_area("Enter Weights (comma-separated) (Must add to 1)", "0.1,0.3,0.3,0.2,0.1").split(',')
44
- portfolio_weights = [float(weight) for weight in portfolio_weights]
45
-
46
- drop_ticker = st.sidebar.text_input("Enter Drop Ticker", "^GSPC")
47
- market_drop_percentage = st.sidebar.slider("Market Drop Percentage", min_value=-0.1, max_value=0.0, step=0.01, value=-0.05)
48
-
49
- start_date = st.sidebar.date_input("Start Date", value=pd.to_datetime("2020-01-01"))
50
- end_date = st.sidebar.date_input("End Date", value=pd.to_datetime("2025-01-01"))
51
- num_simulations = st.sidebar.number_input("Number of Simulations", min_value=1000, max_value=100000, step=1000, value=50000)
52
- rolling_window = st.sidebar.number_input("Rolling Window", min_value=7, max_value=1000, step=10, value=250)
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  if len(portfolio_tickers) != len(portfolio_weights):
56
  st.sidebar.error("The number of tickers must match the number of weights.")
57
 
58
-
59
  run_button = st.sidebar.button("Run Analysis")
60
 
61
  if run_button and len(portfolio_tickers) == len(portfolio_weights):
62
 
 
63
  st.markdown("## Simulating Market Drop Scenarios: Best, Worst, and Mean Cases")
64
- #st.markdown("## Transforming Returns")
65
- st.markdown("""
66
- To prepare the returns for copula modeling, we transform them to a uniform distribution using quantile transformation.
67
- This step ensures that the data fits within the range required by the copula model.
68
- """)
69
- st.latex(r"""
70
- u_i = \frac{\text{rank}(R_i)}{n + 1}
71
- """)
72
 
73
- #st.markdown("## Fitting the Copula Model")
74
- st.markdown("""
75
- Next, we fit a multivariate Student-t copula to the transformed data. The copula model captures the dependencies between the stock returns,
76
- enabling us to understand the joint behavior of the assets.
77
- """)
78
- st.latex(r"""
79
- C_{\nu}(u_1, u_2, \ldots, u_d) = t_{\nu, \Sigma}(t_{\nu}^{-1}(u_1), t_{\nu}^{-1}(u_2), \ldots, t_{\nu}^{-1}(u_d))
80
- """)
81
 
82
- #st.markdown("## Simulating Scenarios")
83
- st.markdown("""
84
- Using the fitted copula model, we simulate a large number of return scenarios. This simulation helps us explore potential future outcomes
85
- and assess the portfolio's risk under various market conditions.
86
- """)
87
-
88
- #st.markdown("## Market Drop Scenarios")
89
- st.markdown("""
90
- We identify scenarios where the specified ticker drops by the given percentage. By analyzing these scenarios, we can evaluate how the portfolio performs under stress.
91
- """)
92
 
93
- #st.markdown("## Portfolio Returns")
94
- st.markdown("""
95
- For each identified scenario, we calculate the portfolio returns. The portfolio return is a weighted sum of the individual stock returns.
96
- """)
97
- st.latex(r"""
98
- R_p = \sum_{i=1}^{n} w_i R_i
99
- """)
100
 
101
- #st.markdown("## Visualizing Results")
102
- st.markdown("""
103
- We visualize the simulated portfolio returns using histograms, cumulative distribution functions (CDF), and kernel density estimates (KDE).
104
- These visualizations help us understand the distribution and characteristics of potential returns.
105
- """)
106
 
107
- #st.markdown("## Portfolio Price Trajectory")
108
- st.markdown("""
109
- Finally, we visualize the portfolio's price trajectory under the worst-case, best-case, and mean scenarios.
110
- This helps in understanding the potential impact of market drops on the portfolio value.
111
- """)
112
-
113
-
114
-
115
-
116
 
117
  # Define the portfolio and allocation
118
  portfolio_allocation = dict(zip(portfolio_tickers, portfolio_weights))
@@ -138,7 +107,6 @@ if run_button and len(portfolio_tickers) == len(portfolio_weights):
138
  copula.fit(data_uniform.values)
139
 
140
  # Simulate scenarios
141
- #num_simulations = 50000
142
  simulated_uniform = copula.random(num_simulations)
143
  simulated_returns = pd.DataFrame(index=range(num_simulations), columns=data_uniform.columns)
144
 
@@ -257,25 +225,23 @@ if run_button and len(portfolio_tickers) == len(portfolio_weights):
257
 
258
  st.plotly_chart(fig_price)
259
 
260
- # Tail Dependence Analysis
261
  # Tail Dependence Analysis
262
  st.markdown("## Tail Dependence Analysis")
263
  st.markdown("""
264
  Tail dependence measures the likelihood of extreme returns occurring simultaneously across different stocks in the portfolio.
265
- It is a critical aspect of understanding how assets behave in extreme market conditions.
266
-
267
- We use the Clayton copula to model the tail dependence. The parameter \\(\theta\\) of the Clayton copula is related to the tail dependence by:
268
- """)
269
- st.latex(r"""
270
- \lambda_{L} = 2^{1/\theta} - 1
271
- """)
272
- st.markdown("""
273
- Where:
274
- - λ1 is the lower tail dependence.
275
- - θ is the parameter of the Clayton copula.
276
-
277
- A higher λ1 value indicates a stronger relationship in the tails, meaning that extreme losses in one stock are more likely to coincide with extreme losses in another.
278
  """)
 
 
 
 
 
 
 
 
 
 
 
279
 
280
  def to_uniform(column):
281
  n = len(column)
@@ -336,11 +302,10 @@ if run_button and len(portfolio_tickers) == len(portfolio_weights):
336
  """)
337
 
338
  # Rolling window analysis
339
- window_size = rolling_window #250
340
  tail_parameters = []
341
 
342
- for start in range(0, len(uniform_data) - window_size):
343
- window_data = uniform_data.iloc[start:start + window_size]
344
 
345
  copula = Clayton()
346
  copula.fit(window_data.values)
@@ -350,7 +315,7 @@ if run_button and len(portfolio_tickers) == len(portfolio_weights):
350
 
351
  # Tail Dependence Over Time
352
  fig1 = go.Figure()
353
- fig1.add_trace(go.Scatter(x=returns.index[window_size:], y=tail_parameters, mode='lines', name='Tail Dependence Parameter'))
354
  fig1.update_layout(
355
  title="Tail Dependence Over Time",
356
  xaxis_title="Date",
@@ -359,11 +324,11 @@ if run_button and len(portfolio_tickers) == len(portfolio_weights):
359
 
360
  st.plotly_chart(fig1)
361
 
362
-
363
  hide_streamlit_style = """
364
  <style>
365
  #MainMenu {visibility: hidden;}
366
  footer {visibility: hidden;}
367
  </style>
368
  """
369
- st.markdown(hide_streamlit_style, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
1
  import numpy as np
2
  import streamlit as st
3
  import pandas as pd
 
18
  Users can assess potential outcomes in terms of best, worst, and mean case scenarios.
19
  """)
20
 
21
+ # Sidebar: How to Use (closed by default)
22
+ with st.sidebar.expander("How to Use", expanded=False):
23
+ st.write("""
24
+ 1. Select the date range for the analysis.
25
+ 2. Adjust the market drop percentage.
26
+ 3. Enter the tickers and their respective weights.
27
+ 4. Select the ticker for the drop scenario.
28
+ 5. Click on 'Run Analysis' to execute.
29
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ # Sidebar: Ticker and Dates (open by default)
32
+ with st.sidebar.expander("Ticker and Dates", expanded=True):
33
+ portfolio_tickers = st.text_area("Enter Tickers (comma-separated)", "^GSPC,MSFT,AAPL,GOOGL,ASML",
34
+ help="Enter the tickers for the assets in the portfolio, separated by commas.").split(',')
35
+ portfolio_weights = st.text_area("Enter Weights (comma-separated) (Must add to 1)", "0.1,0.3,0.3,0.2,0.1",
36
+ help="Enter the weights for each ticker, separated by commas. Make sure they sum to 1.").split(',')
37
+ portfolio_weights = [float(weight) for weight in portfolio_weights]
38
+
39
+ start_date = st.date_input("Start Date", value=pd.to_datetime("2020-01-01"),
40
+ help="Select the start date for the analysis period.")
41
+ end_date = st.date_input("End Date", value=pd.to_datetime(pd.Timestamp.now().date() + pd.Timedelta(days=1)),
42
+ help="Select the end date for the analysis period.")
43
+
44
+ # Sidebar: Market Drop Settings (open by default)
45
+ with st.sidebar.expander("Market Drop Settings", expanded=True):
46
+ drop_ticker = st.text_input("Enter Drop Ticker", "^GSPC",
47
+ help="Enter the ticker of the asset that will experience a drop.")
48
+ market_drop_percentage = st.slider("Market Drop Percentage", min_value=-0.1, max_value=0.0, step=0.01, value=-0.05,
49
+ help="Set the percentage drop in the market for the scenario.")
50
+ num_simulations = st.number_input("Number of Simulations", min_value=1000, max_value=100000, step=1000, value=50000,
51
+ help="Set the number of simulations to run.")
52
+ rolling_window = st.number_input("Rolling Window", min_value=7, max_value=1000, step=10, value=250,
53
+ help="Set the rolling window size for tail dependence analysis.")
54
 
55
  if len(portfolio_tickers) != len(portfolio_weights):
56
  st.sidebar.error("The number of tickers must match the number of weights.")
57
 
 
58
  run_button = st.sidebar.button("Run Analysis")
59
 
60
  if run_button and len(portfolio_tickers) == len(portfolio_weights):
61
 
62
+ # Explanation of the Simulation and Copula Models
63
  st.markdown("## Simulating Market Drop Scenarios: Best, Worst, and Mean Cases")
64
+ st.markdown("This section explores how the portfolio performs under simulated market drop scenarios using copula models.")
 
 
 
 
 
 
 
65
 
66
+ with st.expander("Methodology", expanded=False):
67
+ st.markdown("""
68
+ **Step 1: Transforming Returns**
69
+ - We transform the returns to a uniform distribution using quantile transformation.
70
+ - This ensures that the data fits within the range required by the copula model.
 
 
 
71
 
72
+ **Step 2: Fitting the Copula Model**
73
+ - A multivariate Student-t copula is fitted to the transformed data.
74
+ - The copula model captures the dependencies between the asset returns.
 
 
 
 
 
 
 
75
 
76
+ **Step 3: Simulating Scenarios**
77
+ - We simulate numerous return scenarios using the fitted copula model to assess the portfolio's risk under various market conditions.
 
 
 
 
 
78
 
79
+ **Step 4: Portfolio Returns Calculation**
80
+ - For each identified scenario, we calculate the portfolio returns using a weighted sum of the individual asset returns.
 
 
 
81
 
82
+ **Step 5: Visualization**
83
+ - We visualize the simulated portfolio returns using histograms, CDFs, and KDEs to understand potential outcomes.
84
+ """)
 
 
 
 
 
 
85
 
86
  # Define the portfolio and allocation
87
  portfolio_allocation = dict(zip(portfolio_tickers, portfolio_weights))
 
107
  copula.fit(data_uniform.values)
108
 
109
  # Simulate scenarios
 
110
  simulated_uniform = copula.random(num_simulations)
111
  simulated_returns = pd.DataFrame(index=range(num_simulations), columns=data_uniform.columns)
112
 
 
225
 
226
  st.plotly_chart(fig_price)
227
 
 
228
  # Tail Dependence Analysis
229
  st.markdown("## Tail Dependence Analysis")
230
  st.markdown("""
231
  Tail dependence measures the likelihood of extreme returns occurring simultaneously across different stocks in the portfolio.
232
+ We use the Clayton copula to model the tail dependence. The parameter θ of the Clayton copula is related to the tail dependence by:
 
 
 
 
 
 
 
 
 
 
 
 
233
  """)
234
+
235
+ with st.expander("Tail Dependence Methodology", expanded=False):
236
+ st.latex(r"""
237
+ \lambda_{L} = 2^{1/\theta} - 1
238
+ """)
239
+ st.markdown("""
240
+ Where:
241
+ - λ1 is the lower tail dependence.
242
+ - θ is the parameter of the Clayton copula.
243
+ A higher λ1 value indicates a stronger relationship in the tails, meaning that extreme losses in one stock are more likely to coincide with extreme losses in another.
244
+ """)
245
 
246
  def to_uniform(column):
247
  n = len(column)
 
302
  """)
303
 
304
  # Rolling window analysis
 
305
  tail_parameters = []
306
 
307
+ for start in range(0, len(uniform_data) - rolling_window):
308
+ window_data = uniform_data.iloc[start:start + rolling_window]
309
 
310
  copula = Clayton()
311
  copula.fit(window_data.values)
 
315
 
316
  # Tail Dependence Over Time
317
  fig1 = go.Figure()
318
+ fig1.add_trace(go.Scatter(x=returns.index[rolling_window:], y=tail_parameters, mode='lines', name='Tail Dependence Parameter'))
319
  fig1.update_layout(
320
  title="Tail Dependence Over Time",
321
  xaxis_title="Date",
 
324
 
325
  st.plotly_chart(fig1)
326
 
327
+ # Hide the Streamlit style elements
328
  hide_streamlit_style = """
329
  <style>
330
  #MainMenu {visibility: hidden;}
331
  footer {visibility: hidden;}
332
  </style>
333
  """
334
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)