주식투자

[파이썬 분석 5] 환율을 적용해 보고 어떤 변화가 발생했는지 살펴보자

오렌지사과키위 2025. 4. 13. 13:46

지난 글에서 SPY의 주가 데이터를 이용하여 1년 수익률의 기초 통계량을 추출해 보고, 확률 분포 그래프로도 그려보았습니다. 대응하는 정규 분포도 함께 나타내어 어떤 점이 다른지 간략하게 살펴보았습니다. 투자 분석에서 데이터를 가공한 결과는 크든 작든 불확실성이 있기에 확률 분포로 표현되는 경우가 많습니다. 그러니 투자자는 불확실성을 다루는 학문인 통계학에 대한 기초적인 지식을 습득하여 이해하는 것이 바람직합니다. 지난 글: [파이썬 분석 4] 수익률의 기초 통계량을 추출해 보고 확률 분포를 그려보자

한국인은 원화로 생활합니다. 달러로 매매하는 SPY에 투자할 수 있지만, 소비를 위해서는 최종적으로는 원화로 환전해야 합니다. 그러니 한국인은 달러가 아닌 원화 수익률을 보아야 합니다.

이 글에서는 환율 데이터를 구해 달러로 표시된 자산 가격을 원화로 환산하는 방법과 이로 인해 수익률의 확률 분포에 어떤 변화가 발생했는지 살펴봅니다.

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

환율 데이터 가져오기

다음은 한국은행의 환율 데이터를 가져와서 그래프로 그리는 코드입니다.

usdkrw = fdr.DataReader("ECOS-KEYSTAT:K152")

usdkrw.plot()

환율 데이터는 여러 데이터 소스(source)로부터 얻을 수 있지만, 제공 기간이 다를 수 있고, 누락된 날짜도 다를 수 있습니다. 제가 사용해 본 데이터 중에서는 한국은행과 인베스팅닷컴(investing.com)에서 제공하는 환율 데이터가 무난했습니다.

FinanceDataReader로 데이터를 가져올 때 "USD/KRW"로만 입력하면 야후 파이낸스(Yahoo Finance) 데이터를 가져옵니다. 앞에 "INVESTING:"이라고 소스(source)를 명시하면, 인베스팅닷컴 데이터를 가져옵니다.

한국은행 데이터를 사용하고 싶다면, "ECOS-KEYSTAT:K152"라 사용하면 됩니다. 한국은행에서 가져올 수 있는 데이터 목록은 FinanceDataReader의 한국은행 통계지표 데이터를 참고하기 바랍니다. 기준 금리부터 국제 수지에 이르기까지 투자에 참고할 수 있는 다양한 데이터를 제공합니다.

본래 계획은 인베스팅닷컴의 환율 데이터를 사용하려고 했습니다. 지금 실행해 보니 한 번에 20년치만 조회가 가능합니다. 긴 기간의 환율 데이터를 얻기 위해서는 날짜를 바꿔 두어 번 정도 실행해서 데이터를 병합해야 합니다. 연재와 설명의 편의를 위해 한국은행 데이터를 사용합니다.

한국은행에서 받은 환율로 그래프를 그리면 다음과 같습니다.

환율 [한국은행]

데이터 필드 이름이 한글이라서 글자가 깨져 나옵니다. 한글로는 "원/달러(종가 15:30)"라고 표시되어 있습니다. 매일 오후 3시 30분 환율입니다.

환율 데이터를 이용한 달러 자산 가격의 원화 환산

달러로 표시된 SPY 주가에 환율을 곱하면 원화로 환산할 수 있습니다. 주의할 점은 SPY 가격과 한국은행 환율의 가격 기록 시각이 다르다는 점입니다. 2025년 4월 1일 SPY 종가는 날짜로는 동일한 4월 1일 환율과 곱하지만, 한국은행 환율은 4월 1일 15시 30분 데이터이고, SPY 가격은 한국 시간으로 다음날인 4월 2일 05시(서머타임 적용 시) 또는 06시 데이터입니다.

