vumichien commited on
Commit
dde01d0
·
1 Parent(s): d4a74f7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -0
app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import yfinance as yf
3
+ from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
4
+ from pypfopt import EfficientFrontier
5
+ from pypfopt import risk_models
6
+ from pypfopt import expected_returns
7
+ from pypfopt import plotting
8
+ import copy
9
+ import numpy as np
10
+ import pandas as pd
11
+ import plotly.express as px
12
+ import matplotlib.pyplot as plt
13
+ from datetime import datetime
14
+ import datetime
15
+
16
+ def plot_cum_returns(data, title):
17
+ daily_cum_returns = 1 + data.dropna().pct_change()
18
+ daily_cum_returns = daily_cum_returns.cumprod()*100
19
+ fig = px.line(daily_cum_returns, title=title)
20
+ return fig
21
+
22
+ def plot_efficient_frontier_and_max_sharpe(mu, S):
23
+ # Optimize portfolio for max Sharpe ratio and plot it out with efficient frontier curve
24
+ ef = EfficientFrontier(mu, S)
25
+ fig, ax = plt.subplots(figsize=(6,4))
26
+ ef_max_sharpe = copy.deepcopy(ef)
27
+ plotting.plot_efficient_frontier(ef, ax=ax, show_assets=False)
28
+ # Find the max sharpe portfolio
29
+ ef_max_sharpe.max_sharpe(risk_free_rate=0.02)
30
+ ret_tangent, std_tangent, _ = ef_max_sharpe.portfolio_performance()
31
+ ax.scatter(std_tangent, ret_tangent, marker="*", s=100, c="r", label="Max Sharpe")
32
+ # Generate random portfolios with random weights
33
+ n_samples = 1000
34
+ w = np.random.dirichlet(np.ones(ef.n_assets), n_samples)
35
+ rets = w.dot(ef.expected_returns)
36
+ stds = np.sqrt(np.diag(w @ ef.cov_matrix @ w.T))
37
+ sharpes = rets / stds
38
+ ax.scatter(stds, rets, marker=".", c=sharpes, cmap="viridis_r")
39
+ # Output
40
+ ax.legend()
41
+ return fig
42
+
43
+ def output_results(start_date, end_date, tickers_string):
44
+ tickers = tickers_string.split(',')
45
+
46
+ # Get Stock Prices
47
+ stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
48
+
49
+ # Plot Individual Stock Prices
50
+ fig_indiv_prices = px.line(stocks_df, title='Giá cổ phiếu riêng lẻ')
51
+
52
+ # Plot Individual Cumulative Returns
53
+ fig_cum_returns = plot_cum_returns(stocks_df, 'Lợi nhuận tích lũy của từng cổ phiếu bắt đầu từ 100 USD')
54
+
55
+ # Calculatge and Plot Correlation Matrix between Stocks
56
+ corr_df = stocks_df.corr().round(2)
57
+ fig_corr = px.imshow(corr_df, text_auto=True, title = 'Tương quan giữa các cổ phiếu')
58
+
59
+ # Calculate expected returns and sample covariance matrix for portfolio optimization later
60
+ mu = expected_returns.mean_historical_return(stocks_df)
61
+ S = risk_models.sample_cov(stocks_df)
62
+
63
+ # Plot efficient frontier curve
64
+ fig_efficient_frontier = plot_efficient_frontier_and_max_sharpe(mu, S)
65
+
66
+ # Get optimized weights
67
+ ef = EfficientFrontier(mu, S)
68
+ ef.max_sharpe(risk_free_rate=0.04)
69
+ weights = ef.clean_weights()
70
+ expected_annual_return, annual_volatility, sharpe_ratio = ef.portfolio_performance()
71
+
72
+ expected_annual_return, annual_volatility, sharpe_ratio = '{}%'.format((expected_annual_return*100).round(2)), \
73
+ '{}%'.format((annual_volatility*100).round(2)), \
74
+ '{}%'.format((sharpe_ratio*100).round(2))
75
+
76
+ weights_df = pd.DataFrame.from_dict(weights, orient = 'index')
77
+ weights_df = weights_df.reset_index()
78
+ weights_df.columns = ['Mã chứng khoán', 'Trọng số']
79
+
80
+ # Calculate returns of portfolio with optimized weights
81
+ stocks_df['Danh mục đầu tư được tối ưu hóa'] = 0
82
+ for ticker, weight in weights.items():
83
+ stocks_df['Danh mục đầu tư được tối ưu hóa'] += stocks_df[ticker]*weight
84
+
85
+ # Plot Cumulative Returns of Optimized Portfolio
86
+ fig_cum_returns_optimized = plot_cum_returns(stocks_df['Danh mục đầu tư được tối ưu hóa'], 'Lợi nhuận tích lũy của từng cổ phiếu bắt đầu từ 100 USD')
87
+
88
+ return fig_cum_returns_optimized, weights_df, fig_efficient_frontier, fig_corr, \
89
+ expected_annual_return, annual_volatility, sharpe_ratio, fig_indiv_prices, fig_cum_returns
90
+
91
+
92
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
93
+ with gr.Row():
94
+ gr.HTML("<h1>Trình tối ưu hóa danh mục đầu tư chứng khoán</h1>")
95
+
96
+ with gr.Row():
97
+ start_date = gr.Textbox("2013-01-01", label="Ngày bắt đầu")
98
+ end_date = gr.Textbox(datetime.datetime.now().date(), label="Ngày kết thúc")
99
+
100
+ with gr.Row():
101
+ tickers_string = gr.Textbox("MA,V,JPM,BA",
102
+ label='Nhập tất cả các mã cổ phiếu sẽ được đưa vào danh mục đầu tư tách biệt \
103
+ bằng dấu phẩy KHÔNG có dấu cách, ví dụ: "MA,V,JPM,BA"')
104
+ btn = gr.Button("Tối ưu hóa danh mục đầu tư")
105
+
106
+ with gr.Row():
107
+ gr.HTML("<h3>Số liệu danh mục đầu tư được tối ưu hóa</h3>")
108
+
109
+ with gr.Row():
110
+ expected_annual_return = gr.Text(label="Lợi nhuận dự kiến ​​hàng năm")
111
+ annual_volatility = gr.Text(label="Biến động hàng năm")
112
+ sharpe_ratio = gr.Text(label="Tỷ lệ Sharpe")
113
+
114
+ with gr.Row():
115
+ fig_cum_returns_optimized = gr.Plot(label="Lợi nhuận tích lũy của danh mục đầu tư được tối ưu hóa (Giá khởi điểm là 100 USD)")
116
+ weights_df = gr.DataFrame(label="Trọng số được tối ưu hóa của mỗi mã")
117
+
118
+ with gr.Row():
119
+ fig_efficient_frontier = gr.Plot(label="Biên giới hiệu quả")
120
+ fig_corr = gr.Plot(label="Tương quan giữa các cổ phiếu")
121
+
122
+ with gr.Row():
123
+ fig_indiv_prices = gr.Plot(label="Giá cổ phiếu riêng lẻ")
124
+ fig_cum_returns = gr.Plot(label="Lợi nhuận tích lũy của từng cổ phiếu bắt đầu từ 100 USD")
125
+
126
+ btn.click(fn=output_results, inputs=[start_date, end_date, tickers_string],
127
+ outputs=[fig_cum_returns_optimized, weights_df, fig_efficient_frontier, fig_corr, \
128
+ expected_annual_return, annual_volatility, sharpe_ratio, fig_indiv_prices, fig_cum_returns])
129
+
130
+ app.launch()