주식투자

[파이썬 분석 20] 인플레이션을 고려해 보자 (한국은행 소비자물가지수 데이터 사용)

오렌지사과키위 2025. 4. 24. 16:36

장기 투자 성과 분석에서는 물가가 상승하는 인플레이션(inflation)을 충분한 수준으로 고려해야 합니다. 20년 후 자산의 명목 가격이 4배로 불어났다고 하더라도, 물가가 2배로 올랐다면, 자산의 실질 가치는 2배에 불과하기 때문입니다. 수익률로 보면 그 차이는 더 커집니다. 4배로 오른 자산은 명목으로는 300%에 해당하는 수익률이지만, 실질 가치 2배의 실질 수익률은 100%에 그치기 때문입니다.

이 글에서는 한국은행 인플레이션 데이터를 이용하여 장기 투자에서 자산 가격을 보정하여 계산하는 방법을 설명합니다.

주의: 이 글은 특정 상품 또는 특정 전략에 대한 추천의 의도가 없습니다. 이 글에서 제시하는 수치는 과거에 그랬다는 기록이지, 앞으로도 그럴 거라는 예상이 아닙니다. 분석 대상, 기간, 방법에 따라 전혀 다른 결과가 나올 수 있습니다. 데이터 수집, 가공, 해석 단계에서 의도하지 않은 오류가 있을 수 있습니다. 일부 설명은 편의상 현재형으로 기술하지만, 데이터 분석에 대한 설명은 모두 과거형으로 이해해야 합니다.

한국은행 소비자물가지수 데이터

한국의 누적 인플레이션에 해당하는 소비자물가지수(Consumer Price Index: CPI)는 FinanceDataReader에서 'ECOS-KEYSTAT:K401'를 키(key)로 가져올 수 있습니다. FinanceDataReader로 가져올 수 100가지 한국은행 통계지표 데이터를 참고하기 바랍니다.

cpi_s = fdr.DataReader('ECOS-KEYSTAT:K401').iloc[:, 0]
cpi_s.plot()

fdr.DataReader()의 결과는 DataFrame이며, 그중에서 첫 번째 칼럼만 꺼내기 위해 iloc[:, 0]를 사용했습니다. 결과는 Series가 됩니다.

한국의 소비자물가지수

소비자물가지수는 5년마다 100으로 정규화합니다. 특정일이 아닌 해당년도 평균입니다. 지금의 소비자물가지수는 2020년을 100으로 두고 산출한 것입니다. 

1994년에 대략 50이었고, 2019년에 100이 되었습니다. 25년 동안 물가가 2배로 증가했다는 의미입니다. 그래프를 보면 기간에 따라 선형으로 증가해 온 것처럼 보입니다. 이는 물가가 오른 품목도 있지만, 공산품의 경우 가격이 하락하는 경우도 있기 때문입니다.

정부에 발표하는 인플레이션 수치는 개인이 체감하는 것과 상당한 차이가 있을 수 있습니다. 예를 들어 전세로 거주하는 사람의 경우 전세금 상승이 피부로 느끼는 물가에 큰 영향을 미칠 수 있습니다. 이 때문에 투자자는 각자 자신에 상황을 고려하여 인플레이션을 추정했야 합니다. 대개의 생각과는 달리 인플레이션은 주관적인 개념입니다. 이 글에서는 일반적으로 사용하는 소비자물가지수를 인플레이션으로 가정합니다.

소비자물가지수는 다음과 같이 매월 1일을 기준으로 설정되어 있습니다.

매월 1일을 기준으로 표시된 소비자물가지수

2025년 3월 1일자 마지막 데이터로 116.29로 입력되어 있습니다. 기준이 되는 5년 전 2020년에 비해 물가가 대략 16% 상승했다는 의미입니다. 표에는 2025년 3월 1일자로 표시되어 있지만, 이 수치는 3월 10일 ~ 20일 사이에 조사한 것입니다.

소비자물가지수와 같은 지표는 수집하여 공표되는데 시간이 걸립니다. 이 글을 쓰는 오늘 날짜는 2025년 4월 24일입니다. 4월치 데이터는 아직 발표되지 않았기에 확인할 수 없습니다. 소비자물가지수는 매월 첫 영업일에 발표됩니다.

