eagle0504 commited on
Commit
68361fe
1 Parent(s): 69d3198

Create ui_helper.py

Browse files
Files changed (1) hide show
  1. utils/ui_helper.py +141 -0
utils/ui_helper.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import streamlit as st
3
+ import plotly.graph_objects as go
4
+ import pandas as pd
5
+ from helpers.app_helper_algotrader import *
6
+
7
+
8
+ def main_algo_trader():
9
+ st.write("# Welcome to Algorithmic Trading! A Toy Implementation👋")
10
+ st.sidebar.success("Select a session from the menu of content.")
11
+
12
+ st.markdown(
13
+ r"""
14
+ The following app is a simple demonstration of the growth stock strategy. For simplicity, we assume our research team hand over a pool of stocks. Amongst the pool of stocks, we can do the following:
15
+ - use `yfinance` library to download stock data live (for the sake of speed, please start with time frame "1mo");
16
+ - every period (time frame is a tuning parameter), we balance our portfolio (equal weight) by holding the top n stocks (n can be top quintile/quartile of stocks);
17
+ """
18
+ )
19
+
20
+ # Main inputs
21
+ tickers = st.text_input(
22
+ "Enter tickers (comma-separated):",
23
+ "AXP, AMGN, AAPL, BA, CAT, CSCO, CVX, GS, HD, HON, IBM, INTC, JNJ, KO, JPM, MCD, MMM, MRK, MSFT, NKE, PG, TRV, UNH, CRM, VZ, V, WBA, WMT, DIS, DOW, XOM, WFC, MA, COST, AVGO, ADBE, C, NFLX, PYPL, TSLA, NVDA",
24
+ )
25
+ start_date = st.date_input("Start date", pd.to_datetime("2001-01-01"))
26
+ end_date = st.date_input("End date", pd.to_datetime("2023-12-31"))
27
+ time_frame = st.selectbox(
28
+ "Select Time Frame:",
29
+ [
30
+ "1mo",
31
+ "3mo",
32
+ ],
33
+ )
34
+ top_n = st.number_input("Top n stocks", min_value=1, value=3)
35
+
36
+ # Process inputs
37
+ tickers_list = [ticker.strip() for ticker in tickers.split(",")]
38
+
39
+ # Run analysis on button click
40
+ if st.button("Run Analysis"):
41
+ with st.spinner("Downloading data and calculating returns..."):
42
+ stock_data = download_stock_data(
43
+ tickers_list,
44
+ start_date.strftime("%Y-%m-%d"),
45
+ end_date.strftime("%Y-%m-%d"),
46
+ w=time_frame,
47
+ )
48
+ returns_data = create_portfolio_and_calculate_returns(stock_data, top_n)
49
+ benchmark_sharpe_ratio = (
50
+ returns_data["benchmark"].mean() / returns_data["benchmark"].std()
51
+ )
52
+ portfolio_sharpe_ratio = (
53
+ returns_data["portfolio_returns"].mean()
54
+ / returns_data["portfolio_returns"].std()
55
+ )
56
+
57
+ # Data for plotting
58
+ df = returns_data[
59
+ ["rolling_benchmark", "rolling_portfolio_returns", "portfolio_history"]
60
+ ]
61
+ df.index = pd.to_datetime(df.index, unit="ms")
62
+
63
+ # Create plot
64
+ fig = go.Figure()
65
+ fig.add_trace(
66
+ go.Scatter(
67
+ x=df.index,
68
+ y=df["rolling_benchmark"],
69
+ mode="lines",
70
+ name="Rolling Benchmark",
71
+ )
72
+ )
73
+ fig.add_trace(
74
+ go.Scatter(
75
+ x=df.index,
76
+ y=df["rolling_portfolio_returns"],
77
+ mode="lines",
78
+ name="Rolling Portfolio Returns",
79
+ )
80
+ )
81
+
82
+ for date, stocks in df["portfolio_history"].items():
83
+ fig.add_shape(
84
+ type="line",
85
+ x0=date,
86
+ y0=0,
87
+ x1=date,
88
+ y1=0,
89
+ line=dict(color="RoyalBlue", width=1),
90
+ )
91
+ fig.add_annotation(
92
+ x=date,
93
+ y=0.5,
94
+ text=str(stocks),
95
+ showarrow=False,
96
+ yshift=10,
97
+ textangle=-90,
98
+ font=dict(size=15), # You can adjust the size as needed
99
+ )
100
+
101
+ # Calculate means and standard deviations
102
+ benchmark_mean = returns_data["benchmark"].mean()
103
+ benchmark_std = returns_data["benchmark"].std()
104
+ portfolio_mean = returns_data["portfolio_returns"].mean()
105
+ portfolio_std = returns_data["portfolio_returns"].std()
106
+
107
+ # Update title text with additional information
108
+ if time_frame == '1mo':
109
+ some_n_based_on_time_frame = 12
110
+ in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
111
+ in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
112
+ else:
113
+ some_n_based_on_time_frame = 4
114
+ in_a_year = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame)
115
+ in_50_years = 1000*(1+portfolio_mean)**(some_n_based_on_time_frame*50)
116
+ title_text = (
117
+ f"Performance:<br>"
118
+ f"Benchmark Sharpe Ratio = {benchmark_sharpe_ratio:.3f}, "
119
+ f"Portfolio Sharpe Ratio = {portfolio_sharpe_ratio:.3f}, "
120
+ f"based on time frame: {time_frame}<br>"
121
+ f"Benchmark => Mean: {benchmark_mean:.4f}, Std: {benchmark_std:.4f}; "
122
+ f"Portfolio => Mean: {portfolio_mean:.4f}, Std: {portfolio_std:.4f}<br>"
123
+ f"---<br>"
124
+ f"This may or may not be a small number, let's check: <br>"
125
+ f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame})={in_a_year}, <br>"
126
+ f"$1,000*(1+{portfolio_mean:.4f})^({some_n_based_on_time_frame}*50)={in_50_years}."
127
+ )
128
+ curr_max_num = max(
129
+ df.rolling_benchmark.max(), df.rolling_portfolio_returns.max()
130
+ )
131
+ fig.update_layout(
132
+ title=title_text,
133
+ xaxis_title="Date",
134
+ yaxis_title="Value",
135
+ yaxis=dict(range=[0, curr_max_num * 1.1]),
136
+ legend=dict(
137
+ orientation="h", x=0.5, y=-0.4, xanchor="center", yanchor="bottom"
138
+ ),
139
+ )
140
+
141
+ st.plotly_chart(fig, use_container_width=True)