Kospi 종목 벡테스팅(2013년~2022년)
지난 글에서 벡테스팅을 하기 위한 코드를 구현하였다.
2022.11.07 - [개발일지] - 3. 투자지표를 활용한 매매 시점 모니터링 - 벡테스팅
현재 적용되어 있는 전략은 RSI를 이용한 매매로 30, 70 기준값 사용한다.
기본 전략을 다시 한번 소개하면,
- 30 이하일 때 매수 대기, 30 이상으로 올라가면 매수
- 70 이상일 때 매도 대기, 70 이하로 떨어지면 매도
이렇게 간단한 전략이 적용되어 있다. RSI를 말할 때 보편적으로 소개되는 전략이긴 한데, 과연 이 전략이 어떤 종목에 적용해도 효과가 있을까?
자동 매매를 위한 전략이라 함은 어떤 종목을 가져와도 수익이 날 가능성이 있는, 즉 수익이 날 확률을 높이기 위해 만들어지는 것이라 생각한다. 따라서 시장에 상장되어있는 모든 종목에 적용해 보고 수익이 나는 종목이 더 많도록 전략을 검증하고자 한다.
검증 과정은 동일한 조건으로 코스피에 상장되어있는 모든 종목에 적용했을 때 현재 기준으로 손익률을 평가한다.
현재 조회되는 코스피 종목은 총 824개가 있으며, 시드머니는 1,000만원으로 시작했다. 그리고 1회 매매 기준 금액은 500만원으로 설정했다. 즉 매매 시그널이 발생하면 500만원씩 매수 혹은 매도하는 것이다.
투자 시점은 2013년부터 하되, 그 이후 상장된 종목은 상장 시점부터 RSI값이 생성되는 14일 이후부터 벡테스팅을 시작한다.
벡테스팅을 완료하고 연평균 수익률을 계산해 전략에 대한 수익성 검증을 한다.
정리하자면,
- 시드 머니 1,000만원
- 1회 매매 기준 금액 500만원
- 투자 지표 RSI
- 투자 시점 2013년 ~ 2022년(2013년 이후 상장 종목은 상장 시점부터)
- 손절선 없이 벡테스팅
2022.11.07 - [개발일지] - 3. 투자지표를 활용한 매매 시점 모니터링 - 벡테스팅
이 글에서 이어서 실행시키면 오류 없이 실행될 것이다. 필요한 함수와 패키지가 윗글에 정리되어있다.
이어서 Kospi 종목을 벡테스팅 하는 코드는 아래와 같다.
%%time
kospi_symbol_list = []
kospi_current_price = []
kospi_time_index = []
lower_cut = 30
upper_cut = 70
stop_loss = -100
seed_money = 10000000
set_base_buy = 5000000
for kospi_symbol in kospi_data.Symbol:
ks = kospi_data[kospi_data["Symbol"]==kospi_symbol]
target_stock = ks.Name.values[0]
print(target_stock)
price_data = fdr.DataReader(ks.Symbol.values[0],"2012-12-1")
if price_data.shape[0]>100:
price_data["stock_name"]=target_stock
RSI_df = rsi(price_data, "Close",14)
RMI_df = rmi(price_data, "Close",14)
price_data["RSI"] = RSI_df
price_data["RMI"] = RMI_df
price_data = price_data[20:]
bitrade = set_init(target_stock,save_path,seed_money,set_base_buy)
plot_value = trading_simulation(bitrade,price_data,"RSI",lower_cut,upper_cut,stop_loss)
kospi_symbol_list.append(ks.Symbol.values[0])
kospi_current_price.append(plot_value[-1])
kospi_time_index.append(price_data.head(1).index)
print("DONE")
종목코드, 마지막 가격, 매매 시작 일자를 기록하는 리스트를 만들어 벡테스팅을 진행한다.
총 실행 시간은 1시간 13분 소요.
방법은 이전 글에서 실행했던 것과 동일하다. 개별 종목을 벡테스팅하면서 마지막 날짜에 평가된 자산을 기록한다.
주식을 보유하고 있으면 일 별 현재 가격에 따라 계속 총자산이 변할 것이고, 전량 매도한 상태이면 총자산이 변동이 없을 것이다.
kospi_result = pd.concat([pd.DataFrame(kospi_symbol_list),pd.DataFrame(kospi_current_price),
pd.DataFrame(kospi_time_index)],axis = 1)
kospi_result.columns = ["Symbol","Last_money","time"]
기록된 리스트를 데이터 프레임 형식으로 만들어 주고 컬럼명을 부여한다.
kospi_result = pd.merge(kospi_result,kospi_data[["Symbol","Name"]])
kospi_result.set_index("time",inplace = True)
종목코드로는 어떤 기업인지 알기 어렵기 때문에 종목 이름을 붙여 준 후 time에 해당하는 컬럼은 index로 만들어 조회가 편하게 한다.
이렇게 만들어진 데이터는 아래와 같다.
총 821개 kospi 종목에 대한 현재 시점의 평가 금액이다. Last_money 부분이 평가 금액 부분이다.
824개를 조회했는데 821개 종목만 데이터로 만들어진 것은 상장한지 얼마 되지 않은(100일 미만) 종목은 제외했기 때문이다.
time 컬럼은 모니터링을 시작한 시점이다.
이제 연평균 수익률을 구해 어느 종목이 가장 투자 손익률이 좋았는지 알아보자.
연평균 수익률은 공식은 다음과 같다.
CAGR = (최종금액 / 최초금액) ^ (1 / 기간) -1
그런데 한 가지 문제가 있다. 각 종목이 시작 시점이 다르기 때문에 연평균 수익률을 내기 위해선 각기 다른 기간을 적용해야 한다.
따라서 현재 일을 기준으로 투자 시작일과의 차이(day)를 구해 연으로 환산한다.
kospi_result["current_time"] = price_data.tail(1).index.values[0]
kospi_result["current_time"] = kospi_result["current_time"] - kospi_result.index
kospi_result["current_time2"] = kospi_result["current_time"].astype(str).str.split(" ").str[0].astype(int)
kospi_result["current_time2"] = np.round(kospi_result["current_time2"]/365,2)
current_time2 컬럼이 소수점 단위의 기간 연도가 만들어졌다.
계산된 기간을 이용해 연평균 수익률을 계산하는 식에 대입해 수익률을 계산한다.
kospi_result["average_yield"] = np.round((np.power((kospi_result["Last_money"] / seed_money),
1/kospi_result["current_time2"])-1)*100,2)
위의 과정으로 만들어진 코스피 종목 별 연평균 수익률이다.
이 데이터를 이용해 RSI 기본 전략을 적용했을 때의 코스피 전체 종목 손익률을 보자.
import seaborn as sns
plt.title("연평균 수익률 분포")
sns.distplot(kospi_result["average_yield"],bins = 15)
plt.show()
최대 30%, 최소 -66프로 손익률이 났다. 히스토그램으로 보면 -20~20 사이에 대부분 분포하고 있는 것을 볼 수 있다.
그럼 최대, 최소 손익률이 난 종목들을 보자.
kospi_result[kospi_result["average_yield"]<-20].sort_values(["average_yield"],ascending = True)
손실률이 20%를 넘어가는 종목을 보니 2년 안에 상장된 기업이 대부분이다. 최근 IPO 공모주에 대한 관심이 높아져 초기 수요에 따른 급등 및 급락이 반복되어 이런 현상이 나타나는 것 같다. 따라서 기간이 짧고 연평균 손실률 큼에도 불구하고 잔액은 어느 정도 남아있다.
반면에 투자기간이 길며 연평균 수익률도 낮은 종목 중 대표적으로 비케이탑스를 보자. 투자기간 9.85년, 연평균 손익률 -34.3%를 기록했다. 원금 1000만원이 약 16만원이 남았다. RSI 기본 전략의 대표적인 실패 케이스이다.
반대로 연평균 손익률이 좋은 종목을 보자.
kospi_result[kospi_result["average_yield"]>15].sort_values(["average_yield"],ascending = False)
대부분 장기 투자로 인한 높은 손익률을 기록했다. 그중 아남전자의 경우 9.85년 투자기간, 22.68%의 연평균 손익률을 기록해 원금 1,000만원이 약 7,300만원을 기록했다. RSI 기본 전략의 우수한 케이스이다.
아남전자를 그대로 가지고 2013년에 원금을 넣고 가만히 있었다면 581원에서 22년 11월 8일자 기준 1,920으로 약 3배 정도 불릴 수 있었지만, RSI 지표를 이용해 약 7배를 불릴 수 있었다.
즉, 투자 전략을 잘 이용하면 더 높은 수익을 기대할 수 있는 것이다.
그럼 이 투자 전략을 사용했을 때 수익을 볼 확률이 더 높을까를 고민해봐야 한다.
투자 전략을 아무리 잘 만들어도 100% 수익을 낼 수 있는 투자 기법은 존재하지 않는다. 결국 투자 시 수익을 내기 위한 확률을 높이는 것이 전략을 세울 때 가장 중요하게 봐야 할 것이다.
지금 RSI 투자 전략으로 얻을 수 있는 수익을 낼 수 있는 종목 분포를 확인해 보면
np.round(kospi_result[kospi_result["average_yield"]>0].shape[0] / kospi_result.shape[0] *100,2)
np.round(kospi_result[kospi_result["average_yield"]<0].shape[0] / kospi_result.shape[0] *100,2)
손익률 0% 초과한 종목이 전체 종목의 57.73 %, 손익률 0% 미만인 종목이 42.27%이다.
이 말은 이 전략으로 접근했을 때 수익을 낼 확률이 57.73%가 된다는 말이다. 절반보다 조금 높다. 개인적인 생각으론 이렇게 해도 전략 없이 접근하는 것보다는 수익이 낼 확률이 높다고 생각한다.(직접 경험한 바에 의하면......)
다음으로 수익을 낼 확률이 높은데 수익률도 높은가와 반대의 경우도 체크해보자. 먼저 그래프로 보면,
손익률 +의 0 ~ 20% 분포와 -의 -0 ~ -20%는 구성이 대략 비슷한데, -의 경우 상장폐지와 같은 이유로 -20%보다 더 낮은 구간을 기록했다.
따라서 전략을 세울 때 마이너스를 기록하는 종목의 투자를 최대한 방지해 손해를 입는 경우를 줄여나가는 방향도 중요할 것이다. 즉, 안정적인 투자도 추구해야 할 것이다.
수익이 난 경우 평균 5.96%, 중위수 5.17%의 연평균 수익률이 나타난다.
손해가 난 경우 평균 - 7.29%, 중위수 -4.45%의 연평균 손해율이 나타난다.
원금 1000만원으로 모든 종목에 동일하게 투자했을 때 연평균 수익률을 평균과 중위수로 계산한다면,
# 연평균 수익률 + 중위수
1000*np.power(1.0517,10) - 1000
# 연평균 수익률 - 중위수
1000*np.power(0.9555,10) - 1000
# 연평균 수익률 + 평균
1000*np.power(1.0596,10) - 1000
# 연평균 수익률 - 평균
1000*np.power(0.9271,10) - 1000
순서대로
- 연평균 수익률 + 중위수 : 655만원
- 연평균 수익률 - 중위수 : -366만원
- 연평균 수익률 + 평균 : 784만원
- 연평균 수익률 - 평균 : -530만원
중위수 기준 655 - 366 = 289
평균 기준 784 - 530 = 254
정리하자면 원금 1,000만원으로 모든 종목에 테스트한 후 연평균 수익률의 중위수와 평균의 손익을 계산했을 때 각각 254만원, 289만원의 수익을 기대할 수 있었다.
RSI 기본 투자 전략으로 약 2013년부터 약 10년 간 벡테스팅 결과를 정리하자면,
- 손익 확률 + : 57.73%, - : 42.27%
- 최대 손익률 + : 30.1%, - 66.8%
- 손익 + 연평균 수익률 중위수 : 5.17%, 평균 : 5.96%
- 손익 - 연평균 수익률 중위수 : -4.45%, 평균 : -7.29%
- 기대 수익금 중위수 기준 289만원, 평균 기준 254만원
앞으로 투자 전략을 만드는 방향으로 위의 기준과 비교해서
- 손익 확률 +를 높여 손해 확률을 낮출 수 있도록 구성
- 최대 손익률을 줄이는 방향 : 안정적으로 투자하기 위해
- 기대 수익금을 높이는 방향
일단 기초적으로 이렇게 세 가지를 보며 전략을 구성하고자 한다.
위의 기준은 내가 투자 전략을 세우기 위해 기준을 최소한의 가이드라인을 만든 것이다. 따라서 저 가이드라인이 투자 전략을 세울 때 잘 맞을지, 의미가 있을지는 아직 모르겠다. 따라서 투자 전략 가이드라인을 조금 더 고민해보고 전략을 구성하면서 추가할 예정이다. 새로운 가이드라인이 만들어지면 관련 내용을 포스팅하도록 하겠다.
전략의 기준은 개인이 중요하다 판다한는 것으로 설정하면 될 것이다. 참고할 수 있는 지표도 개인의 판단으로 더 필요한 값을 만들어 비교할 수 있다.
투자 전략 또한, 추구하는 방향으로 만들면 될 것이다. 예를 들어 투자 중 최대 손실률을 줄이는 방향으로(안정성이 높은 전략) 만들 수도 있고, 최대 손실률이 높더라도 최대 수익률을 높이는 방향으로(위험성이 있지만, 기대수익이 커지는 전략)으로 만들 수도 있을 것이다.
'개발일지' 카테고리의 다른 글
7. 투자지표를 활용한 매매 시점 모니터링 - 다중 종목 벡테스팅 (0) | 2022.11.10 |
---|---|
6. 투자지표를 활용한 매매 시점 모니터링 - 손절선 (0) | 2022.11.09 |
4. 투자지표를 활용한 매매 시점 모니터링 - 시각화 (0) | 2022.11.08 |
3. 투자지표를 활용한 매매 시점 모니터링 - 벡테스팅 (0) | 2022.11.07 |
2. 투자지표를 활용한 매매 시점 모니터링 - RSI, RMI (0) | 2022.11.07 |
댓글