래리 윌리엄스 - 변동성 돌파 전략
Volatility Breakout Strategy
전략의 기본 원리
하루 동안의 단기 상승 추세에 탑승해서 이익을 실현한다.
시장 상황이 상승 추세인 상황에서, 현재 주가가 이미 오늘 시가에 어제 Range 보다 더 올라가고 있다면, 오늘 하루 상승을 예측함.
- Range = (어제 고가 - 어제 저가)
- 매수 : 현재가 > (오늘 시가 + Range * 0.5(=k))
- k는 조절 가능
- 매도 : 다음 날 시가
코스닥 지수에 백테스팅
# 코스닥 지수(KQ11) 전체 (데이터 시작 ~ 현재)
df = fdr.DataReader('KQ11')
# 변동성 돌파 전략 시뮬레이션
def volatility_break_out_strategy(df, k):
# 함수 내의 변수 df로 복사
df = df.copy()
# 필요한 데이터 컬럼 추가
df['변동폭'] = df['High'] - df['Low']
df['목표가'] = df['Open'] + df['변동폭'].shift(1) * k
df['다음날시가'] = df['Open'].shift(-1)
# 맨앞과 맨뒤에 목표가가 Nan인 row 제거
df = df.dropna()
# 조건
cond = df['High'] > df['목표가'] # 특정 순간에 현재가가 목표가보다 높았던 순간이 있었다.
# 조건에 맞는 날짜만 뽑기
수익률 = df.loc[cond, '다음날시가'] / df.loc[cond, '목표가']
# 슬리피지를 0.002로 고려 0.2%
수익률 = 수익률 - 0.002
누적수익률 = 수익률.cumprod()
기간수익률 = 누적수익률.iloc[-1]
# CAGR 계산 공식
N = (df.index[-1] - df.index[0]).days / 365 # 투자 날짜
CAGR = (기간수익률 ** (1/N)) - 1
return CAGR, int(N), 누적수익률
- df.shift(n) : n의 수 만큼 아래로 내려감. n이 음수일 경우 위로 올라감. 처음 밀린 자리는 NaN값이 들어간다.
- df['변동폭'].shift(1) : 변동폭 컬럼의 값이 한칸 아래로 밀린 값. 전날의 변동폭 값이 필요하기 때문.
- df['Open'].shift(-1) : Open 컬럼의 값이 한칸 위로 밀린 값. 다음날의 Open 값이 필요하기 때문
- 슬리피지 : 주문이 체결될 것이라고 예상한 가격과 실행된 가격의 차이
상수 k값의 변화에 따른 투자 결과 변화
CAGR_dict = {}
for k in range(1, 21):
CAGR, invest_year, 누적수익률 = volatility_break_out_strategy(df, k/10)
CAGR_dict[f'{k/10}'] = CAGR
print(f'range 가중치 : {k/10}, CAGR 수익률 : {CAGR}, 투자년도 : {invest_year}년')
# 딕셔너리 내림차순 정렬
sorted(CAGR_dict.items(), key=lambda item: item[1], reverse=True)
무조건 CAGR이 높다고 쓰면 과적합이 날 수 있다.
수익률 그래프
CAGR, invest_year, 누적수익률 = volatility_break_out_strategy(df, 0.5)
print(f'CAGR 수익률 : {CAGR}, 투자년도 : {invest_year}년')
# CAGR 수익률 : 0.22526677329310751, 투자년도 : 22년
print(누적수익률)
# Date
# 2001-01-03 1.073477
# 2001-01-05 1.061213
# 2001-01-08 1.112404
# 2001-01-10 1.038447
# 2001-01-12 1.066388
# ...
# 2021-08-27 173.282374
# 2021-08-31 173.162288
# 2021-09-01 173.491811
# 2021-09-03 173.733170
# 2021-09-14 173.928866
# Length: 1563, dtype: float64
# 그래프
fig = 누적수익률.plot(figsize=(20,10), title=f'변동성 돌파전략 (k=0.5) - 코스닥 지수 - 백테스팅 결과 ({누적수익률.index[0].strftime("%Y-%m-%d")}-{누적수익률.index[-1].strftime("%Y-%m-%d")}) - 누적수익률 {(누적수익률.iloc[-1]-1)*100:.2f}%', fontsize=10)
fig.axes.title.set_size(30)
- .strftime() : 날짜 형식 변환 메서드
- %d : 0을 채운 10진수 표기로 날짜를 표시
- %m : 0을 채운 10진수 표기로 월을 표시
- %y : 0을 채운 10진수 표기로 2자리 년도
- %Y : 0을 채운 10진수 표기로 4자리 년도
- %H : 0을 채운 10진수 표기로 시간 (24시간 표기)
- %I : 0을 채운 10진수 표기로 시간 (12시간 표기)
- %M : 0을 채운 10진수 표기로 분
- 등등
'퀀트' 카테고리의 다른 글
25. 레이 달리오의 올웨더 전략 (0) | 2023.01.15 |
---|---|
24. 게리 안토나치의 듀얼 모멘텀 전략 (0) | 2023.01.14 |
22. 켈리 베팅 (0) | 2023.01.12 |
21. 백테스팅 기본 예제 (0) | 2023.01.10 |
20. 투자 전략을 과거 시장에 실험해보기 : 백테스트 (1) | 2023.01.09 |