eagle0504 commited on
Commit
7e94170
1 Parent(s): 60697f7

apps updated

Browse files
Files changed (5) hide show
  1. app.py +47 -6
  2. pages/1_english_.py +1 -1
  3. pages/2_chinese_.py +1 -1
  4. utils/helper.py +1 -1
  5. utils/ui_helper.py +47 -32
app.py CHANGED
@@ -16,11 +16,7 @@ import streamlit as st
16
 
17
 
18
  def run():
19
- st.set_page_config(
20
- page_title="Momentum-Strategy",
21
- page_icon="💹",
22
- layout="wide"
23
- )
24
 
25
  st.write("# Welcome to the Momentum Strategy Simulator! 💹")
26
 
@@ -56,6 +52,51 @@ def run():
56
  """
57
  )
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  if __name__ == "__main__":
61
- run()
 
16
 
17
 
18
  def run():
19
+ st.set_page_config(page_title="Momentum-Strategy", page_icon="💹", layout="wide")
 
 
 
 
20
 
21
  st.write("# Welcome to the Momentum Strategy Simulator! 💹")
22
 
 
52
  """
53
  )
54
 
55
+ with st.expander("Reference (Expand/Collapse)"):
56
+ st.markdown(
57
+ f"""
58
+ # Factor Models and Mutual Fund Evaluation
59
+
60
+ ## Monthly Momentum Factor (MOM)
61
+
62
+ The Monthly Momentum Factor (MOM) can be calculated by subtracting the equal-weighted average of the lowest performing firms from the equal-weighted average of the highest performing firms, lagged one month (Carhart, 1997). A stock exhibits momentum if its prior 12-month average of returns is positive. Similar to the three-factor model, the momentum factor is defined by a self-financing portfolio of (long positive momentum) + (short negative momentum). Momentum strategies remain popular in financial markets, and financial analysts often incorporate the 52-week price high/low in their Buy/Sell recommendations.
63
+
64
+ ## Four-Factor Model
65
+
66
+ The four-factor model is commonly used for active management and mutual fund evaluation. Three commonly used methods to adjust a mutual fund's returns for risk are:
67
+
68
+ ### 1. Market Model:
69
+
70
+ $$
71
+ EXR_t = α^J + β_mkt * EXMKT_t + ε_t
72
+ $$
73
+
74
+ The intercept in this model is referred to as "Jensen's alpha".
75
+
76
+ ### 2. Fama–French Three-Factor Model:
77
+
78
+ $$
79
+ EXR_t = α^FF + β_mkt * EXMKT_t + β_HML * HML_t + β_SMB * SMB_t + ε_t
80
+ $$
81
+
82
+ The intercept in this model is referred to as the "three-factor alpha".
83
+
84
+ ### 3. Carhart Four-Factor Model:
85
+
86
+ $$
87
+ EXR_t = α^c + β_mkt * EXMKT_t + β_HML * HML_t + β_SMB * SMB_t + β_UMD * UMD_t + ε_t
88
+ $$
89
+
90
+ The intercept in this model is referred to as the "four-factor alpha".
91
+
92
+ `EXR_t` is the monthly return to the asset of concern in excess of the monthly t-bill rate. These models are used to adjust for risk by regressing the excess returns of the asset on an intercept (the alpha) and some factors on the right-hand side of the equation that attempt to control for market-wide risk factors. The right-hand side risk factors include the monthly return of the CRSP value-weighted index less the risk-free rate (`EXMKT_t`), monthly premium of the book-to-market factor (`HML_t`), monthly premium of the size factor (`SMB_t`), and the monthly premium on winners minus losers (`UMD_t`) from Fama-French (1993) and Carhart (1997).
93
+
94
+ A fund manager demonstrates forecasting ability when their fund has a positive and statistically significant alpha.
95
+
96
+ SMB is a zero-investment portfolio that is long on small capitalization (cap) stocks and short on big-cap stocks. Similarly, HML is a zero-investment portfolio that is long on high book-to-market (B/M) stocks and short on low B/M stocks, and UMD is a zero-cost portfolio that is long previous 12-month return winners and short previous 12-month loser stocks.
97
+ """
98
+ )
99
+
100
 
101
  if __name__ == "__main__":
