-
하나금융투자 Weekly Talk의 추천주 믿어도 될까?재테크 2021. 6. 27. 22:22
TL;DR
하나금융투자 Weekly Talk 추천주는 2019년 동안 코스피 지수를 초과하는 수익률을 냈다.
얼마 전 기릿의 주식 노트라는 유튜브 채널에서 하나금융투자의 Weekly Talk의 추천주를 바탕으로 1달 동안 추천한 주식들이 진짜 좋은 성과를 거두었는지에 대한 영상을 여러 편 올렸다. 해당 영상에서도 꽤 의미 있는 수익률을 거두었다고 생각하여 실제 긴 시간대에서도 추천주가 의미 있는 성과를 거둘까? 에 대한 궁금증이 생겼고 2019년 동안의 추천 리포트를 바탕으로 동기간 코스피 지수에 비해 초과 성과를 거두었는지에 대한 백테스팅을 해보기로 했다.
데이터 수집
먼저 2019년 데이터를 사용한 이유는 2020년은 코로나 시국에 의하여 전례 없는 주가의 이동이 있었다고 생각하여 주가 변동폭이 더 작은 년도를 선택하게 되었다. 데이터를 수집하기 위하여 한경 컨센서스 사이트에서 검색하여 2019년 1월 2일 데이터부터 2019년 12월 23일 데이터까지 일일이 PDF를 열어서 종목을 확인하고 아래와 같이 시트에 종목을 작성하여 csv 파일로 저장하였다.
주가 데이터를 수집하기 위해서는 지난 포스팅을 참고로 하여 2019년 1월 1일부터 400일간의 데이터를 받아서 저장하였다.
백테스팅 방법
단순히 양의 수익률을 내는 것보다는 reference라고 할 수 있는 코스피 지수의 수익률을 초과하는 것이 의미가 있기 때문에, 추천주를 소개한 리포트가 나온 날을 기점으로 N일 후에 추천 종목들의 가격에 대한 수익률을 계산하고 똑같은 기간 동안의 코스피 지수 변화율을 따로 계산했다. 리포트에는 단기 추천 종목이라고만 나와 있기 때문에 얼마 동안 주식을 보유하고 있어야 하는지 알 수 없었고 7일 ~ 34일 기준에 대해서 모든 추천주 수익률의 평균 그리고 코스피 지수 수익률의 평균을 구하였다.
결과
2019년 [07일 기준] - 추천주 평균 수익률: 0.90%, KOSPI 평균 수익률: 0.27% 2019년 [08일 기준] - 추천주 평균 수익률: 1.09%, KOSPI 평균 수익률: 0.36% 2019년 [09일 기준] - 추천주 평균 수익률: 1.15%, KOSPI 평균 수익률: 0.33% 2019년 [10일 기준] - 추천주 평균 수익률: 1.14%, KOSPI 평균 수익률: 0.28% 2019년 [11일 기준] - 추천주 평균 수익률: 1.19%, KOSPI 평균 수익률: 0.30% 2019년 [12일 기준] - 추천주 평균 수익률: 1.25%, KOSPI 평균 수익률: 0.42% 2019년 [13일 기준] - 추천주 평균 수익률: 1.27%, KOSPI 평균 수익률: 0.48% 2019년 [14일 기준] - 추천주 평균 수익률: 1.18%, KOSPI 평균 수익률: 0.44% 2019년 [15일 기준] - 추천주 평균 수익률: 1.43%, KOSPI 평균 수익률: 0.65% 2019년 [16일 기준] - 추천주 평균 수익률: 1.77%, KOSPI 평균 수익률: 0.59% 2019년 [17일 기준] - 추천주 평균 수익률: 1.58%, KOSPI 평균 수익률: 0.57% 2019년 [18일 기준] - 추천주 평균 수익률: 1.82%, KOSPI 평균 수익률: 0.76% 2019년 [19일 기준] - 추천주 평균 수익률: 1.63%, KOSPI 평균 수익률: 0.75% 2019년 [20일 기준] - 추천주 평균 수익률: 1.61%, KOSPI 평균 수익률: 0.75% 2019년 [21일 기준] - 추천주 평균 수익률: 1.75%, KOSPI 평균 수익률: 0.79% 2019년 [22일 기준] - 추천주 평균 수익률: 1.84%, KOSPI 평균 수익률: 1.01% 2019년 [23일 기준] - 추천주 평균 수익률: 1.88%, KOSPI 평균 수익률: 1.09% 2019년 [24일 기준] - 추천주 평균 수익률: 1.62%, KOSPI 평균 수익률: 0.90% 2019년 [25일 기준] - 추천주 평균 수익률: 1.86%, KOSPI 평균 수익률: 1.00% 2019년 [26일 기준] - 추천주 평균 수익률: 1.59%, KOSPI 평균 수익률: 0.84% 2019년 [27일 기준] - 추천주 평균 수익률: 1.64%, KOSPI 평균 수익률: 0.84% 2019년 [28일 기준] - 추천주 평균 수익률: 1.75%, KOSPI 평균 수익률: 0.97% 2019년 [29일 기준] - 추천주 평균 수익률: 1.99%, KOSPI 평균 수익률: 0.98% 2019년 [30일 기준] - 추천주 평균 수익률: 2.08%, KOSPI 평균 수익률: 0.98% 2019년 [31일 기준] - 추천주 평균 수익률: 2.01%, KOSPI 평균 수익률: 0.88% 2019년 [32일 기준] - 추천주 평균 수익률: 3.06%, KOSPI 평균 수익률: 0.66% 2019년 [33일 기준] - 추천주 평균 수익률: 1.71%, KOSPI 평균 수익률: 0.70% 2019년 [34일 기준] - 추천주 평균 수익률: 1.69%, KOSPI 평균 수익률: 0.69% 최고 수익을 내는 단기 투자기간: 32일, 투자 기간 평균 투자수익률: 3.06%
사실 이 백테스팅을 준비하는 동안 전혀 기대하지 않았었는데, 전 보유 기간에 대한 구간에서 코스피 지수를 초과하는 수익률을 냈다. 그리고 32일간 보유했다고 했을 때 (데이터에 의한 편향은 있겠지만) 무려 평균 3%가 넘는 수익률을 거두었다. 3%는 피크 값이라고 생각하여 적당히 월 1.8%의 평균 수익률이라고 가정하더라도 연 단위로 보면 23.8%의 수익률로 엄청난 성과를 보여주는 것을 확인할 수 있다. 2019년은 지수가 오르는 기간이었고 하락장에서의 성과는 어떨지 모르지만 적어도 하나금융투자의 추천 종목은 무시할 수 없는 정보라고 생각한다. 이 결과는 1년이라는 짧은 기간 동안의 데이터이고 데이터 처리 과정에서 오류가 있을 수 있으므로 수동적으로 추천주를 매매하는 것은 추천하지 않는다. 그 대신 그들의 논리를 공부하여 능동적으로 투자 결정에 활용하는 것이 좋다고 생각한다.
구현
Python 3.6을 기반으로 하였으며 내장 패키지 외에 gspread 패키지를 사용하여 google sheet를 통해 데이터를 수집하였다.
코스피와 코스닥 중 어떤 종목인지를 리포트에 나온 종목명만으로는 알 수가 없어서 먼저 코스피 기준(KRX)으로 검색해보고 결과 값이 제대로 안돌아오면 코스닥 기준(KOSDAQ)으로 다시 검색해서 사용하였다. 또한 google spread sheet API가 100초당 100 requests에 대한 제한이 있기 때문에 안전하게 수집하기 위하여 API 사용마다 2초간의 지연 시간을 두고 수집하도록 하였다.
import csv import os import json import time import datetime import gspread from statistics import mean # 추천 종목 csv 파일을 통하여 gspread를 통해 주가 데이터를 저장 def save_recommends(sh): with open('weekly_talk.csv', 'r') as f: lines = csv.reader(f) next(lines) keys = set() for line in lines: name, ticker = line[2:] keys.add((name, ticker)) for name, ticker in keys: save_price_data(sh, ticker, name, 2019, 1, 1) save_price_data(sh, 'KOSPI', 'KOSPI', 2019, 1, 1) # Ticker 정보를 통하여 특정 기간동안의 날짜 데이터를 가져와서 json 파일로 저장 def save_price_data(sh, ticker, name, year, month, day): print(f'Save data: {name}: {ticker}') time.sleep(2) sh.clear() # KOSPI 데이터 로드 values = load_price_values(sh, ticker, year, month, day) # KOSPI에 없는 종목은 KOSDAQ에서 로드 if len(values) < 2: values = load_price_values(sh, ticker, year, month, day, platform='KOSDAQ') ret = {} for value in values[1:]: year, month, day, _, __ = value[0].split(' ') price = value[1] ret[f'{year[:-1]}/{month[:-1]}/{day}'] = price with open(f'data/{ticker}_{name}.json', 'w') as df: json.dump(ret, df) # googlefinance 함수를 통하여 주가 데이터를 시작 날짜를 기준으로 400일간 받아서 값을 가져옴 def load_price_values(sh, ticker, year, month, day, platform='KRX'): start_date = datetime.datetime(year, month, day) end_date = start_date + datetime.timedelta(days=400) query = ( f'=googlefinance("{platform}:{ticker}", "price", "{year}. {month}. {day}", ' f'"{end_date.year}. {end_date.month}. {end_date.day}", "DAILY")' ) time.sleep(2) sh.update_cell(1, 1, query) time.sleep(2) return sh.get_all_values() # json 파일로 저장된 주가 데이터를 로드 def load_stocks(): ret = dict() for path in os.listdir('./data'): ticker, name = os.path.splitext(path)[0].split('_') with open(f'./data/{path}', 'r') as f: data = json.load(f) ret[(ticker, name)] = data return ret # 주가 데이터의 특정 종목에 대하여 특정 날짜의 가격과 # 그 날로 부터 특정 보유기간 (offset_days) 후의 가격을 가져와서 수익률을 계산 def obtain_return_rate(stocks, ticker, name, year, month, day, offset_days): start_price = None end_price = None start_date_key = '' end_date_key = '' offset = 0 stock = stocks[(ticker, name)] while start_price is None: delta = datetime.timedelta(days=offset) date = datetime.datetime(year, month, day) + delta date_key = f'{date.year}/{date.month}/{date.day}' if date_key in stock: start_date_key = date_key start_price = float(stock[date_key]) else: offset += 1 offset = offset + offset_days while end_price is None: delta = datetime.timedelta(days=offset) date = datetime.datetime(year, month, day) + delta date_key = f'{date.year}/{date.month}/{date.day}' if date_key in stock: end_date_key = date_key end_price = float(stock[date_key]) else: offset += 1 return_rate = (end_price - start_price) / start_price print(f'티커: {ticker}, 종목: {name}, 날짜: {start_date_key}, ' f'가격: {start_price:.0f}, {offset_days}일 후 날짜: {end_date_key}, ' f'가격: {end_price:.0f}, 변동률: {return_rate:.3f}') return return_rate # 특정 보유기간 동안 추천 종목을 보유했을 때 예상 수익률과 같은 기간 동안의 코스피 지수 수익률을 계산 def simulate(stocks, offset): return_rates = [] refer_rates = [] with open('weekly_talk.csv', 'r') as f: lines = csv.reader(f) next(lines) for line in lines: month, day, name, tick = line month = int(month) day = int(day) try: return_rate = obtain_return_rate(stocks, tick, name, 2019, month, day, offset) refer_rate = obtain_return_rate(stocks, 'KOSPI', 'KOSPI', 2019, month, day, offset) return_rates.append(return_rate) refer_rates.append(refer_rate) except Exception as e: print(e) print(f'오류 발생: 2019-{month}-{day}, {tick}, {name}') print(f'2019년 [{offset:0>2}일 기준] - ' f'추천주 평균 수익률: {mean(return_rates) * 100:.2f}%, ' f'KOSPI 평균 수익률: {mean(refer_rates) * 100:.2f}%') return mean(return_rates) if __name__ == '__main__': gc = gspread.service_account(filename='./service_account.json') sh = gc.open('gspread-test').sheet1 save_recommends(sh) stocks = load_stocks() max_return_rate = 0 max_offset = -1 # 7일 ~ 34일간의 보유 기간에 따른 추천 종목의 평균 수익률을 계산 for offset in range(7, 35): return_rate = simulate(stocks, offset) if return_rate > max_return_rate: max_return_rate = return_rate max_offset = offset print(f'최고 수익을 내는 단기 투자기간: {max_offset}일, ' f'투자 기간 평균 투자수익률: {max_return_rate * 100:.2f}%')
'재테크' 카테고리의 다른 글
신고가 매매는 얼마나 통할까? (0) 2021.08.23 MSCI 편입/편출 종목 매매는 효과적일까? (0) 2021.08.14 주가 데이터 자동으로 가져오기 (gspread 이용) (1) 2021.06.22 삼성전자 주식 조금이라도 싸게 모을 수 있을까? (2) - RSI 보조지표의 활용 (0) 2021.03.01 삼성전자 주식 조금이라도 싸게 모을 수 있을까? (0) 2021.01.31