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("

Trình tối ưu hóa danh mục đầu tư chứng khoán

") 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("

Số liệu danh mục đầu tư được tối ưu hóa

") 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()