102
+ run()
pages/1_english_.py CHANGED
@@ -3,4 +3,4 @@ from utils.helper import *
3
  from utils.ui_helper import *
4
 
5
  # run ui
6
- main_algo_trader()
 
3
  from utils.ui_helper import *
4
 
5
  # run ui
6
+ main_algo_trader()
pages/2_chinese_.py CHANGED
@@ -3,4 +3,4 @@ from utils.helper import *
3
  from utils.ui_helper import *
4
 
5
  # run ui
6
- main_algo_trader_chinese()
 
3
  from utils.ui_helper import *
4
 
5
  # run ui
6
+ main_algo_trader_chinese()
utils/helper.py CHANGED
@@ -74,4 +74,4 @@ def create_portfolio_and_calculate_returns(
74
  new_returns_data["portfolio_returns"] + 1
75
  ).cumprod()
76
 
77
- return new_returns_data
 
74
  new_returns_data["portfolio_returns"] + 1
75
  ).cumprod()
76
 
77
+ return new_returns_data
utils/ui_helper.py CHANGED
@@ -4,7 +4,8 @@ import streamlit as st
4
  import plotly.graph_objects as go
5
  import pandas as pd
6
  from utils.helper import *
7
-
 
8
  # english
9
  def main_algo_trader():
10
  # Front-end Design
@@ -25,9 +26,11 @@ def main_algo_trader():
25
  tickers = st.text_input(
26
  "Enter tickers (comma-separated):",
27
  "MSFT, AAPL, NVDA, GOOG, AMZN, META, LLY, AVGO, TSLA, JPM, V, WMT, UNH, MA, PG, HD, JNJ, ORCL, MRK, COST, ABBV, BAC, CRM, AMD, NFLX, ACN, ADBE, DIS, TMO, WFC, MCD, CSCO, ABT, QCOM, INTC, INTU, IBM, AMAT, CMCSA, AXP, PFE, NOW, AMGN, MU",
28
- )
29
  start_date = st.sidebar.date_input("Start date", pd.to_datetime("2001-01-01"))
30
- end_date = st.sidebar.date_input("End date", pd.to_datetime(datetime.now().strftime("%Y-%m-%d")))
 
 
31
  time_frame = st.sidebar.selectbox(
32
  "Select Time Frame:",
33
  [
@@ -36,7 +39,9 @@ def main_algo_trader():
36
  ],
37
  )
38
  top_n = st.sidebar.number_input("Top n stocks", min_value=1, value=3)
39
- height_of_graph = st.sidebar.number_input("Height of the plot", min_value=500, value=750)
 
 
40
 
41
  # Process inputs
42
  tickers_list = [ticker.strip() for ticker in tickers.split(",")]
@@ -69,8 +74,8 @@ def main_algo_trader():
69
  @st.cache_data
70
  def convert_df(df):
71
  # IMPORTANT: Cache the conversion to prevent computation on every rerun
72
- return df.to_csv().encode('utf-8')
73
-
74
  csv = convert_df(df)
75
 
76
  # Create plot
@@ -118,14 +123,18 @@ def main_algo_trader():
118
  portfolio_std = returns_data["portfolio_returns"].std()
119
 
120
  # Update title text with additional information
121
- if time_frame == '1mo':
122
  some_n_based_on_time_frame = 12
123
- in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
124
- in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
 
 
125
  else:
126
  some_n_based_on_time_frame = 4
