http://www.yes24.com/Product/Goods/86017987?Acode=101
최근 읽은
사경인 회계사님의 재무제표 모르면 주식투자 절대하지마라.
이 책의 논리 구성은 훌륭하다.
두 파트로 나눠보면 첫 파트는 어떤 기업을 피하는 것이 좋다고 알려주신다.
첫 파트만 봐도 투자 공부에 큰 도움이 된다.
큰 수익을 얻지는 못할지언정 잘못된 기업의 주식을 골라 망하는 일은 없도록 해주니 이것만으로도 충분하다고 생각하다가도 읽다보면 이런 생각이 든다.
그럼 어떤 기업의 주식을 살 것인가?
이에 대한 설명이 두번째 파트에 담겨져 있다.
기업 가치를 측정해 현재 종가에 비해 저평가되어 있는 주식을 사는 것이 우리가 주식 시장에서 이길 수 있는 확률을 조금이나마 높이는 길이고 이 방법에 대해 알려주신다.
저자가 알려주는 기업 가치 측정 방법을 S-RIM이라고 하는데 이에 대한 설명은 아래 블로그에 잘 되어있다.
https://bricoler.tistory.com/119
여기서 측정하는 가치는 자본과 이익을 바탕으로 한다. 하지만 이렇게 계산한 기업 가치가 주가에 다 반영되어 있다고 볼 수 는 업기 때문에
실적이 좋네 => 무조건 주가 오르겠다 가즈아~
이런 식의 생각은 위험하지만 측정한 기업 가치를 바탕으로 현재 가격과 비교해보았을 때 그 차이가 크다면
어느 정도 상승해볼 것을 기대할 수 있다.
아무튼 기업가치를 측정하는 방법은 간단히 요약하면 다음과 같다.
기업가치 = 자산가치 + 초과이익의 현재가치 = 자기 자본 + 자기자본*(ROE-할인율)/할인율
이렇게 측정할 기업 가치는 현재 공시된 ROE를 이용해 계산하다.
하지만 이 수치는 어디까지나 과거 데이터이기 때문에 미래에 기업 이익이 어떻게 변할지는 모른다.
이에 대비해 할인율을 적용해 이익이 더 줄어들 상황을 가정한 기업 가치를 계산해볼 수 있다.
이렇게 적용한 가치를 기준으로 점수화한다.
예를 들면,
(1) 현재 초과이익보다 20% 줄어든 기업 가격 > 현재 종가
(초과 이익이 20% 줄어들었다고 가정한 상황보다 현재 가격이 더 싸다 = 킹 저평가)
(2) 현재 초과이익보다 10% 줄어든 기업 가격 > 현재 종가
(초과 이익이 10% 줄어들었다고 가정한 상황보다 현재 가격이 더 싸다 = 꽤 저평가)
(3) 현재 초과이익 기준 기업 가격 > 현재 종가
(초과 이익 기준 기업 가치보다 현재 가격이 더 싸다 = 저평가)
위 (1), (2), (3) 순으로 높은 점수를 부여한다.
(아래 첨부 코드에서는 실제로 높은 점수를 주는 것이 아니라 어찌됐던 (1), (2), (3) 순으로 랭킹될 수 있도록 한다.)
이렇게 현재 초과이익을 기준으로한 기업 가치보다 종가가 더 싼 300여개의 기업들을 추려내 PER, PBR, ROE를 합산한 랭킹을 매긴다.
이에 대한 평균 및 (1), (2), (3) 밴드 중 어디에 속하는지를 가지고 낸 점수를 종합해 기업을 평가한 순위를 계산해 본다.
local db에 저장해둔 재무, 실적 정보는 이렇게 생겼다.
이를 크롤링하는 코드는 따로 첨부하지는 않았다.
아래는 기업 가치를 측정하는 소스이나 원래 혼자만 해보고 기록하지는 않으려고 했던터라 주석이 친절하지 않을 수 있다.
import traceback
from lib.StockDB import *
import time
import FinanceDataReader as fdr
if __name__ == "__main__":
# 시작시간 측정
start_time = time.time()
stock_db = StockDB()
stock_db.init()
code_list = stock_db.select_all_codes()
total_summary = []
empty_finance = []
# kospi code iterate
for idx, row in enumerate(code_list):
try:
index, code, name, financial_crawl_date, daily_candle_date = row[0], row[1], row[2], row[3], row[4]
finance_list = stock_db.select_all_naver_finance(code).fillna(0)
# 컬럼 지우기 0: for row, 1: for column
finance_list = finance_list.drop('index', 1)
'''
s-rim계산에 필요한 것
1. 자본총계(지배)
2. ROE(%)
3. 발행주식수(보통주)
'''
자기자본 = finance_list.loc['자본총계(지배)']['2020/03']
ROE = (finance_list.loc['ROE(%)']['2020/03'] + finance_list.loc['ROE(%)']['2019/12']) / 2
발행주식수 = finance_list.loc['발행주식수(보통주)']['2020/03'] or finance_list.loc['발행주식수(보통주)']['2019/12'] or \
finance_list.loc['발행주식수(보통주)']['2018/12']
PER = finance_list.loc['PER(배)']['2020/03']
PBR = finance_list.loc['PBR(배)']['2020/03']
억 = 100000000
초과이익 = 자기자본 * 억 * (ROE - 7.9) / 100
적정주가가치 = 자기자본 * 억 + 자기자본 * 억 * (ROE - 7.9) / 7.9
적정주가 = 적정주가가치 / 발행주식수
할인율10가치 = 자기자본 * 억 + 초과이익 * 0.9 / (1 + 0.079 - 0.9)
적정주가_할인율10 = 할인율10가치 / 발행주식수
할인율20가치 = 자기자본 * 억 + 초과이익 * 0.8 / (1 + 0.079 - 0.8)
적정주가_할인율20 = 할인율20가치 / 발행주식수
# 가격정보
price_df = fdr.DataReader(code, '2020')
today_close = price_df[-1:]['Close'][0]
if today_close < 적정주가:
info_summary = {'name': name, 'PBR': PBR, 'PER': PER, 'ROE': ROE, '적정주가': 적정주가,
'적정주가_할인율10': 적정주가_할인율10, '적정주가_할인율20': 적정주가_할인율20}
# ROE가 채권 수익률보다 작으면 할인율 적용한 적정 주가가 오히려 더 큰 값이 나온다.
if today_close <= 적정주가_할인율20 <= 적정주가 and 적정주가_할인율20:
diff = (적정주가_할인율20 - today_close) / today_close * 100
info_summary['band'] = 1
info_summary['diff'] = diff
elif today_close <= 적정주가_할인율10 <= 적정주가 and 적정주가_할인율10:
diff = (적정주가_할인율10 - today_close) / today_close * 100
info_summary['band'] = 2
info_summary['diff'] = diff
else:
diff = (적정주가 - today_close) / today_close * 100
info_summary['band'] = 3
info_summary['diff'] = diff
total_summary.append(info_summary)
except Exception as e:
empty_finance.append(name)
print(traceback.format_exc())
print(total_summary)
print(empty_finance)
df = pd.DataFrame(total_summary)
df['BPR'] = 1 / df['PBR'].astype(float) # BPR = 1/PBR
df['1/PER'] = 1 / df['PER'].astype(float) # PER의 역수
df['RANK_BPR'] = df['BPR'].rank(method='max', ascending=False) # BPR의 순위
df['RANK_1/PER'] = df['1/PER'].rank(method='max', ascending=False) # 1/PER의 순위
df['RANK_ROE'] = df['ROE'].rank(method='max', ascending=False) # BPR의 순위
df['RANK_TOTAL'] = ((df['RANK_BPR'] + df['RANK_1/PER'] + df['RANK_ROE']) / 3 * df['band']).rank(method='max', ascending=True)
df = df.sort_values(by=['RANK_TOTAL']) # 최종 순위로 정렬
df = df.reset_index(drop=True)
df.to_excel('s-rim_kospi_result.xlsx')
print("--- %s seconds ---" % (time.time() - start_time))
코멘트할 부분은
1.코스피 상장기업들만 대상으로 수행했다.
2.가치측정에 사용한 ROE는 2020/03분기 기준이기 때문에 해당 분기에만 숫자가 커진 경우
이전 실적과 무관하게 과대평가 받는 것을 방지하기 위해 2019/12 ROE와의 평균을 계산했다.
(사실은 둘 중 한 값이 없는 경우, 다른 시점 ROE를 가져오도록 해야하고 전년동기와 비교하는게 맞을 것 같다.)
3.우선주랑 보통주랑 동일한 순위로 랭크된다.
4.위에 S-RIM 계산에 참고한 블로그 그리고 책에서도 그렇고 원래는 발생주식수에서 자기주식수를 제외한
제외한 유통주식수를 사용해아하는데 자기주식수를 구할 수 없어서 발행주식수를 그대로 사용했다.
이 때문에 기업가치가 원래 의도한 값 보다 전체적으로 더 작게 나온다.
5.현재 BBB- 등급 채권 수익률은 더 낮아졌는데 며칠전에 돌릴 때는 7.9여서 7.9를 사용했다..
(www.kisrating.com/ratingsStatistics/statics_spread.do)
이렇게 나온 엑셀 파일을 보면 이렇게 생겼다.
RANK_TOTAL을 기준으로 정렬한 순위이다.
이렇게 계산한 엑셀 파일은 다음과 같다.
+ 전체적으로 금융주들이 실적에 비해 저평가되어 있는데 그 이유에 대해 생각해보기 좋은 영상
https://www.youtube.com/watch?v=N984xDtEU1w&feature=youtu.be
+++
이렇게 s-rim을 이용해 적정가치를 계산하는 방법을 이용하다보면 이런 상황을 마주하게 된다.
원래 예상대로라면 주당 가격은 아래처럼 되어야 한다.
적정가치 > 10프로 할인가치 > 20프로 할인가치
왜냐하면 10프로,20프로 할인이라는 의미 자체가 현재 초과이익이 더 줄어들 경우
즉 앞으로 돈을 더 못벌경우 가치이므로 가치가 떨어져야 맞다.
하지만 위 상황은 반대로
할인할수록 가치가 높아지는 이상한 현상이다.
이렇게 된 이유는 ROE가 할인율보다 낮아지게 되어서 초과이익이 (-)가 되는 경우 발생한다.
즉 ROE가 BBB- 채권 금리보다 낮은 기업이므로 제외하거나 감안해서 보면 된다.
이런 경우, 사경인님은 건들지 말라고 했다고 카더라..
같이 보시면 좋을 글
2021.10.14 - [파이썬/주식] - [공지] 쉽게 따라 만드는 파이썬 주식 자동매매 시스템 출간
'파이썬 > 주식' 카테고리의 다른 글
[공지] 쉽게 따라 만드는 파이썬 주식 자동매매 시스템 출간 (197) | 2021.10.14 |
---|---|
한국신용평가 등급별금리 크롤링 python bs4 (0) | 2020.11.07 |
Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 2 (0) | 2020.06.06 |
Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 1 (0) | 2020.06.06 |
Python으로 주식 알파 찾기, Open-to-Close 전략 수행 With Backtrader 백테스팅 (0) | 2020.01.16 |
댓글