단기적인 가격 변동을 분석해야 하는 경우에는 추가 환율 데이터를 구하거나 좀 더 엄밀한 환율 가격 모델을 만들어서 사용해야 합니다. 데이터마다 기록 시각이 다를 수 있기 때문입니다. 이 연재에서는 장기 투자 성과 위주로 살펴보기에 특별한 처리를 하지 않습니다.

다음은 SPY 달러 가격에 환율을 곱해 원화 가격으로 변환하는 코드입니다.

import pandas as pd

usdkrw_s = usdkrw.iloc[:, 0]

spy_usd = fdr.DataReader('SPY')['Adj Close']
spy_krw = (spy_usd * usdkrw_s).dropna()

spy_df = pd.concat([spy_usd, spy_krw], axis = 1).dropna()
spy_df.columns = ['SPY(USD)', 'SPY(KRW)']
spy_df

 

import pandas as pd는 Pandas 모듈을 사용하겠다는 지시입니다 Pandas 모듈은 DataFrame을 정의하고 다루는 모듈입니다. 

DataFrame은 스프레드시트의 시트와 같은 개념입니다. 2차원 테이블이라 볼 수 있습니다. 시트에 칼럼(column)이 하나만 있을 수 있듯, 칼럼이 하나뿐인 DataFrame도 있을 수 있습니다. usdkrw는 칼럼이 하나인 DataFrame입니다.

개개의 칼럼은 Series라고 부릅니다. 하나 이상의 Series가 모여서 DataFrame이 됩니다. DataFrame에서 첫 번째 칼럼을 꺼내오기 위해 iloc[:, 0]을 사용하고, Series임을 명시하기 위해 변수명에 _s를 붙인 usdkrw_s에 저장했습니다.

iloc[]의 첫 번째 인자(parameter)인 콜론(:)은 모든 행(row)을 의미합니다. 두 번째 인자인 0은 첫 번째 칼럼(column; 열)을 의미합니다. 파이썬과 같은 언어에서 배열(또는 리스트나 행렬)안의 절대 위치는 순서가 아니라 오프셋(offset) 개념입니다. 첫 번째 위치는 배열의 시작 위치에서 0번째 거리에 있기에, 0으로 표시합니다.

spy_usd 역시 SPY 주가 데이터에 대한 DataFrame에서 Adj Close 칼럼만 꺼낸 Series입니다. spy_usd와 usdkrw_s 모두 Series이며 곱할 수 있습니다. 두 Series에 대해 같은 키값 즉 같은 날짜 데이터에 대해 곱한 결과가 나옵니다. SPY 가격 또는 환율만 있는 날이 있을 수 있기에 이를 제거하기 위해 dropna()를 사용했습니다.

이제 달러 가격으로 표시한 spy_usd와 원화 가격을 가진 spy_krw 두 개의 Series가 생겼습니다. 이 두 Series를 pd.concat()으로 병합해서 DataFrame을 만들었습니다. 이때 같은 날짜에 대해 병합하라는 의미로 axis = 1으로 지정하였습니다. 양쪽 다 데이터가 있는 날짜만 남기기 위해 dropna()를 추가로 사용하였습니다.

실행 결과는 다음과 같습니다.

SPY 달러와 원화 가격

총 7,711개의 행이 있습니다. 본래 SPY 데이터의 개수는 8,107개였습니다. 한국 또는 미국의 거래일이 완전히 일치하지 않기에 4.9%의 날짜가 사라졌습니다. 예를 들어 한국의 설날 연휴 동안 미국 증시는 개장할 수 있지만, 환율 데이터가 없기에 제외됩니다.

평균 거래일수 구하기

이제 CAGR을 구해 보겠습니다. 먼저 다음과 같이 데이터 전체 기간이 년으로 얼마인지 계산합니다. 