참고: 지표마다 계산 시점, 계산 방식 및 공표 시점이 다를 수 있습니다. 지표의 변화에 민감한 투자 전략을 사용하는 경우라면 해당 지표가 어떻게 만들어지는지 확인할 필요가 있습니다. 이 글에서 다루는 소비자물가지수는 갑작스러운 큰 변동이 없다고 가정하고 해당 데이터는 해당 일자의 수치라 간주합니다.

빈 날짜 데이터 채우기

소비자물가지수와 같은 데이터를 사용하기 위해서는 비어있는 날짜에도 값을 채워야 합니다. 이를 내삽(interpolation)과 외삽(extraplolation)이라고 합니다. 내삽은 빈 값 양쪽으로 값이 있는 경우이고, 외삽은 어느 한쪽만 있는 경우입니다. 소비자물가지수는 두 가지를 모두 해야 합니다.

다음은 일자별 소비자물가지수를 채우는 코드입니다.

from datetime import date

infl_df = pd.DataFrame()
infl_df.index = pd.date_range(cpi_s.index.min(), date.today())
infl_df['CPI'] = cpi_s
infl_df['iCPI'] = infl_df.CPI.interpolate(method = 'slinear', fill_value = "extrapolate")

infl_df['2024':].iCPI.plot()
plt.scatter(infl_df.index, infl_df.CPI)

plt.ylim(110)
plt.show()

처음 보는 부분 위주로 설명합니다.

infl_df = pd.DataFrame()
infl_df.index = pd.date_range(cpi_s.index.min(), date.today())

빈 DateFrame을 하나 만들고, 소비자물가지수 데이터의 첫 날짜부터 오늘까지 하루 단위로 색인(인덱스, index)을 만듭니다. infl_df는 색인으로 날짜만 있는 DateFrame이 됩니다.

infl_df['CPI'] = cpi_s
infl_df['iCPI'] = infl_df.CPI.interpolate(method = 'slinear', fill_value = "extrapolate")

한국은행 소비자물가지수 데이터를 CPI 칼럼에 넣습니다. 해당 날짜 데이터가 없는 경우에는 NaN으로 채워지게 됩니다. CPI 데이터를 slinear(linear spline) 방식으로 채워 넣습니다. fill_value는 extraploate로 지정했기에 외삽도 함께 이루어집니다.

2024년 이후 데이터를 그려보면 다음과 같습니다.

날짜별로 내삽과 외삽이 이루어진 소비자물가지수

그래프에서 점은 실제 데이터가 주어진 경우이고, 선은 추정치입니다. 2025년 3월 이후에도 추정치가 있습니다. 전월 값의 변동을 이용하여 선형으로 추정한 결과입니다.

환율과 인플레이션을 고려한 누적 수익률 추정

이제 환율과 인플레이션을 고려해서 누적 수익률 그래프를 그려봅니다.

spy_s = fdr.DataReader('SPY')['Adj Close']
usdkrw_s = fdr.DataReader("ECOS-KEYSTAT:K152").iloc[:, 0]

spy_krw_s = spy_s * usdkrw_s
spy_ikrw_s = spy_krw_s / infl_df.iCPI

df = pd.concat([spy_s, spy_krw_s, spy_ikrw_s], axis = 1).dropna()
df.columns = ['SPY (USD)', 'SPY (KRW)', 'SPY (iKRW)']
df /= df.iloc[0]

df.plot()

plt.yscale('log', base = 1.1)

yticks = np.array([-0.2, 0, 1, 2, 5, 10, 30] + (df.iloc[-1] - 1).to_list() * 2)
plt.yticks(ticks = yticks + 1,
           labels = [f'{round(tick * 100)}%' for tick in yticks])

plt.show()

이전 글에서 설명한 부분은 생략합니다.

spy_krw_s = spy_s * usdkrw_s
spy_ikrw_s = spy_krw_s / infl_df.iCPI

달러 기준 SPY 가격에 환율을 곱해 원화 가격으로 환산했습니다. 환산된 SPY 원화 가격을 소비자물가지수로 나눠 명목 가격을 실질 가치로 변환하였습니다.

df = pd.concat([spy_s, spy_krw_s, spy_ikrw_s], axis = 1).dropna()
df.columns = ['SPY (USD)', 'SPY (KRW)', 'SPY (iKRW)']
df /= df.iloc[0]

SPY의 달러 명목 가격, 원화 명목 가격, 원화 실질 가격을 합해 하나의 DataFrame으로 만들고 칼럼명을 붙였습니다. 각 데이터는 1로 시작하도록 정규화(normalize)하였습니다.

