File size: 3,777 Bytes
23c88d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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("<h1>๊ธ€๋กœ๋ฒŒ ์ฃผ์‹ ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ๋„๊ตฌ</h1>")
    
    with gr.Row():
        start_date = gr.Textbox("2013-01-01", label="์‹œ์ž‘ ์ผ์ž")
        end_date = gr.Textbox(datetime.now().date(), label="์ข…๋ฃŒ ์ผ์ž")
    
    with gr.Row():
        tickers_string = gr.Textbox("TSLA,META,AMZN,MSFT,BTC-USD", label="ํฌํŠธํด๋ฆฌ์˜ค์— ํฌํ•จ๋  ์ฃผ์‹ ํ‹ฐ์ปค๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž…๋ ฅํ•˜์„ธ์š” (์˜ˆ: 'TSLA,META,AMZN,MSFT,BTC-USD')")
        btn = gr.Button("ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ๊ฒฐ๊ณผ ๋ณด๊ธฐ")
    
    with gr.Row():
        expected_annual_return = gr.Text(label="์˜ˆ์ƒ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ ")
        annual_volatility = gr.Text(label="์—ฐ๊ฐ„ ๋ณ€๋™์„ฑ")
        sharpe_ratio = gr.Text(label="์ƒคํ”„ ๋น„์œจ")
    
    with gr.Row():
        fig_cum_returns = gr.Plot(label="์ตœ์ ํ™”๋œ ํฌํŠธํด๋ฆฌ์˜ค์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  (์‹œ์ž‘ ๊ฐ€๊ฒฉ $100)")
        fig_efficient_frontier = gr.Plot(label="ํšจ์œจ์  ํˆฌ์ž์„ ")
        fig_corr = gr.Plot(label="์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„")
        fig_indiv_prices = 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])

app.launch()