Spaces:
Runtime error
Runtime error
import gradio as gr | |
import yfinance as yf | |
from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices | |
from pypfopt import EfficientFrontier | |
from pypfopt import risk_models | |
from pypfopt import expected_returns | |
from pypfopt import plotting | |
import copy | |
import numpy as np | |
import pandas as pd | |
import plotly.express as px | |
import matplotlib.pyplot as plt | |
from datetime import datetime | |
import datetime | |
def plot_cum_returns(data, title): | |
daily_cum_returns = 1 + data.dropna().pct_change() | |
daily_cum_returns = daily_cum_returns.cumprod()*100 | |
fig = px.line(daily_cum_returns, title=title) | |
return fig | |
def plot_efficient_frontier_and_max_sharpe(mu, S): | |
# Optimize portfolio for max Sharpe ratio and plot it out with efficient frontier curve | |
ef = EfficientFrontier(mu, S) | |
fig, ax = plt.subplots(figsize=(6,4)) | |
ef_max_sharpe = copy.deepcopy(ef) | |
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=False) | |
# Find the max sharpe portfolio | |
ef_max_sharpe.max_sharpe(risk_free_rate=0.02) | |
ret_tangent, std_tangent, _ = ef_max_sharpe.portfolio_performance() | |
ax.scatter(std_tangent, ret_tangent, marker="*", s=100, c="r", label="Max Sharpe") | |
# Generate random portfolios with random weights | |
n_samples = 1000 | |
w = np.random.dirichlet(np.ones(ef.n_assets), n_samples) | |
rets = w.dot(ef.expected_returns) | |
stds = np.sqrt(np.diag(w @ ef.cov_matrix @ w.T)) | |
sharpes = rets / stds | |
ax.scatter(stds, rets, marker=".", c=sharpes, cmap="viridis_r") | |
# Output | |
ax.legend() | |
return fig | |
def output_results(start_date, end_date, tickers_string): | |
tickers = tickers_string.split(',') | |
# Get Stock Prices | |
stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close'] | |
# Plot Individual Stock Prices | |
fig_indiv_prices = px.line(stocks_df, title='Giá cổ phiếu riêng lẻ') | |
# Plot Individual Cumulative Returns | |
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') | |
# Calculatge and Plot Correlation Matrix between Stocks | |
corr_df = stocks_df.corr().round(2) | |
fig_corr = px.imshow(corr_df, text_auto=True, title = 'Tương quan giữa các cổ phiếu') | |
# Calculate expected returns and sample covariance matrix for portfolio optimization later | |
mu = expected_returns.mean_historical_return(stocks_df) | |
S = risk_models.sample_cov(stocks_df) | |
# Plot efficient frontier curve | |
fig_efficient_frontier = plot_efficient_frontier_and_max_sharpe(mu, S) | |
# Get optimized weights | |
ef = EfficientFrontier(mu, S) | |
ef.max_sharpe(risk_free_rate=0.04) | |
weights = ef.clean_weights() | |
expected_annual_return, annual_volatility, sharpe_ratio = ef.portfolio_performance() | |
expected_annual_return, annual_volatility, sharpe_ratio = '{}%'.format((expected_annual_return*100).round(2)), \ | |
'{}%'.format((annual_volatility*100).round(2)), \ | |
'{}%'.format((sharpe_ratio*100).round(2)) | |
weights_df = pd.DataFrame.from_dict(weights, orient = 'index') | |
weights_df = weights_df.reset_index() | |
weights_df.columns = ['Mã chứng khoán', 'Trọng số'] | |
# Calculate returns of portfolio with optimized weights | |
stocks_df['Danh mục đầu tư được tối ưu hóa'] = 0 | |
for ticker, weight in weights.items(): | |
stocks_df['Danh mục đầu tư được tối ưu hóa'] += stocks_df[ticker]*weight | |
# Plot Cumulative Returns of Optimized Portfolio | |
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') | |
return fig_cum_returns_optimized, weights_df, fig_efficient_frontier, fig_corr, \ | |
expected_annual_return, annual_volatility, sharpe_ratio, fig_indiv_prices, fig_cum_returns | |
with gr.Blocks(theme=gr.themes.Soft()) as app: | |
with gr.Row(): | |
gr.HTML("<h1>Trình tối ưu hóa danh mục đầu tư chứng khoán</h1>") | |
with gr.Row(): | |
start_date = gr.Textbox("2013-01-01", label="Ngày bắt đầu") | |
end_date = gr.Textbox(datetime.datetime.now().date(), label="Ngày kết thúc") | |
with gr.Row(): | |
tickers_string = gr.Textbox("MA,V,JPM,BA", | |
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 \ | |
bằng dấu phẩy KHÔNG có dấu cách, ví dụ: "MA,V,JPM,BA"') | |
btn = gr.Button("Tối ưu hóa danh mục đầu tư") | |
with gr.Row(): | |
gr.HTML("<h3>Số liệu danh mục đầu tư được tối ưu hóa</h3>") | |
with gr.Row(): | |
expected_annual_return = gr.Text(label="Lợi nhuận dự kiến hàng năm") | |
annual_volatility = gr.Text(label="Biến động hàng năm") | |
sharpe_ratio = gr.Text(label="Tỷ lệ Sharpe") | |
with gr.Row(): | |
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)") | |
weights_df = gr.DataFrame(label="Trọng số được tối ưu hóa của mỗi mã") | |
with gr.Row(): | |
fig_efficient_frontier = gr.Plot(label="Biên giới hiệu quả") | |
fig_corr = gr.Plot(label="Tương quan giữa các cổ phiếu") | |
with gr.Row(): | |
fig_indiv_prices = gr.Plot(label="Giá cổ phiếu riêng lẻ") | |
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") | |
btn.click(fn=output_results, inputs=[start_date, end_date, tickers_string], | |
outputs=[fig_cum_returns_optimized, weights_df, fig_efficient_frontier, fig_corr, \ | |
expected_annual_return, annual_volatility, sharpe_ratio, fig_indiv_prices, fig_cum_returns]) | |
app.launch() |