127
- in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
128
- in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
 
 
129
  title_text = (
130
  f"Performance:<br>"
131
  f"Benchmark Sharpe Ratio = {benchmark_sharpe_ratio:.3f}, "
@@ -158,8 +167,8 @@ def main_algo_trader():
158
  st.download_button(
159
  label="Download data as CSV",
160
  data=csv,
161
- file_name=f'history_{end_date}.csv',
162
- mime='text/csv',
163
  )
164
 
165
 
@@ -183,9 +192,11 @@ def main_algo_trader_chinese():
183
  tickers = st.text_input(
184
  "使用英文键入输入股票代码(以逗号分隔):",
185
  "MSFT, AAPL, NVDA, GOOG, AMZN, META, LLY, AVGO, TSLA, JPM, V, WMT, UNH, MA, PG, HD, JNJ, ORCL, MRK, COST, ABBV, BAC, CRM, AMD, NFLX, ACN, ADBE, DIS, TMO, WFC, MCD, CSCO, ABT, QCOM, INTC, INTU, IBM, AMAT, CMCSA, AXP, PFE, NOW, AMGN, MU",
186
- )
187
  start_date = st.sidebar.date_input("开始日期", pd.to_datetime("2001-01-01"))
188
- end_date = st.sidebar.date_input("结束日期", pd.to_datetime(datetime.now().strftime("%Y-%m-%d")))
 
 
189
  time_frame = st.sidebar.selectbox(
190
  "选择时间框架:",
191
  [
@@ -227,8 +238,8 @@ def main_algo_trader_chinese():
227
  @st.cache_data
228
  def convert_df(df):
229
  # IMPORTANT: Cache the conversion to prevent computation on every rerun
230
- return df.to_csv().encode('utf-8')
231
-
232
  csv = convert_df(df)
233
 
234
  # Create plot
@@ -276,23 +287,27 @@ def main_algo_trader_chinese():
276
  portfolio_std = returns_data["portfolio_returns"].std()
277
 
278
  # Update title text with additional information
279
- if time_frame == '1mo':
280
  some_n_based_on_time_frame = 12
281
- in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
282
- in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
 
 
283
  else:
284
  some_n_based_on_time_frame = 4
285
- in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
286
- in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
 
 
287
  title_text = (
288
- f"Performance:<br>"
289
- f"Benchmark Sharpe Ratio = {benchmark_sharpe_ratio:.3f}, "
290
- f"Portfolio Sharpe Ratio = {portfolio_sharpe_ratio:.3f}, "
291
- f"based on time frame: {time_frame}<br>"
292
- f"Benchmark => Mean: {benchmark_mean:.4f}, Std: {benchmark_std:.4f}; "
293
- f"Portfolio => Mean: {portfolio_mean:.4f}, Std: {portfolio_std:.4f}<br>"
294
  f"---<br>"
295
- f"This may or may not be a small number, let's check: <br>"
296
  f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame})={in_a_year}, <br>"
297
  f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame}*50)={in_50_years}."
298
  )
@@ -316,6 +331,6 @@ def main_algo_trader_chinese():
316
  st.download_button(
317
  label="Download data as CSV",
318
  data=csv,
319
- file_name=f'history_{end_date}.csv',
320
- mime='text/csv',
321
- )
 
4
  import plotly.graph_objects as go
5
  import pandas as pd
6
  from utils.helper import *
7
+
8
+
9
  # english
10
  def main_algo_trader():
11
  # Front-end Design
 
26
  tickers = st.text_input(
27
  "Enter tickers (comma-separated):",
28
  "MSFT, AAPL, NVDA, GOOG, AMZN, META, LLY, AVGO, TSLA, JPM, V, WMT, UNH, MA, PG, HD, JNJ, ORCL, MRK, COST, ABBV, BAC, CRM, AMD, NFLX, ACN, ADBE, DIS, TMO, WFC, MCD, CSCO, ABT, QCOM, INTC, INTU, IBM, AMAT, CMCSA, AXP, PFE, NOW, AMGN, MU",
29
+ )
30
  start_date = st.sidebar.date_input("Start date", pd.to_datetime("2001-01-01"))
31
+ end_date = st.sidebar.date_input(
32
+ "End date", pd.to_datetime(datetime.now().strftime("%Y-%m-%d"))
33
+ )
34
  time_frame = st.sidebar.selectbox(
35
  "Select Time Frame:",
36
  [
 
39
  ],
40
  )
41
  top_n = st.sidebar.number_input("Top n stocks", min_value=1, value=3)
42
+ height_of_graph = st.sidebar.number_input(
43
+ "Height of the plot", min_value=500, value=750
44
+ )
45
 
46
  # Process inputs
47
  tickers_list = [ticker.strip() for ticker in tickers.split(",")]
 
74
  @st.cache_data
75
  def convert_df(df):
76
  # IMPORTANT: Cache the conversion to prevent computation on every rerun
77
+ return df.to_csv().encode("utf-8")
78
+
79
  csv = convert_df(df)
