- 책 내용을 계속 따라가고 있다. 앞 내용이 궁금하시다면 맨 아래 포스팅들을 참고부탁드립니다. (핀터스텔라 만세)
● ROA ROE RIM GP/A
우량주는 기업 자체의 수익성이 좋은지 안전한지 등을 따지는 개념이다. 수익성과 안전성을 판단한다. 이 중에는 고평가 된 것이 있을 수도 있고 저평가된 것이 있을 수도 있다.
분석하는 방법이 사람마다 다르지만 투자 효율이 좋은 기업을 판단해 볼 수 있다. 1억 원을 벌어도 10억 원을 투자한 기업과 100억 원을 투자한 기업의 효율은 10억 원의 1억이 더 큰 셈인 것이기 때문이다.
ROA는 Return on Asset의 약자로 (당기순이익) / (평균 총 자산)으로 평가된다. (자산은 부채 + 자본의 합) ROE는 순자산인 자본으로 평가하는데 (당기순이익) / (평균총자본)으로 평가된다.
ROA와 ROE의 차이는 기업이 레버리지를 얼마나 잘 활용하는지 보여주는 것이고, ROE/ROA = 레버리지 비율로 볼 수 있다. ( * (당기순이익)/(평균총자본) = (당기순이익)/(평균총자산) * (평균총자산)/평균총자본) = (당기순이익)/(평균총자산) * (자본+부채)/(평균총자본) = ROA * (레버리지 비율) )
ROA는 비슷한데, ROE가 큰 기업이면 그 기업은 부채를 잘 활용하는 기업이다. ROE와 부채비율은 양날의 검인 긴 하다. 무조건 크다고 좋은 것은 아님. TXN으로 체크해 보자
pip install finterstellar
import finterstellar as fs
df=fs.fn_single(otp='OTP', symbol='TXN', window='T')
ROA에는 Net income (수익), Total Assets(자산)가 필요하고 ROE에는 Net Income과 Share holders equity(자본)가 필요하다.
fs.draw_chart(df,left=['Total Assets','Shareholders Equity'],right='Net Income')
ROA와 ROE를 구하기 전에, 자산의 기초자산과 기말자산의 평균값을 구해야 한다. 분기별로 회계자료를 산출하는데, 있는 그대로의 숫자를 사용하면 오류가 생길 수 있어서 통상 위와 같이 계산한다고 한다.
#전년도 총 자산, 최근 5개 분기 도시
df['Total Assets'].tail()
#shift 함수로 데이터프레임의 데이터를 괄호 안에 표시한 숫자 만큼 밀어냄
df['Total Assets'].shift(4).tail()
#기초 자산과 기말자산의 평균값 구하기
df['Avg Assets'] = (df['Total Assets'] + df['Total Assets'].shift(4) ) /2
#ROA 계산
df['ROA']=df['Net Income']/df['Avg Assets']
#ROA와 수익과 자산 dataframe 값 확인
df[['ROA','Net Income','Avg Assets']].tail()
#ROA와 주가 확인
fs.draw_chart(df, left='ROA', right='Price')
TXN 같은 경우는 ROA와 주가와의 연관성이 조금 있어 보인다. ROE도 비슷한 방법으로 구하면 된다.
#전년도 총 자산, 최근 5개 분기 도시
df['Total Assets'].tail()
#shift 함수로 데이터프레임의 데이터를 괄호 안에 표시한 숫자 만큼 밀어냄
df['Total Assets'].shift(4).tail()
#기초 자본과 기말자본의 평균값 구하기
df['Avg Equity'] = (df['Shareholders Equity'] + df['Shareholders Equity'].shift(4) ) /2
#ROE 계산
df['ROE']=df['Net Income']/df['Avg Equity']
#ROA와 수익과 자산 dataframe 값 확인
df[['ROE','Net Income','Avg Assets']].tail()
#ROE와 주가 확인
fs.draw_chart(df, left='ROE', right='Price')
TXN 같은 경우에는 ROE와 주가와의 관계도 꽤 연관성이 있다. ROA와 ROE가 높은 상위 종목에 투자하는 아이디어로 전략을 짜서 백테스트를 돌려보자.
terms=fs.set_terms(trade_start='2011Q1', trade_end='2023Q1')
data={}
for t in terms :
data[t]=fs.fn_consolidated(otp='otp',term=t)
#prev_t에다가 quarters_before()함수를 이용해 4분기 전 값을 받아옴
for t in terms:
prev_t=fs.quarters_before(terms, t, 4)
data[t]['Avg Assets']= (data[t]['Total Assets'] + data[prev_t]['Total Assets'])/2
data[t]['ROA']=data[t]['Net Income'] / data[t]['Avg Assets']
#수익 자산 ROA 중에 하나라도 0이면 nan으로 처리함.
data[t].loc[(data[t]['Net Income']<0) | data[t]['Avg Assets']<0 | (data[t]['Total Assets']<0), 'ROA'] = float('nan')
s= {}
signal = {}
for t in terms :
s[t] = fs.fn_filter(data[t],by='ROA',floor=0,n=30,asc=False)
signal[t] =list(s[t].index)
#백테스트
df=fs.backtest(signal=signal, data=data, m=3, cost=0.001)
CAGR: 2.08%
Accumulated return: 28.11%
Investment period: 12.0yrs
Sharpe ratio: 0.11
MDD: -27.74%
그저 그런 수익률과 전략이다. ROA 높은 종목 30개를 모아서 3개월마다 리벨런싱을 해줬는데, 12년에 연평균 복리수익률 2.08%라니, 예금이 훨씬 이득이다.
ROE로도 결과를 확인해 보자
for t in terms:
prev_t=fs.quarters_before(terms,t,4)
data[t]['Avg Equity'] = (data[t]['Shareholders Equity']+data[prev_t]['Shareholders Equity'])/2
data[t]['ROE']=data[t]['Net Income'] / data[t]['Avg Equity']
data[t].loc[(data[t]['Net Income']<0) | data[t]['Avg Equity']<0 | (data[t]['Shareholders Equity']<0), 'ROE'] = float('nan')
s[t]=fs.fn_filter(data[t], by='ROE',floor=0, n=30, asc=False)
signal[t] = list(s[t].index)
df=fs.backtest(signal=signal, data=data, m=3, cost=0.001)
CAGR: 21.81%
Accumulated return: 968.63%
Investment period: 12.0yrs
Sharpe ratio: 2.47
MDD: -26.65%
ROE로 30개 종목을 추려 투자를 했으면 투자 성과가 매우 상당히 좋다. signal 데이터 프레임을 쳐보면 각 분기에 어떤 종목을 가지고 있어야 하는지 나오게 된다. 가끔 아는 기업이 나오기도 하는데, 대부분 모르는 기업이다. 아마도 부채비율이 높은 중소형 기업이 많이 섞여 있어서 그런 것 같다.
● RIM(잔여이익모델)
RIM은 Residual Income Model이라고 하는데, 사경인 회계사가 유행시킨 방법이다. BBB-등급 채권의 5년 수익률을 기준으로 하여 기업의 주가를 산정하는 방식이다. 초과이익은 기업의 이익에서 자본 조달비용을 뺀다면 초과이익이라고 일단 산정할 수 있다. (번 돈에서 내가 넣은 돈을 뺀 값)
초과이익 = 이익 - 자본조달비용
이렇게 구한 초과이익은 기업에 계속 쌓이게 되는데, 기업의 가치는 현재 가진 자본에 앞으로 쌓아갈 초과이익을 더한 값이라고 계산할 수 있다.
기업가치 = 자본 + 초과이익
초과이익은 계속 발생할 테니, 앞으로 발생할 이익을 모두 더해주어 현재 가치로 환산하여 더해준다. 내가 돈을 그냥 BBB-등급 채권 5년에다가 넣으면 그 목표수익률을 얻을 것이니, 그것을 목표수익률로 하여 현재가치로 초과수익을 환산한다.
기업가치 = 자본 + 초과수익/목표수익률
기업가치 = 자본 +(이익 - 자본조달비용)/목표수익률
이때, 원래 자본에 자본의 이익률을 곱하면 이익이고 (이익 = 자본*자본이익률), 자본조달비용을 기업 하지 말고 그냥 채권에 놔두었으면 얻을 수 있는 자본조달비용은 자본*목표수익률이라고 치환할 수 있다고 한다고 이해했다.
= 자본 + ((자본 x자본이익률) - (자본 x목표수익률))/(목표수익률)
= 자본 + (자본*자본이익률)/목표수익률 - (자본 x목표수익률)/목표수익률
= 자본*자본이익률/목표수익률
여기서 양 변을 주식 수로 나누면
기업가치/주식수 = 자본/주식수 * 자본이익률/목표수익률
적정주가 = (주당 순자산) * 자본이익률 / 목표수익률
적정주가 = BPS* 자본이익률/목표수익률
자본/주식수과 (자산+부채)/주식수가 조금 다른 것 같긴 하지만 책에서는 이렇게 소개하고 있다. 여기서, RIM의 강점은 BPS와 자본이익률(ROE)로 단순히 계산할 수 있다는 점인데, 단점은 ROE를 어떤 값을 사용하느냐에 따라 값에 큰 영향을 미친다. (3년 or 5년 or 1년 등)
이번 지표 산출은 나의 아픈 손가락 월트디즈니로 해보겠다.
df=fs.fn_single(otp='OTP',symbol='DIS',window='T')
df['BPS']=df['Shareholders Equity']/ df['Shares']
df['ROE']=df['Net Income'] / df['Shareholders Equity']
#ROE를 3년간 이동평균을 구해서 좀 더 안정적인 수치를 갖다 쓰자
#rolling(12)는 여기서 1이 분기단위의 데이터라 3년치면 12분기가 필요해서 그렇다.
#수익률 10%부터 6%까지 그려서 BAND로 그래프 그려보기
df['ROE3AVG']=df['ROE'].rolling(12).mean()
df['RIM']=df['BPS']*df['ROE3AVG']/0.1
df['RIM6']=df['BPS']*df['ROE3AVG']/0.06
df['RIM7']=df['BPS']*df['ROE3AVG']/0.07
df['RIM8']=df['BPS']*df['ROE3AVG']/0.08
fs.draw_chart(df,right=['Price','RIM','RIM6','RIM7','RIM8'])
RIM을 이용하여 적정주가보다 실제 주가가 낮으면 주가가 저평가된 상태로 매수하고 그렇지 않으면 매도하는 전략으로 백테스트를 해본다.
terms=fs.set_terms(trade_start='2011Q1', trade_end='2023Q1')
data={}
for t in terms :
data[t]=fs.fn_consolidated(otp='otp',term=t)
s={}
signal={}
for t in terms :
#1년전 data
t_1 = fs.quarters_before(terms, t, 4)
#2년전 data
t_2 = fs.quarters_before(terms, t, 8)
#BPS 구하기
data[t]['BPS']=data[t]['Shareholders Equity'] / data[t]['Shares']
#자본 평균
data[t]['Avg Equity'] = (data[t]['Shareholders Equity']+data[t_1]['Shareholders Equity'])/2
#ROE구하기
data[t]['ROE']=data[t]['Net Income'] / data[t]['Avg Equity']
#0되면 뺴는 예외처리
data[t].loc[(data[t]['Net Income']<0) | (data[t]['Avg Equity']<0) | (data[t]['Shareholders Equity']<0), 'ROE'] = float('nan')
#ROE의 평균 구하기 위함, 3년치 ROE의 평균
data[t]['Avg ROE'] = ( data[t]['ROE'] + data[t_1]['ROE'] + data[t_2]['ROE']) /3
#목표수익률 10%로 하여 RIM구함
data[t]['RIM'] = data[t]['BPS'] * data[t]['Avg ROE'] /0.1
#가격/RIM 하는 시그널에 쓸 재료
data[t]['P/RIM']=data[t]['Price_M3'] / data[t]['RIM']
#30개 종목추리기
s[t]=fs.fn_filter(data[t], by='P/RIM', floor=0, cap=1, n=30, asc=True)
signal[t] = list(s[t].index)
#백테스트
df=fs.backtest(signal=signal, data=data, m=3, cost=0.001)
뭐.. 그냥 그런 수준이 나왔다.
CAGR: 5.99%
Accumulated return: 101.12%
Investment period: 12.0yrs
Sharpe ratio: 0.34
MDD: -36.07%
댓글