days = (spy_df.index.max() - spy_df.index.min()).days
years = days / 365.25
years

spy_df.index는 인덱스로 사용한 날짜를 의미합니다. 그중에서 마지막 날에서 첫날을 빼서 날짜로 환산해서 days 변수에 넣고, 365.25로 나눠 년단위로 환산합니다.

32.19712525667351

32.2년으로 나왔습니다. 이 숫자를 전체 데이터 개수로 나누면, 년평균 거래일수를 알 수 있습니다.

len(spy_df) / years
239.493431122449

해당 데이터 기간인 지난 33년간 한국과 미국의 1년 평균 공통 거래일수는 240일 정도였습니다. 미국만 보면 252일 정도이고, 한국만 보면 248일 정도가 됩니다. 유럽은 미국보다 공휴일이 조금 더 많아 250일 정도가 나옵니다.

데이터에 따라 휴일 개념이 다를 수 있으니 구체적으로 확인해 보고 사용할 필요가 있을 수 있습니다. 분석 목적에 따라서는 데이터가 없는 날짜에 대해서 합리적인 추정치를 생성하여 사용해야 할 수도 있습니다.

예를 들어 미국은 개장일이지만, 환율 데이터가 없다면, 전일치 또는 가까운 이전과 이후 날짜의 환율 평균치를 사용할 수 있습니다. 이 연재에서는 1년 정도의 긴 기간에 대한 분석이 위주이므로 이러한 추가적인 데이터 보정은 하지 않습니다.

환헤지와 환노출의 누적 수익률과 확률 분포

SPY에 대한 환헤지(달러 가격)와 환노출(원화 가격) 누적 수익률을 그래프로 그려봅니다.

spy_df2 = spy_df / spy_df.iloc[0]
spy_df2.plot()

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

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

plt.show()

이전 글에서 소개한 방법을 이용하여 로그 스케일로 나타내되 눈금은 수익률로 표기하였습니다. 참고: [파이썬 분석 3] 누적 수익률로 그래프로 그려 보자 (로그 스케일에 수익률을 표현하는 방법)

SPY의 환헤지 환노출 투자의 누적 수익률

한국에 IMF 외환 위기가 닥친 1997년 말에 환율이 크게 상승해서 오렌지색으로 표현된 환노출 수익률이 급등했던 기록을 볼 수 있습니다. 그 이후 환노출과 환헤지의 수익률 격차가 전반적으로 어느 정도 유지되고 있습니다. 자세히 보면 2007 ~ 2008년 세계 금융 위기 때 환노출의 하락폭이 상대적으로 낮았음을 알 수 있습니다.

환헤지와 환노출의 1년 수익률을 확률 분포로 그려 비교해 봅니다.

plt.hist(spy_df.pct_change(240), bins = 100, histtype = 'step', density = True,
         label = spy_df.columns)

plt.gca().xaxis.set_major_formatter(PercentFormatter(xmax = 1))

plt.legend(reverse = True)

plt.show()

plt.hist() 함수로 확률 분포를 그립니다. 이전 글에서 설명한 것처럼 DataFrame을 이용하여 spy_df.hist()로 히스토그램을 그리면, 각각의 Series에 대해 히스토그램이 따로 그려집니다. 한 그래프에 두 확률 분포를 나타내기 위해 plt.hist() 함수를 사용했습니다.

앞에서 확인한 1년 평균 거래일수인 240일을 기준으로 1년 수익률을 계산해서 그렸습니다. 범례를 지정하는 label 인자로는 spy_df의 칼럼 목록을 주었습니다.

범례를 표시하라는 plt.legend()에 reverse = True라고 지시했습니다. plt.hist()는 이해하기 어려운 이유로 범례 순서가 역순으로 나타나기에, 데이터 순서 그대로 표시하기 위해 사용한 것입니다.

결과는 다음과 같습니다.

SPY의 환헤지와 환노출의 1년 수익률 분포

