LAA 전략 포지션 확인을 위한 간단 파이썬 코드를 공유합니다.
.
LAA(Lethargic Asset Allocation) 전략은 영구 포트폴리오를 개선한 동적 자산배분 전략이라고 볼 수 있습니다. 비교적 노력? 덜 드는 전략으로서 ‘게으른 자산 배분’ 전략이라고 번역할 수 있을 것 같습니다.
.
미국 주식(IWD), 금(GLD), 미국 중기채(IEF)에 투자 자산의 각 25%씩 동일한 비중으로 고정 투자합니다. 나머지 25%의 자산은 나스닥(QQQ) 혹은 단기채권(SHY/현금) 중에서 유동적으로 선택하는 전략입니다.
.
매월 마지막 날 S&P500 종가가 200일 이동 평균보다 낮으면서, 미국 실업률이 12개월 이동 평균보다 높을 때, 하락장이면서 불황기로 판단하고 단기채권(SHY 혹은 현금) 포지션을 가져갑니다. 그 외에는 나스닥(QQQ) 포지션으로 가져갑니다. 매달 리밸런싱을 하게 되겠죠.
* 미국 실업률 지표 : https://fred.stlouisfed.org/series/UNRATE
.
LAA 전략을 실행하기 위해 S&P500의 200일 이동 평균을 보려 앱이나 웹을 여는 것, 그리고 실업률 지표를 보고 이동 평균을 계산하는 것조차 귀찮아진 저 같은 분들을 위해 아래 파이썬 코드를 공유합니다.
.
YFINANCE, PANDAS 패키지가 설치되어 있어야 합니다. 파이썬으로 주식 데이터를 다룰 때 자주 쓰고 있습니다.
또한 미국 실업률 지표를 가져오기 위하여 FREDAPI가 필요합니다. FREDAPI 패키지를 쓰기 위해서는 FRED에서 API키를 받으셔야 합니다. 아래 링크에서 ‘Request or view your API keys‘로 가셔서 회원 가입 하시고 발급 받으시면 됩니다.
* FRED API KEY 링크 : https://fred.stlouisfed.org/docs/api/api_key.html
.
먼저 사용한 라이브러리는 아래와 같습니다.
from fredapi import Fred # 미국 실업률 지표
import yfinance as yf # S&P500 지표
import pandas as pd
import datetime as dt
from dateutil.relativedelta import relativedelta
.
- ‘실업률 상태가 안좋은가?’ 알아보는 함수
오늘 날짜 정보를 변수 ‘today’로 설정했습니다. 그리고 API 키를 이용해 FRED API를 쓸 준비를 합니다.
함수 내용을 알아보겠습니다. ‘observation_start’ 변수는 실업률을 조사할 기준 날짜로서 1년보다 더 넉넉하게 잡아줍니다. 저는 오늘 날짜 기준 15개월 전 달의 1일을 기준으로 했습니다. get_series() 함수를 이용해서 실업률 정보를 기준 날짜부터 지금까지 호출하고 이를 ‘data’라는 변수에 저장합니다. 정리 좀 하구요.
가져온 실업률 지표 값의 12개월 평균이 필요하기 때문에 해당 열을 12개 값씩 모아서 평균을 내기 위하여 rolling(window=12).mean()을 사용했습니다. 그리고 ’12SMA’라는 열을 만들어 이동 평균 값을 저장합니다.
이제는 지난 달 실업률 지표를 찾아서 이동 평균과 비교해보면 끝나겠죠? ‘tgt_date’라는 변수로 지난 달 1일 날짜를 설정합니다. 그리고 ‘tgt_date’ 날짜의 실업률 값과 이동 평균 값을 비교하게 했습니다. ‘실업률이 안좋은가?’라는 함수였기 때문에 실업률 값이 12개월 이동 평균 값 이상이면 참을, 반대면 거짓을 반환합니다.
today = dt.datetime.today()
fred = Fred(api_key='발급 받으신 API키를 여기에 넣어주세요')
def unrate_is_bad():
# 실업률 정보 파싱 시작일
observation_start = (today - relativedelta(months=15)).strftime('%Y-%m-01')
# 데이터 가져오고 정리하기
data = fred.get_series('unrate', observation_start=observation_start)
data = pd.DataFrame(data)
data.index.names = ['Date']
data.columns = ['Unrate']
# 12개월 이동평균 만들기
data['12SMA'] = data['Unrate'].rolling(window=12).mean()
# 지난달 실업률을 검색할 기준일
tgt_date = (today - relativedelta(months=1)).strftime('%Y-%m-01')
return data.loc[tgt_date,'Unrate'] >= data.loc[tgt_date,'12SMA']
.
- ‘S&P500 상태가 안좋은가?’ 알아보는 함수
기본적으로 함수의 흐름은 실업률 지표를 계산하는 것과 유사합니다. YFINANCE를 이용하여 S&P500 지표 자료를 가져옵니다. 그리고 데이터에 ‘200SMA’열을 추가로 만들어 200일 이동 평균 값을 저장합니다.
여기서 앞의 함수와 흐름이 다른 점이 있습니다. 데이터의 인덱스는 날짜로 구성되어 있는데 영업일이 아닌 날은 아예 데이터가 없습니다. 날짜가 점프하는 날들이 생기는 것이죠. 지난 달 말일이 영업일이었는지 아니었는지 확인하기 귀찮아지기 시작합니다. 그래서 인덱스를 1일 간격(freq = ‘D’)으로 모두 만들고 값이 비어있는 곳은 전날의 값과 같게(method = ‘ffill’)하였습니다. asfreq()라는 함수가 일을 덜어주었습니다. 예를 들어 토요일/일요일은 금요일과 같은 값으로 채워 놓은 거라고 생각하시면 되겠습니다.
지난 달의 말일을 계산하여 ‘last_day’라는 변수로 지정하고, 해당 일의 종가와 200일 이동평균을 비교합니다. 종가가 200일 이동 평균 이하라면 참을, 반대면 거짓을 반환합니다.
def sp500_is_bad():
# S&P500 정보 파싱 시작일
start = (today - relativedelta(months=15)).strftime('%Y-%m-%d')
# S&P500 지수 자료에 엑세스하고 시작일부터 현재까지의 자료를 가져옵니다.
sp500 = yf.Ticker('^GSPC')
data = sp500.history(start=start, auto_adjust = False)
data = pd.DataFrame(data)
# 200일 이동평균 만들기
data['200SMA'] = data['Close'].rolling(window=200).mean()
# 빈 날짜를 새로 만들고 데이터 채우기
data = data.asfreq(freq='D', method='ffill')
# 지난 달 말일
first_day = dt.datetime(today.year, today.month, day=1).date()
last_day = (first_day - relativedelta(days=1)).strftime('%Y-%m-%d')
return data.loc[last_day,'200SMA'] >= data.loc[last_day,'Close']
.
- ‘이번 달 투자할 자산’을 알려주는 함수
이번 달 투자할 LAA 종목들과 비율을 리스트로 반환해주는 pick_assets()이라는 함수입니다. 지속적으로 투자하는 종목들과 비율을 우선 리스트로 만들었습니다. 그리고 앞서 만들어 둔 두 개의 함수를 이용해서 실업률과 S&P500 지표를 확인하고 둘 다 좋지 않은 상황이면 안전자산(‘SHY’)을, 그 외의 상황에선 공격자산(‘QQQ’)를 목록에 넣게 하였습니다.
def pick_assets():
# 지속적으로 투자하는 종목들 리스트
ASSET_TOGO = [('IWD', 0.25), ('GLD', 0.25), ('IEF', 0.25)]
# 투자 자산 선정
if unrate_is_bad() and sp500_is_bad():
ASSET_TOGO.append(('SHY', 0.25))
else :
ASSET_TOGO.append(('QQQ', 0.25))
return ASSET_TOGO
.
- 마지막 정리
함수 세 개를 만들어두고 단순하게 pick_assets() 함수만 매달 초에 호출하면 이번 달에 투자할 종목을 알게 됩니다. 귀찮게 지표를 보면서 계산하거나 비교할 필요가 없습니다.
print(pick_assets())
# 결과 = [('IWD', 0.25), ('GLD', 0.25), ('IEF', 0.25), ('QQQ', 0.25)]
.
저는 이 코드를 서버에 올려두고 정기적으로 실행하게 하고 있습니다. 웹훅을 이용해서 투자 포지션과 투자 자산이 메세지앱(SLACK)으로 전달되도록 만들어 두었습니다. 그리고 또한 봇이 알아서 리밸런싱 하도록 해두었습니다. 더 게으른 전략으로 발전했다고 할 수 있겠네요.
다음에는 웹훅을 이용해서 투자 포지션 정보를 메세지로 받는 법을 간단하게 알아보겠습니다.
감사합니다.