[Project] 증권사 리포트에 따라 사면 어떻게 될까??
Question
문뜩 증권사 애널리스트 말대로 사면 좋은 수익을 낼 수 있는지 의문이 들었다.
애널리스트는 직업으로 기업 분석에 모든 시간을 투자하기 때문에 개인 투자자보다
분석에 우위를 가지고 있을 것이기 때문이다.
Design
Where & Who
어떤 증권사의 애널리스트들을 선정했는지는 해당 증권사, 애널리스트 이미지에
오해의 소지를 가져올 수 있으므로 blind 처리하였다.
How
증권사 홈페이지에 게시된 리포트 종목/날짜/평가등급을 크롤링 후
dataframe으로 변경 후, 리포트 게시 날의 종목 가격, 일정 기간 후의 가격, 변화율 특성을 추가한다.
When
2019년 1월 1일 ~ 2022년 1월 1일까지 게시된 리포트를 구하고,
3개월 이후의 가격과 비교하도록 한다.
What
기간 내 10개 미만의 리포트를 쓴 애널리스트는 제외시킨다.
Develop
1) 애널리스트 이름과 각 애널리스트들의 리포트를 내역을 저장할 dataframe list 생성
name_list = ['이**' ,
'최**' ,
'박**' ,
'이**' ,
'이**' ,
'박**' ,
'안**' ,
'김**' ,
'정**' ,
'이**' ,
'김**' ,
'백**' ,
'허**' ]
analysis_list = []
2) 종목 가격을 찾는 API를 사용하려면 종목코드로 검색해야 하기 때문에 종목명 : 종목코드 dictionary 생성
stock_list = pd.DataFrame({'종목코드':stock.get_market_ticker_list(market="ALL")})
stock_list['종목명'] = stock_list['종목코드'].map(lambda x: stock.get_market_ticker_name(x))
stock_list = stock_list.set_index('종목명').T.to_dict('list')
3) 리포트 데이터들 크롤링
def analysis_crawling(name) :
# site page 별로 데이터 크롤링
df_list = []
# 애널리스트별로 page 수가 다르기 때문에 page 수를 16으로 설정
page_num = 16
# page 수만큼 다 크롤링해서 중간에 끊기는 경우 braek로 크롤링 중단
exit1 = 0
exit2 = 0
for i in range(page_num):
if exit2 == 1:
break
# 해당 url로 이동 , 19년 1월 1일 ~ 22년 1월 1일
url = "url 주소는 blind"
driver.implicitly_wait(10)
driver.get(url)
driver.implicitly_wait(10)
# table 형태의 애널리스트 리포트 데이터 추출
table = driver.find_element_by_class_name() # blind
tbody = table.find_element_by_tag_name("tbody")
rows = tbody.find_elements_by_tag_name("tr")
df = pd.DataFrame()
for k in range(3):
if exit1 == 1:
exit2 == 1
break
content = []
for index, value in enumerate(rows):
body=value.find_elements_by_tag_name("td")[k]
content.append(body.text)
# page 끝난 경우
if k == 0 :
if body.text == '조회 자료가 없습니다.':
exit1 = 1
break
# 날짜 데이터
else :
df['date'] = content
elif k == 1 : # 종목 데이터
df['stock'] = content
elif k == 2 : # 평가 등급 데이터
df['rate'] = content
# page 별로 만들어진 dataframe list에 추가
df_list.append(df)
# df_list 에 있는 page 별 report들 통합
analysis = pd.concat(df_list)
# 과거 -> 현재 순으로 정렬
analysis = analysis[::-1]
# 날짜 형식 변경
analysis["date"] = analysis["date"].str.replace(pat=r'[^\w]', repl=r'', regex=True)
return analysis
4) 날짜에 따른 가격 데이터 열 생성
def price_search(analysis, name) :
re_price = []
af_price = []
for i in range(analysis.shape[0]) :
# 종목 코드
c = stock_list.get(analysis['stock'].iloc[i])
if c == None :
re_price.append(0)
af_price.append(0)
continue
else :
c = c[0]
# 리포트 발표 날짜
re_date = analysis['date'].iloc[i]
# 주말 , 공휴일, 연휴 고려 탐색기간 5일
re_end = datetime.datetime.strptime(re_date, '%Y%m%d') + datetime.timedelta(hours=96)
re_end_str = re_end.strftime('%Y%m%d')
# 발표 날 주가 데이터
re_p = stock.get_market_ohlcv(re_date, re_end_str, c)
# 주가가 없으면 0원 처리
if re_p.shape[0] == 0 :
re_e = 0
else :
re_e = re_p['종가'].iloc[0]
# 3개월 후 주가
af_date = datetime.datetime.strptime(re_date, '%Y%m%d') + datetime.timedelta(weeks=12)
af_end = af_date + datetime.timedelta(hours=120)
# datetime -> str
af_date_str = af_date.strftime('%Y%m%d')
af_end_str = af_end.strftime('%Y%m%d')
# 발표 날 주가 데이터
af_p = stock.get_market_ohlcv(af_date_str, af_end_str, c)
# 주가가 없으면 0원 처리
if af_p.shape[0] == 0 :
af_e = 0
else :
af_e = af_p['종가'].iloc[0]
re_price.append(re_e)
af_price.append(af_e)
# 리포트 등록 날 주가, 3개월 후 주가 특성 추가
analysis['report_price'] = re_price
analysis['month_price'] = af_price
# 꼬인 index 재정렬
analysis.reset_index(inplace=True, drop=True)
# 주가 열이 0인 경우 해당 행 삭제
indexNames = analysis[ (analysis['report_price'] == 0)
| (analysis['month_price'] == 0) ].index
analysis.drop(indexNames , inplace=True)
# 3개월 변화율 특성 추가
analysis['change'] = 100 * (analysis['month_price'] - analysis['report_price']) / analysis['report_price']
# 오른 종목 수 counting
u = 0
for i in range(analysis.shape[0]):
if analysis['change'].iloc[i] > 0 :
u += 1
# report 수 대비 오른 종목 수로 점수화
print("Analysis score is : " , round(u /analysis.shape[0],3))
return analysis
Evaluation
analysis score가 가장 높은 사람의 점수는 0.635이고, 가장 낮은 사람의 점수는 0.136이다.
name : 애널리스트 이름
outperform : 리포트 중 가장 많이 오른 종목
max ratio : 가장 많이 오른 종목의 3개월 변화율
max ratio : 가장 많이 내린 종목의 3개월 변화율
mean propit ratio : 평균 수익률
analysis score : 등록한 report 대비 상승한 종목 비율
name : 이**
outperform : 카카오
max ratio : 66.75%
min profit ratio : -49.041%
mean propit ratio : 3.958%
analysis score is : 0.571
number of report : 126
name : 최**
outperform : 두산
max ratio : 57.48%
min profit ratio : -30.036%
mean propit ratio : -0.133%
analysis score is : 0.437
number of report : 119
name : 박**
outperform : 상아프론테크
max ratio : 155.446%
min profit ratio : -50.76%
mean propit ratio : 3.195%
analysis score is : 0.455
number of report : 156
name : 이**
outperform : LG전자
max ratio : 108.187%
min profit ratio : -29.924%
mean propit ratio : 9.511%
analysis score is : 0.635
number of report : 115
name : 이**
outperform : 세아베스틸
max ratio : 97.77%
min profit ratio : -40.809%
mean propit ratio : 2.034%
analysis score is : 0.481
number of report : 135
name : 박**
outperform : 신세계인터내셔날
max ratio : 40.751%
min profit ratio : -36.961%
mean propit ratio : -2.361%
analysis score is : 0.409
number of report : 225
name : 안**
outperform : 서울옥션
max ratio : 101.863%
min profit ratio : -39.627%
mean propit ratio : 4.022%
analysis score is : 0.494
number of report : 85
name : 김**
outperform : 동화기업
max ratio : 113.58%
min profit ratio : -42.105%
mean propit ratio : 2.762%
analysis score is : 0.465
number of report : 172
name : 정**
outperform : 한국금융지주
max ratio : 51.515%
min profit ratio : -33.381%
mean propit ratio : 3.65%
analysis score is : 0.574
number of report : 289
name : 이**
outperform : 카페24
max ratio : 45.206%
min profit ratio : -52.922%
mean propit ratio : -1.786%
analysis score is : 0.399
number of report : 143
name : 김**
outperform : 에코프로비엠
max ratio : 111.623%
min profit ratio : -21.259%
mean propit ratio : 11.043%
analysis score is : 0.595
number of report : 84
Name : 허**
outperform : 아이엘사이언스
max ratio : 37.072%
min profit ratio : -36.853%
mean propit ratio : -12.564%
analysis score is : 0.136
number of report : 22
Feedback
사실은 각 애널리스트 저마다 올리는 리포트의 섹터가 다르다
score가 높은 사람은 해당 기간 동안 해당 섹터가 선방했기 때문에 점수가 높은 것이고,
score가 낮은 사람은 그 반대이다.
또한 대부분의 애널리스트의 점수가 0.5 근처인 것을 보았을 때,
내부자 정보를 알지 않는 이상 아무리 분석을 많이 한 사람이라도 주가의 향방 타이밍은 알 수가 없다.
애널리스트는 기업의 내제 가치를 평가하는 사람일 뿐 기업의 미래를 아는 사람은 아니다.
피터 린치의 명언으로 마무리
'Quant' 카테고리의 다른 글
Finance 참고 블로그 (27) | 2022.03.20 |
---|---|
[Quant Strategy] NCAV 전략 - 2022.03.16 기준 (12) | 2022.03.17 |
[Quant Strategy] Pair Trading with Long/Short (17) | 2022.02.20 |
Project : Price and EPS NTM (1) | 2021.12.09 |
[금융상품] 채권 (18) | 2021.10.26 |