yticks = np.array([-0.2, 0, 1, 2, 5, 10, 30] + (df.iloc[-1] - 1).to_list() * 2)

각 칼럼의 최종 수익률을 굵은 글자로 그래프 눈금값으로 표시하도록 지정했습니다.

인플레이션을 고려한 SPY의 누적 수익률 추이

SPY가 상장된 시점에 거치식으로 투자했다면, 약 32년 3개월간 SPY는 달러로는 2,090% 수익률을 얻었고, 원화로는 3,816% 수익률을 거두었습니다. 인플레이션을 고려하면 3,816% 명목 수익률은 절반 이하인 1,434%로 실질 수익률로 줄어듭니다.

CAGR을 계산해 보면 다음과 같습니다.

years = (df.index.max() - df.index.min()).days / 365.25
((df.iloc[-1] ** (1 / years) - 1) * 100).round(1)

인플레이션을 고려한 SPY의 CAGR

SPY의 달러 가격은 연 10.0% 명목 성장했지만, 환율 상승으로 인해 원화로는 연 12.1% 명목 성장했습니다. 하지만 인플레이션이 고려되면 연 8.8% 성장하는데 그쳤습니다. 명목 성장비를 실질 성장비로 나누면 평균 인플레이션을 추정할 수 있습니다. (1 + 12.1%) / (1 + 8.8%) - 1 ≒ 2.9%입니다. 연평균 2.9% 정도 인플레이션 발생했다고 볼 수 있습니다.

정리하며

장기 투자 성과 분석에서는 합리적인 수준으로 인플레이션을 고려해야 합니다. 장기간 투자 후 기대와는 사뭇 다른 수익률을 얻을 수 있기 때문입니다. 이 글에서는 한국은행 소비자물가지수를 인플레이션으로 두고 명목 가격을 실질 가격으로 환산하여 투자 성과를 추정하는 방법을 소개하였습니다.

장기 투자자는 인플레이션만 고려해서는 안 됩니다. 지금까지는 거치식 투자를 가정하고 투자 성과를 분석했지만, 많은 투자자들은 적립식이 현실적인 투자 방안이기 때문입니다. 이어지는 글에서 인플레이션을 고려한 적립식 투자 성과를 추정하는 방법을 소개합니다.

참고: 연재와 관련한 질문은 댓글로 남겨주시기 바랍니다. 답변을 드리거나 이후 연재에서 다룰 수 있도록 노력하겠습니다.

참고 서적: 왜 위험한 주식에 투자하라는 걸까? - 장기 투자와 분산 투자에 대한 통계학적 시각

이어지는 글: [파이썬 분석 21] 적립식 성과를 인플레이션을 고려해서 추정해 보자

연재 목록: 자산 배분 분석 방법 책 소개, 연재글 및 사례 모음 [목록]

함께 읽으면 좋은 글 (최신 글)

  1. [파이썬 분석 19] 관계의 안정성을 살펴보자 (상관 계수 변화를 통한 관찰)
  2. [파이썬 분석 18] 투자 기간에 따른 위험의 변화를 살펴보자 (기초자산과 커버드콜의 경우, VaR, CVaR)
  3. [파이썬 분석 17] 투자 분석은 왜 통계적으로 접근해야 하나? (기초자산과 커버드콜의 경우)
  4. [파이썬 분석 16] 두 자산의 수익률 분포를 비교해 보자 (기초자산 수익률에 따른 커버드콜 수익률 분포, +구글 드라이브 이용)
  5. [파이썬 분석 15] 지수 데이터로 두 자산의 성과를 비교해 보자 (기초자산과 커버드콜 지수 + 외부 파일 읽기)

함께 읽으면 좋은 글 (인기 글)

  1. 챗GPT(ChatGPT)로 사진을 지브리 만화 스타일로 변환하기
  2. 구글 제미나이(Gemini)를 이용한 그림 생성하기 (vs. 마이크로소프트 이미지 크리에이터의 이미지 생성 AI)
  3. 스튜디오 지브리 만화 스타일로 그림 그리기 (구글 제미나이 + ImageFX)
  4. 스튜디오 지브리 만화 스타일로 그림 그리기 (구글 제미나이)
  5. 챗GPT(ChatGPT)로 사진을 지브리 vs 이누야샤 만화 스타일로 변환한 사례 비교 (인물 사진 #3)
도움이 되었다면, 이 글을 친구와 공유하는 건 어떻까요?

facebook twitter kakaoTalk naver band