Spaces:
Sleeping
Sleeping
Bhanu Prasanna
commited on
Commit
•
8c08ea9
1
Parent(s):
7db6bc2
Update
Browse files- main.py +111 -24
- utilities/py/__pycache__/summary_tables.cpython-310.pyc +0 -0
- utilities/py/sharpe.py +0 -1
- utilities/py/summary_tables.py +114 -3
main.py
CHANGED
@@ -11,6 +11,7 @@ from utilities.py import summary_tables
|
|
11 |
from pypfopt import EfficientFrontier
|
12 |
from pypfopt import risk_models
|
13 |
from pypfopt import expected_returns
|
|
|
14 |
|
15 |
import plotly.express as px
|
16 |
import plotly.graph_objects as go
|
@@ -35,16 +36,26 @@ streamlit_company_list_input = st.multiselect(
|
|
35 |
"Select Multiple Companies", company_name, default=None
|
36 |
)
|
37 |
|
38 |
-
|
39 |
-
"
|
40 |
(
|
41 |
-
"
|
42 |
-
"
|
43 |
-
"Minimum Volatility",
|
44 |
-
"Efficient Return",
|
45 |
),
|
46 |
)
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
company_name_to_symbol = [name_to_symbol_dict[i] for i in streamlit_company_list_input]
|
49 |
|
50 |
number_of_symbols = len(company_name_to_symbol)
|
@@ -90,23 +101,39 @@ if number_of_symbols > 1:
|
|
90 |
if number_of_symbols > 1:
|
91 |
company_stock_returns_data = company_data.pct_change().dropna()
|
92 |
|
93 |
-
mu =
|
94 |
-
S =
|
|
|
|
|
95 |
|
96 |
-
|
|
|
|
|
97 |
|
98 |
-
|
99 |
-
ef.max_sharpe()
|
100 |
-
elif optimization_methods == "Minimum Volatility":
|
101 |
-
ef.min_volatility()
|
102 |
-
elif optimization_methods == "Efficient Risk":
|
103 |
-
ef.efficient_risk(0.5)
|
104 |
-
else:
|
105 |
-
ef.efficient_return(0.05)
|
106 |
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
|
111 |
company_asset_weights.columns = ["Ticker", "Allocation"]
|
112 |
|
@@ -139,7 +166,15 @@ if number_of_symbols > 1:
|
|
139 |
|
140 |
st_portfolio_performance.columns = ["Metrics", "Summary"]
|
141 |
|
142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
|
144 |
st.dataframe(st_portfolio_performance, use_container_width=True)
|
145 |
|
@@ -155,12 +190,64 @@ if number_of_symbols > 1:
|
|
155 |
|
156 |
cumulative_returns = (portfolio_returns + 1).cumprod() * initial_investment
|
157 |
|
158 |
-
tab1, tab2 = st.tabs(["Plots", "
|
159 |
|
160 |
with tab1:
|
|
|
161 |
plots.plot_annual_returns(annual_portfolio_returns)
|
162 |
plots.plot_cummulative_returns(cumulative_returns)
|
163 |
|
164 |
with tab2:
|
165 |
-
|
166 |
-
summary_tables.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
from pypfopt import EfficientFrontier
|
12 |
from pypfopt import risk_models
|
13 |
from pypfopt import expected_returns
|
14 |
+
from pypfopt import HRPOpt, hierarchical_portfolio
|
15 |
|
16 |
import plotly.express as px
|
17 |
import plotly.graph_objects as go
|
|
|
36 |
"Select Multiple Companies", company_name, default=None
|
37 |
)
|
38 |
|
39 |
+
optimisation_method = st.selectbox(
|
40 |
+
"Choose an optimization method accordingly",
|
41 |
(
|
42 |
+
"Efficient Frontier",
|
43 |
+
"Hierarchical Risk Parity",
|
|
|
|
|
44 |
),
|
45 |
)
|
46 |
|
47 |
+
parameter_for_optimisation = 0
|
48 |
+
if optimisation_method == "Efficient Frontier":
|
49 |
+
parameter_for_optimisation = st.selectbox(
|
50 |
+
"Choose an optimization parameter accordingly",
|
51 |
+
(
|
52 |
+
"Maximum Sharpe Ratio",
|
53 |
+
"Efficient Risk",
|
54 |
+
"Minimum Volatility",
|
55 |
+
"Efficient Return",
|
56 |
+
),
|
57 |
+
)
|
58 |
+
|
59 |
company_name_to_symbol = [name_to_symbol_dict[i] for i in streamlit_company_list_input]
|
60 |
|
61 |
number_of_symbols = len(company_name_to_symbol)
|
|
|
101 |
if number_of_symbols > 1:
|
102 |
company_stock_returns_data = company_data.pct_change().dropna()
|
103 |
|
104 |
+
mu = 0
|
105 |
+
S = 0
|
106 |
+
ef = 0
|
107 |
+
company_asset_weights = 0
|
108 |
|
109 |
+
if optimisation_method == "Efficient Frontier":
|
110 |
+
mu = expected_returns.mean_historical_return(company_data)
|
111 |
+
S = risk_models.sample_cov(company_data)
|
112 |
|
113 |
+
ef = EfficientFrontier(mu, S)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
+
if parameter_for_optimisation == "Maximum Sharpe Raio":
|
116 |
+
ef.max_sharpe()
|
117 |
+
elif parameter_for_optimisation == "Minimum Volatility":
|
118 |
+
ef.min_volatility()
|
119 |
+
elif parameter_for_optimisation == "Efficient Risk":
|
120 |
+
ef.efficient_risk(0.5)
|
121 |
+
else:
|
122 |
+
ef.efficient_return(0.05)
|
123 |
+
|
124 |
+
company_asset_weights = pd.DataFrame.from_dict(
|
125 |
+
ef.clean_weights(), orient="index"
|
126 |
+
).reset_index()
|
127 |
+
elif optimisation_method == "Hierarchical Risk Parity":
|
128 |
+
mu = expected_returns.returns_from_prices(company_data)
|
129 |
+
S = risk_models.sample_cov(company_data)
|
130 |
+
|
131 |
+
ef = HRPOpt(mu, S)
|
132 |
+
|
133 |
+
company_asset_weights = ef.optimize()
|
134 |
+
company_asset_weights = pd.DataFrame.from_dict(
|
135 |
+
company_asset_weights, orient="index", columns=["Weight"]
|
136 |
+
).reset_index()
|
137 |
|
138 |
company_asset_weights.columns = ["Ticker", "Allocation"]
|
139 |
|
|
|
166 |
|
167 |
st_portfolio_performance.columns = ["Metrics", "Summary"]
|
168 |
|
169 |
+
if optimisation_method == "Efficient Frontier":
|
170 |
+
st.write(
|
171 |
+
"Optimization Method - ",
|
172 |
+
optimisation_method,
|
173 |
+
"---- Parameter - ",
|
174 |
+
parameter_for_optimisation,
|
175 |
+
)
|
176 |
+
else:
|
177 |
+
st.write("Optimization Method - ", optimisation_method)
|
178 |
|
179 |
st.dataframe(st_portfolio_performance, use_container_width=True)
|
180 |
|
|
|
190 |
|
191 |
cumulative_returns = (portfolio_returns + 1).cumprod() * initial_investment
|
192 |
|
193 |
+
tab1, tab2, tab3 = st.tabs(["Plots", "Annual Returns", "Montly Returns"])
|
194 |
|
195 |
with tab1:
|
196 |
+
|
197 |
plots.plot_annual_returns(annual_portfolio_returns)
|
198 |
plots.plot_cummulative_returns(cumulative_returns)
|
199 |
|
200 |
with tab2:
|
201 |
+
|
202 |
+
annual_portfolio_returns = summary_tables.annual_returns_dataframe(
|
203 |
+
annual_portfolio_returns
|
204 |
+
)
|
205 |
+
annual_cumulative_returns = (
|
206 |
+
summary_tables.annual_cumulative_returns_dataframe(cumulative_returns)
|
207 |
+
)
|
208 |
+
annual_stock_returns = summary_tables.company_wise_annual_return(
|
209 |
+
company_stock_returns_data, company_asset_weights
|
210 |
+
)
|
211 |
+
|
212 |
+
merged_annual_returns_data = pd.merge(
|
213 |
+
annual_portfolio_returns,
|
214 |
+
annual_cumulative_returns,
|
215 |
+
on="Year",
|
216 |
+
suffixes=("_portfolio", "_cumulative"),
|
217 |
+
)
|
218 |
+
|
219 |
+
merged_annual_returns_data = pd.merge(
|
220 |
+
merged_annual_returns_data, annual_stock_returns, on="Year"
|
221 |
+
)
|
222 |
+
|
223 |
+
st.write("Annual Returns")
|
224 |
+
st.dataframe(merged_annual_returns_data, use_container_width=True)
|
225 |
+
|
226 |
+
with tab3:
|
227 |
+
|
228 |
+
monthly_portfolio_return = summary_tables.monthly_returns_dataframe(
|
229 |
+
portfolio_returns
|
230 |
+
)
|
231 |
+
monthly_stock_return = summary_tables.company_wise_monthly_return(
|
232 |
+
company_stock_returns_data, company_asset_weights
|
233 |
+
)
|
234 |
+
monthly_cumulative_returns = (
|
235 |
+
summary_tables.monthly_cumulative_returns_dataframe(cumulative_returns)
|
236 |
+
)
|
237 |
+
|
238 |
+
merged_monthly_returns_data = pd.merge(
|
239 |
+
monthly_portfolio_return,
|
240 |
+
monthly_cumulative_returns,
|
241 |
+
on=["Year", "Month"],
|
242 |
+
how="inner",
|
243 |
+
)
|
244 |
+
|
245 |
+
merged_monthly_returns_data = pd.merge(
|
246 |
+
merged_monthly_returns_data,
|
247 |
+
monthly_stock_return,
|
248 |
+
on=["Year", "Month"],
|
249 |
+
how="inner",
|
250 |
+
)
|
251 |
+
|
252 |
+
st.write("Montly Return")
|
253 |
+
st.dataframe(merged_monthly_returns_data)
|
utilities/py/__pycache__/summary_tables.cpython-310.pyc
CHANGED
Binary files a/utilities/py/__pycache__/summary_tables.cpython-310.pyc and b/utilities/py/__pycache__/summary_tables.cpython-310.pyc differ
|
|
utilities/py/sharpe.py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
import numpy as np
|
|
|
|
utilities/py/summary_tables.py
CHANGED
@@ -13,10 +13,10 @@ def annual_returns_dataframe(annual_portfolio_returns):
|
|
13 |
|
14 |
annual_portfolio_returns["Year"] = annual_portfolio_returns.Year.dt.year.astype(str)
|
15 |
|
16 |
-
|
17 |
|
18 |
|
19 |
-
def
|
20 |
|
21 |
cumulative_returns = cumulative_returns.to_frame().reset_index()
|
22 |
|
@@ -28,4 +28,115 @@ def cumulative_returns_dataframe(cumulative_returns):
|
|
28 |
cumulative_returns.groupby("Year").tail(1).reset_index().drop("index", axis=1)
|
29 |
)
|
30 |
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
annual_portfolio_returns["Year"] = annual_portfolio_returns.Year.dt.year.astype(str)
|
15 |
|
16 |
+
return annual_portfolio_returns
|
17 |
|
18 |
|
19 |
+
def annual_cumulative_returns_dataframe(cumulative_returns):
|
20 |
|
21 |
cumulative_returns = cumulative_returns.to_frame().reset_index()
|
22 |
|
|
|
28 |
cumulative_returns.groupby("Year").tail(1).reset_index().drop("index", axis=1)
|
29 |
)
|
30 |
|
31 |
+
return cumulative_returns
|
32 |
+
|
33 |
+
|
34 |
+
def company_wise_annual_return(company_stock_returns_data, company_asset_weights):
|
35 |
+
# Create an empty DataFrame to store annual returns for each stock
|
36 |
+
annual_stock_returns = pd.DataFrame(
|
37 |
+
index=company_stock_returns_data.index.year.unique(),
|
38 |
+
columns=company_asset_weights["Ticker"],
|
39 |
+
)
|
40 |
+
|
41 |
+
# Iterate over each year
|
42 |
+
for year in annual_stock_returns.index:
|
43 |
+
# Filter returns data for the current year
|
44 |
+
year_returns = company_stock_returns_data.loc[
|
45 |
+
company_stock_returns_data.index.year == year
|
46 |
+
]
|
47 |
+
# Iterate over each stock
|
48 |
+
for ticker, weight in zip(
|
49 |
+
company_asset_weights["Ticker"], company_asset_weights["Allocation"]
|
50 |
+
):
|
51 |
+
# Calculate the weighted sum of returns for the current stock in the current year
|
52 |
+
weighted_sum_returns = (year_returns[ticker] * weight).sum() * 100
|
53 |
+
# Store the weighted average return for the current stock in the current year
|
54 |
+
annual_stock_returns.loc[year, ticker] = weighted_sum_returns
|
55 |
+
|
56 |
+
# Display annual returns for each stock
|
57 |
+
annual_stock_returns.reset_index(inplace=True)
|
58 |
+
annual_stock_returns["Date"] = annual_stock_returns["Date"].astype(str)
|
59 |
+
annual_stock_returns.rename(columns={"Date": "Year"}, inplace=True)
|
60 |
+
|
61 |
+
return annual_stock_returns
|
62 |
+
|
63 |
+
|
64 |
+
def company_wise_monthly_return(company_stock_returns_data, company_asset_weights):
|
65 |
+
# Resample daily returns to monthly returns for each stock
|
66 |
+
monthly_stock_returns = company_stock_returns_data.resample("M").mean()
|
67 |
+
|
68 |
+
# Iterate over each stock
|
69 |
+
for ticker, weight in zip(
|
70 |
+
company_asset_weights["Ticker"], company_asset_weights["Allocation"]
|
71 |
+
):
|
72 |
+
# Calculate the weighted monthly returns for the current stock
|
73 |
+
weighted_monthly_returns = monthly_stock_returns[ticker] * weight
|
74 |
+
# Fill missing values with 0
|
75 |
+
weighted_monthly_returns.fillna(0, inplace=True)
|
76 |
+
# Store the weighted monthly returns in the DataFrame
|
77 |
+
monthly_stock_returns[ticker] = weighted_monthly_returns
|
78 |
+
|
79 |
+
# Reset the index and add new columns for year and month
|
80 |
+
monthly_stock_returns.reset_index(inplace=True)
|
81 |
+
monthly_stock_returns["Year"] = monthly_stock_returns["Date"].dt.year.astype(str)
|
82 |
+
monthly_stock_returns["Month"] = monthly_stock_returns["Date"].dt.month.astype(str)
|
83 |
+
|
84 |
+
# Rearrange the columns
|
85 |
+
columns_order = ["Year", "Month"] + [
|
86 |
+
col for col in monthly_stock_returns.columns if col not in ["Year", "Month"]
|
87 |
+
]
|
88 |
+
monthly_stock_returns = monthly_stock_returns[columns_order]
|
89 |
+
|
90 |
+
# Drop the original date index column
|
91 |
+
monthly_stock_returns.drop(columns=["Date"], inplace=True)
|
92 |
+
|
93 |
+
# Display monthly returns for each stock
|
94 |
+
# st.write("Monthly Returns for Individual Stocks:")
|
95 |
+
# st.dataframe(monthly_stock_returns, use_container_width=True)
|
96 |
+
|
97 |
+
return monthly_stock_returns
|
98 |
+
|
99 |
+
|
100 |
+
def monthly_returns_dataframe(portfolio_returns):
|
101 |
+
monthly_portfolio_returns = (
|
102 |
+
(portfolio_returns.resample("M").mean() * 100).to_frame().reset_index()
|
103 |
+
)
|
104 |
+
|
105 |
+
monthly_portfolio_returns.columns = ["Date", "Return"]
|
106 |
+
|
107 |
+
monthly_portfolio_returns["Year"] = monthly_portfolio_returns.Date.dt.year.astype(
|
108 |
+
str
|
109 |
+
)
|
110 |
+
monthly_portfolio_returns["Month"] = monthly_portfolio_returns.Date.dt.month.astype(
|
111 |
+
str
|
112 |
+
)
|
113 |
+
|
114 |
+
monthly_portfolio_returns.drop(columns=["Date"], inplace=True)
|
115 |
+
|
116 |
+
monthly_portfolio_returns = monthly_portfolio_returns[["Year", "Month", "Return"]]
|
117 |
+
|
118 |
+
return monthly_portfolio_returns
|
119 |
+
|
120 |
+
|
121 |
+
def monthly_cumulative_returns_dataframe(cumulative_returns):
|
122 |
+
|
123 |
+
monthly_cumulative_returns = (
|
124 |
+
cumulative_returns.resample("M").last().to_frame().reset_index()
|
125 |
+
)
|
126 |
+
|
127 |
+
monthly_cumulative_returns.columns = ["Date", "Balance"]
|
128 |
+
|
129 |
+
monthly_cumulative_returns["Year"] = monthly_cumulative_returns.Date.dt.year.astype(
|
130 |
+
str
|
131 |
+
)
|
132 |
+
monthly_cumulative_returns["Month"] = (
|
133 |
+
monthly_cumulative_returns.Date.dt.month.astype(str)
|
134 |
+
)
|
135 |
+
|
136 |
+
monthly_cumulative_returns.drop(columns=["Date"], inplace=True)
|
137 |
+
|
138 |
+
monthly_cumulative_returns = monthly_cumulative_returns[
|
139 |
+
["Year", "Month", "Balance"]
|
140 |
+
]
|
141 |
+
|
142 |
+
return monthly_cumulative_returns
|