오렌지색의 환노출(KRW) 수익률 분포의 꼭지점이 약간 왼쪽으로 치우쳐 있지만, 환헤지(USD)에 비해 큰 손실이 발생한 빈도가 낮았고, 높은 수익률이 발생한 빈도는 높았습니다.

손실 부분만 확대해서 보기 위해 plt.xlim() 함수로 x좌표 범위를 지정할 수 있습니다. 다음 코드를 plt.hist() 아래에 넣고 다시 실행하면 됩니다. 최대 0% 즉 손실 부분만 나타내도로 지시한 것입니다.

plt.xlim(right = 0)

SPY의 환헤지와 환노출의 1년 수익률 분포 (손실 부분 확대)

확률 분포를 보면 알 수 있다시피, 환노출로는 큰 손실이 발생한 빈도가 상당히 낮았음을 알 수 있습니다. 다르게 말하면, 한국인의 경우 환헤지보다는 환노출로 투자하는 것인 위험 관리 측면에서 조금 더 유리했다고 볼 수 있습니다.

환헤지와 환노출의 기초 통계량

describe() 명령으로 몇 가지 기초 통계량을 추출해 보겠습니다.

spy_df.pct_change(240).describe().round(3)

SPY 환헤지 및 환노출 1년 수익률의 기초 통계량

평균(mean)은 환노출이 높았고, 중앙값(50%)은 환헤지가 높았습니다. 1년 투자 시 최대 손실은 환헤지가 좀 더 컸습니다. 표준 편차를 보면 환노출이 23.2%, 환헤지가 17.0%로 환노출의 변동성이 더 높았던 것으로 나옵니다. 이는 한국의 외환 위기 기간이 데이터에 포함되어 있기 때문입니다. 최근 20년 정도인 20년 × 240일 = 4,800일에 대해 살펴보면 다음과 같습니다.

spy_df.pct_change(240)[-4800: ].describe().round(3)

[-4800: ]은 끝에서 4800번째 데이터부터 마지막까지라는 의미입니다.

SPY 환헤지 및 환노출 1년 수익률의 기초 통계량 (최근 4,800거래일 = 대략 최근 20년)

표준 편차를 보면 환노출이 12.0%, 환헤지가 16.2%로 환노출의 변동성이 더 낮았습니다. 하위 25% 수익률은 4.9%로 비슷했고, 최소 수익률은 환노출이 -46.7%, 환헤지가 -23.8%로 환노출의 위험이 훨씬 낮았습니다. 최근 20년만 본다면, 환노출로 투자하는 것이 유리했다고 해석할 수 있습니다.

정리하며

한국은행 환율 데이터를 이용하여 달러 자산에 대한 원화 가격을 구해 달러 가격과 비교해 보았습니다. 환헤지와 환노출을 확률 분포로 비교해 보면, 환노출이 위험 측면에서 좀 더 유리했음을 알 수 있었습니다.

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

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

이어지는 글: [파이썬 분석 6] 산점도(scatter plot)에 자산의 특성을 나타내고, 예금과 혼합 효과도 표현해 보자

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

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

  1. [파이썬 분석 4] 수익률의 기초 통계량을 추출해 보고 확률 분포를 그려보자
  2. [파이썬 분석 3] 누적 수익률로 그래프로 그려 보자 (로그 스케일에 수익률을 표현하는 방법)
  3. [파이썬 분석 2] PR(배당 미고려)과 TR(배당 재투자) 주가 흐름을 그래프로 그려 보자 (FinanceDataReader 모듈 사용)
  4. [파이썬 분석 1] 주가 흐름을 그래프로 그려 보자 (구글 코랩을 써 보자! 인공지능 너도 실수하는구나?)
  5. [중급 14] 레버리지 ETF의 성과는 왜 좋았을까? (민감한 레버리지님과 기준 금리)

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

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

facebook twitter kakaoTalk naver band