강환국 님의 '할수있다 퀀트투자'를 읽고나서 파이썬으로 만들어 보았다.
여러 조건을 백테스트 해 보았고, 이 조건이 가장 괜찮았다.
2003년부터 매월 11월 4일 즈음에 매수를 하고, 1년 후 매도 후 다시 매수하는 방법으로 17년간 백테스틀 해 보았다.
수익률이 8652% 즉, 원금의 86배가 된다. 하지만 문제는 손실이 많이 발생하는 해도 있다는 사실이다. 복리 수익률로 실컷 자금을 불렸지만, -42% 손실이 발생하면 정말 견디기 힘들 것 같다.
그래서 11월과 더불어 2월에도 분산해서 투자하는 방법을 생각했다. 그러니 가장 손실이 많이 발생한 해는 -1%로 견딜만한 수준이 되었다. CAGR도 11월만 하면 30%이지만, 2월까지 같이 하더라도 29%로 차이가 거의 없다.
저 PER, 저 PBR, 저 PER X 저 PBR, 고 DIV(배당수익률) 등 여러 케이스를 해 보았지만, 이 조건이 제일 괜찮다.
신기하게도 저 PBR X 저 DPS 가 왜 수익이 좋게 나온지는 나도 잘 모르겠다. DIV(배당수익률)을 한다는 것이 실수로 DPS(주당 배당금)으로 했는데, 수익이 좋게 나왔다. 내 논리로는 설명이 되지 않지만, 사실이 이러니깐 이렇게 실제 투자를 시작했다.
코드를 보면 알겠지만, 거래량이 없는 종목은 제외하였고, 주식수가 변동된 것은 보수적으로 보정해 주었다.
그럼에도 불구하고 실제 투자에서는 변수가 발생한다. 하지만, 큰 흐름에 영향을 줄 수준은 아닌 것 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
from pykrx import stock
import pandas as pd
import numpy as np
import os
import time
# 백테스트 할 날짜를 생성하기
def make_date_list(m, d):
date_list = []
for y in range(2003, 2021):
day = str(y) + str(m) + str(d)
b_day = stock.get_nearest_business_day_in_a_week(date=day) #휴일이면 근처의 영업일로 변경
date_list.append(b_day)
return date_list
# 연도별 수익률 구하기
def row_pbr_dps(date, date2):
codes = stock.get_market_ticker_list(date, market='ALL')
corp = []
for code in codes:
name = stock.get_market_ticker_name(code)
corp.append([code, name])
df1 = pd.DataFrame(data=corp, columns=['code', '종목명'])
df1 = df1.set_index('code')
df_f = stock.get_market_fundamental_by_ticker(date=date, market='ALL') # PER, PBR, DIV,... : KRX 우선가져오기
df_c = stock.get_market_cap_by_ticker(date=date, market='ALL') # 종가
df_c2 = stock.get_market_cap_by_ticker(date2, market='ALL') # 1년 후 종가
time.sleep(1)
df_c2 = df_c2[['종가', '상장주식수']]
df = pd.merge(df1, df_c, left_index=True, right_index=True)
df = pd.merge(df, df_f, left_index=True, right_index=True)
df = pd.merge(df, df_c2, left_index=True, right_index=True)
df = df[['종목명', '종가_x', '상장주식수_x', 'PBR', 'DPS', '종가_y', '상장주식수_y', '거래량']]
df.columns = ['종목명', '종가', '상장주식수', 'PBR', 'DPS', '1년후종가', '1년후상장주식수', '거래량']
df['상장주식수변동'] = df['1년후상장주식수'] - df['상장주식수']
df = df[df['PBR'] > 0] # PBR 0이상만 구하기
df['pbr_rank'] = df['PBR'].rank()
df = df[df['DPS'] > 0]
df['dps_rank'] = df['DPS'].rank()
df['pbr_dps'] = df['pbr_rank'] + df['dps_rank']
df['pbr_dps_rank'] = df['pbr_dps'].rank()
df = df.sort_values(by='pbr_dps_rank')
df = df[df['거래량'] > 0] # 거래량이 0 이상인 종목만 구하기
df = df.iloc[:30] # 종목개수
df['수익'] = df['1년후종가'] - df['종가']
df['수익'].loc[df['상장주식수변동'] < 0] = df['1년후종가'] * (1 + df['상장주식수변동'] / df['상장주식수']) - df['종가']
df['수익률'] = (df['수익'] / df['종가'])
df['투자년도'] = np.array([date] * len(df))
p = df['수익률'].mean()
result = []
result.append([date, date2, p])
df_t = pd.DataFrame(data=result, columns=['투자일', '1년후', '수익률'])
return df, df_t
# 투자 시작년도부터 마직막 년도까지 반복
def inverst_years(date_list):
for n in range(len(date_list)):
if n < len(date_list)-1:
date = date_list[n]
date2 = date_list[n+1]
if n == 0:
df_t = row_pbr_dps(date, date2)[1]
df = row_pbr_dps(date, date2)[0]
else:
df_t = pd.concat([df_t, row_pbr_dps(date, date2)[1]])
df = pd.concat([df, row_pbr_dps(date, date2)[0]])
path2 = origin_path + folder_name + '\\저PBR_DPS(' + m + '월' + d + '일)_거래량 0이상_30개_All Market.xlsx'
df.to_excel(path2)
return df_t
print(df_t)
test_days = ['4', '27'] # 매월 매수/매도일
for d in test_days:
origin_path = 'C:\\Users\\passi\\Desktop'
folder_name = '\\PBR_DPS백테스트(매월' + d + '일)거래량 0이상(30개)_All Market'
os.mkdir(origin_path + folder_name)
# 월별로 테스트를 반복하여 결과 얻기
for m in range(12):
if m == 0:
m = '01'
# 연도별 날짜 List 만들기
date_list = make_date_list(m, d)
# 백테스트 구동하기
df_t = inverst_years(date_list)
else:
m += 1
m = '0' + str(m)
m = m[-2:]
print(m)
#연도별 날짜 List 만들기
date_list = make_date_list(m, d)
#백테스트 구동하기
df_t = pd.concat([df_t, inverst_years(date_list)])
path = origin_path + folder_name + '\\저PBR_DPS 백테스트(종합 매월'+ d + '일 투자) 거래량 0이상 30개.xlsx'
df_t.to_excel(path)
|
cs |
728x90
'파이썬(Python) > 퀀트투자' 카테고리의 다른 글
파이썬 퀀트투자 쉽게하기 - 8. 모듈가져오기 (2) | 2021.12.20 |
---|---|
퀀트투자 종목 스크리닝 파이썬 코드 (0) | 2021.12.15 |
파이썬 퀀트투자 쉽게 하기 - 7. 파이썬 기초 (4) | 2021.12.13 |
파이썬 퀀트투자 쉽게하기 - 6 파이썬(Python) 설치하기 (2) | 2021.12.03 |
파이썬 퀀트투자 쉽게하기 - 5 파이썬(Python) 이란? (0) | 2021.12.01 |
댓글