수익률 그래프 출력

# 필요한 라이브러리들을 임포트합니다.
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
IPython_default = plt.rcParams.copy()  # 원래의 Matplotlib 스타일 설정을 저장합니다.

import yfinance as yf  # Yahoo Finance에서 금융 데이터를 다운로드하기 위한 라이브러리
import pyfolio as pf  # 포트폴리오 성능 분석을 위한 라이브러리
import quantstats as qs  # 투자 포트폴리오의 통계 분석을 위한 라이브러리

# 분석할 자산의 티커들을 리스트로 정의합니다.
tickers = ['SPY', 'TLT', 'GLD', 'BIL', 'IEF']
# 지정된 티커들의 최대 기간 일간 종가 데이터를 Yahoo Finance에서 다운로드합니다.
df_close = yf.download(tickers=tickers, 
                       period='max',
                       interval='1d',
                       auto_adjust=True  # 자동으로 주가 조정(배당, 분할 등 반영)
                      )['Close'][tickers]

# 각 자산의 시작 날짜를 출력합니다.
print('Start date of each stock')
print('-'*25)
for ticker in tickers:
    print(f"{ticker}: {df_close[[ticker]].dropna().iloc[0].name.strftime('%Y-%m-%d')}")
print('-'*25)

# 'CASH'라는 새로운 열을 추가하고 모든 값에 1을 할당합니다.
df_close['CASH'] = 1
# 자산 목록을 업데이트합니다.
tickers = ['SPY', 'TLT', 'GLD', 'CASH']

# 결측치를 제거한 후 필요한 자산만 포함하는 새로운 데이터 프레임을 생성합니다.
df = df_close[tickers].dropna()

# 트레이딩 기간을 정의합니다.
time_period = df.index.to_frame()  # 인덱스를 데이터 프레임으로 변환
trading_period = time_period.resample('BM').last().iloc[::12, :].rename(columns={'Date':'start_date'})
trading_period = trading_period.assign(end_date=trading_period.start_date.shift(-1).fillna(time_period.iloc[-1].name))
print(trading_period)

def get_mdd(df_price, start, end, col):
    """자산 가격의 최대 낙폭을 계산합니다."""
    df_price = df_price[start:end].copy()
    return ((df_price[col] - df_price[col].cummax()) / df_price[col].cummax()).cummin()

def get_pf_returns(df_price, tickers, start, end, weights=None, use_signal=None):
    """포트폴리오 수익률을 생성합니다."""
    if weights is None:
        weights = [1/len(tickers) for _ in range(len(tickers))]

    ret_dict = {ticker+'_RET': df_price[ticker].pct_change().fillna(0) for ticker in tickers}
    df_price = df_price.assign(**ret_dict)
    ret_cols = [ticker+'_RET' for ticker in tickers]  # 일일 수익률 컬럼 이름을 리스트로 저장

    df_trade = df_price.loc[start:end].copy()
    df_trade.loc[start, ret_cols] = 0  # 첫 거래일의 수익률은 0으로 설정
    df_trade = df_trade.assign(PF_RET=df_trade[ret_cols].dot(weights))

    cumret_dict = {col+'_CUMRET': (1 + df_trade[col+'_RET']).cumprod() for col in tickers}
    df_trade = df_trade.assign(**cumret_dict, PF_CUMRET=(1 + df_trade['PF_RET']).cumprod())

    mdd_dict = {col.split('_')[0]+'_MDD': get_mdd(df_price=df_trade, start=df_trade.index[0], end=df_trade.index[-1], col=col+'_CUMRET') for col in tickers}
    df_trade = df_trade.assign(**mdd_dict)

    return df_trade

# 각 거래 기간에 대한 결과를 집계합니다.
df_res = pd.DataFrame()
for i in range(len(trading_period)):
    df_trade = get_pf_returns(df_price=df,
                              tickers=tickers,
                              start=trading_period.iloc[i].start_date,
                              end=trading_period.iloc[i].end_date)
    df_res = pd.concat([df_res, df_trade], axis=0)

# 중복된 행을 제거합니다.
df_res = df_res.reset_index().drop_duplicates(['Date'], keep='first').set_index('Date')

# 그래프 스타일을 복원하고 새로운 스타일을 설정합니다.
plt.rcParams.update(IPython_default)
plt.style.use('_mpl-gallery')

# 누적 수익률을 다양한 색상으로 그래프에 표시합니다.
color_map = ['blue', 'green', 'red', 'pink','yellow']  # 색상 지정
(1 + df_res[['SPY_RET', 'TLT_RET', 'GLD_RET', 'CASH_RET', 'PF_RET']]).cumprod().plot(figsize=(12, 8), linewidth=1, color=color_map)
plt.show()

 

'재테크•투자•경제•주식' 카테고리의 다른 글

2차 전지 개발 관련 재 추진 정책  (0) 2024.05.05
SPY 누적수익률, 최고점, 일별수익률  (0) 2024.04.28
각 자산의 시장 시작 날짜 확인  (0) 2024.04.28
QuantStats  (0) 2024.04.28
pyfolio  (0) 2024.04.28