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): # 일일 누적 수익률 계산 및 시각화 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): # 최대 샤프 비율로 포트폴리오 최적화 및 효율적 투자선 그리기 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="최대 샤프") ax.legend() 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, '개별 주식의 누적 수익률 ($100 시작)') # 주식 간 상관 관계 계산 및 시각화 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) # 효율적 투자선 시각화 fig_efficient_frontier = plot_efficient_frontier_and_max_sharpe(mu, S) return fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices # Gradio 인터페이스 구성 with gr.Blocks() as app: with gr.Row(): gr.HTML("