vumichien's picture
Create app.py
dde01d0
raw
history blame
5.92 kB
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()