80
 
81
  # Create plot
 
123
  portfolio_std = returns_data["portfolio_returns"].std()
124
 
125
  # Update title text with additional information
126
+ if time_frame == "1mo":
127
  some_n_based_on_time_frame = 12
128
+ in_a_year = 1000 * (1 + portfolio_mean) ** (some_n_based_on_time_frame)
129
+ in_50_years = 1000 * (1 + portfolio_mean) ** (
130
+ some_n_based_on_time_frame * 50
131
+ )
132
  else:
133
  some_n_based_on_time_frame = 4
134
+ in_a_year = 1000 * (1 + portfolio_mean) ** (some_n_based_on_time_frame)
135
+ in_50_years = 1000 * (1 + portfolio_mean) ** (
136
+ some_n_based_on_time_frame * 50
137
+ )
138
  title_text = (
139
  f"Performance:<br>"
140
  f"Benchmark Sharpe Ratio = {benchmark_sharpe_ratio:.3f}, "
 
167
  st.download_button(
168
  label="Download data as CSV",
169
  data=csv,
170
+ file_name=f"history_{end_date}.csv",
171
+ mime="text/csv",
172
  )
173
 
174
 
 
192
  tickers = st.text_input(
193
  "使用英文键入输入股票代码(以逗号分隔):",
194
  "MSFT, AAPL, NVDA, GOOG, AMZN, META, LLY, AVGO, TSLA, JPM, V, WMT, UNH, MA, PG, HD, JNJ, ORCL, MRK, COST, ABBV, BAC, CRM, AMD, NFLX, ACN, ADBE, DIS, TMO, WFC, MCD, CSCO, ABT, QCOM, INTC, INTU, IBM, AMAT, CMCSA, AXP, PFE, NOW, AMGN, MU",
195
+ )
196
  start_date = st.sidebar.date_input("开始日期", pd.to_datetime("2001-01-01"))
197
+ end_date = st.sidebar.date_input(
198
+ "结束日期", pd.to_datetime(datetime.now().strftime("%Y-%m-%d"))
199
+ )
200
  time_frame = st.sidebar.selectbox(
201
  "选择时间框架:",
202
  [
 
238
  @st.cache_data
239
  def convert_df(df):
240
  # IMPORTANT: Cache the conversion to prevent computation on every rerun
241
+ return df.to_csv().encode("utf-8")
242
+
243
  csv = convert_df(df)
244
 
245
  # Create plot
 
287
  portfolio_std = returns_data["portfolio_returns"].std()
288
 
289
  # Update title text with additional information
290
+ if time_frame == "1mo":
291
  some_n_based_on_time_frame = 12
292
+ in_a_year = 1000 * (1 + portfolio_mean) ** (some_n_based_on_time_frame)
293
+ in_50_years = 1000 * (1 + portfolio_mean) ** (
294
+ some_n_based_on_time_frame * 50
295
+ )
296
  else:
297
  some_n_based_on_time_frame = 4
298
+ in_a_year = 1000 * (1 + portfolio_mean) ** (some_n_based_on_time_frame)
299
+ in_50_years = 1000 * (1 + portfolio_mean) ** (
300
+ some_n_based_on_time_frame * 50
301
+ )
302
  title_text = (
303
+ f"业绩:<br>"
304
+ f"标杆回报风险比 = {benchmark_sharpe_ratio:.3f}, "
305
+ f"投资组合回报风险比 = {portfolio_sharpe_ratio:.3f}, "
306
+ f"交易窗口: {time_frame}<br>"
307
+ f"标杆 => Mean: {benchmark_mean:.4f}, Std: {benchmark_std:.4f}; "
308
+ f"投资组合 => Mean: {portfolio_mean:.4f}, Std: {portfolio_std:.4f}<br>"
309
  f"---<br>"
310
+ f"这个数字如何理解,我们以1000块钱计算以下: <br>"
311
  f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame})={in_a_year}, <br>"
312
  f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame}*50)={in_50_years}."
313
  )
 
331
  st.download_button(
332
  label="Download data as CSV",
333
  data=csv,
334
+ file_name=f"history_{end_date}.csv",
335
+ mime="text/csv",
336
+ )