유자차의 재테크 공부방

[동적 자산배분] 종합 듀얼 모멘텀- 파이썬으로 직접 백테스팅하기 - (1) 본문

자산배분

[동적 자산배분] 종합 듀얼 모멘텀- 파이썬으로 직접 백테스팅하기 - (1)

유자차H 2023. 3. 2. 23:30
반응형

전략

종합 듀얼 모멘텀

 

구현

import pandas as pd
import yfinance as yf

# yahoo finance에서 필요 종목들의 공통 시작일부터 종가 데이터 받기
def get_yahoo_data(tickers, get_type="Adj Close"):
    df = yf.download(tickers)
    df = df[get_type]
    df.dropna(inplace=True)
    return df

# 리밸런싱 하는 날의 데이터만 뽑기(월말 데이터만 추출)  
def get_rebal_date(df, rebal="month"):
    res_df = pd.DataFrame()
    df["year"] = df.index.year
    df["month"] = df.index.month
    df["day"] = df.index.day
    days_df = df.groupby(["year","month"])["day"].max()
    for i in range(len(days_df)):
        if days_df.iloc[i] >= 25:
            day = "{}-{}-{}".format(days_df.index[i][0], days_df.index[i][1], days_df.iloc[i])
            res_df = pd.concat([res_df,df[df.index==day]])
    return res_df
    
def CDM():
  tickers = ["SPY", "EFA", "LQD", "HYG", "VNQ", "REM", "TLT", "GLD","BIL"]
  
  data = get_yahoo_data(tickers, get_type="Adj Close") # 데이터 불러오기
  rebal_data = get_rebal_date(data) # 월말 데이터만 뽑기

  res = pd.DataFrame()
  for i in range(12, rebal_data.shape[0]):
    date = rebal_data.index[i]
    buy={}
    bil_m12 = rebal_data["BIL"].iloc[i]/rebal_data["BIL"].iloc[i-12] -1
    for a,b in [["SPY","EFA"],["LQD", "HYG"], ["VNQ", "REM"], ["TLT", "GLD"]]:
      a_m12 = rebal_data[a].iloc[i]/rebal_data[a].iloc[i-12] -1
      b_m12 = rebal_data[b].iloc[i]/rebal_data[b].iloc[i-12] -1

      if max(bil_m12, a_m12, b_m12) == bil_m12:
        name = "BIL"
      else:
        if a_m12 > b_m12:
          name = a
        elif b_m12 > a_m12:
          name = b
        else:
          name = "None"
      
      if name in buy.keys():
        buy[name] += 25
      else:
        buy[name] = 25
    
    df_buy = pd.DataFrame([[date, buy]],columns=["Date","Buy"])
    res = pd.concat([res, df_buy])
  return res
CDM_result = CDM()
CDM_result.tail(5) # 최근 5개만

반응형
Comments