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 def plot_cum_returns(data, title, initial_capital=1000): # 일일 누적 수익률 계산 및 시각화 daily_cum_returns = (1 + data.dropna().pct_change()).cumprod() * initial_capital fig = px.line(daily_cum_returns, title=title) return fig def plot_efficient_frontier_and_max_sharpe(mu, S): # 최대 샤프 비율로 포트폴리오 최적화 및 효율적 투자선 그리기 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) 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") ax.legend() return fig def plot_weights(weights): # 포트폴리오 최적 투자 비율 그래프 출력 labels = weights.keys() sizes = weights.values() fig, ax = plt.subplots() ax.pie(sizes, labels=labels, autopct='%1.1f%%') ax.axis('equal') return fig def output_results(start_date, end_date, tickers_string): tickers = tickers_string.split(',') stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close'] fig_indiv_prices = px.line(stocks_df, title='개별 주식 가격') fig_cum_returns = plot_cum_returns(stocks_df, '개별 주식의 누적 수익률 ($1,000 시작)') corr_df = stocks_df.corr().round(2) fig_corr = px.imshow(corr_df, text_auto=True, title='주식 간 상관 관계') mu = expected_returns.mean_historical_return(stocks_df) S = risk_models.sample_cov(stocks_df) ef = EfficientFrontier(mu, S) weights = ef.max_sharpe(risk_free_rate=0.02) cleaned_weights = ef.clean_weights() fig_weights = plot_weights(cleaned_weights) expected_annual_return, annual_volatility, sharpe_ratio = ef.portfolio_performance() fig_efficient_frontier = plot_efficient_frontier_and_max_sharpe(mu, S) return fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, \ f"{expected_annual_return*100:.2f}%", f"{annual_volatility*100:.2f}%", f"{sharpe_ratio:.2f}" css = """ footer { visibility: hidden; } """ # Gradio 인터페이스 구성 with gr.Blocks(css=css) as app: gr.Markdown("""

AIQ Asset Portpolio: 글로벌 자산(주식,지수,BTC,상품 등) AI 포트폴리오 최적화 서비스

전세계 모든 티커 보기(야후 파이낸스): https://finance.yahoo.com/most-active

""") with gr.Row(): start_date = gr.Textbox("2013-01-01", label="시작 일자") end_date = gr.Textbox(datetime.now().date(), label="종료 일자") tickers_string = gr.Textbox("NVDA,^GSPC,GC=F,MSFT,BTC-USD", label="주식 티커를 쉼표로 구분하여 입력하세요") btn = gr.Button("포트폴리오 최적화 결과 보기") with gr.Row(): expected_annual_return = gr.Text(label="예상 연간 수익률") annual_volatility = gr.Text(label="연간 변동성") sharpe_ratio = gr.Text(label="샤프 비율") with gr.Column(): fig_cum_returns = gr.Plot(label="최적화된 포트폴리오의 누적 수익률 (시작 가격 $1,000)") fig_efficient_frontier = gr.Plot(label="효율적 투자선") fig_corr = gr.Plot(label="주식 간 상관 관계") fig_indiv_prices = gr.Plot(label="개별 주식 가격") fig_weights = gr.Plot(label="포트폴리오 최적 투자 비율") btn.click(fn=output_results, inputs=[start_date, end_date, tickers_string], outputs=[fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, expected_annual_return, annual_volatility, sharpe_ratio]) app.launch()