본문 바로가기
경제 금융 포털사이트 경제 금융 포털사이트

주가 데이터 다운로드 후 막막하다면? 파이썬 시계열 전처리 핵심 3가지

금알남 읽는 시간 약 19분
ai thumbnail infographic 파이썬 시계열 데이터 전처리 방법 결측치 이상치 수익률 변환까지 1789200538

결론부터 말씀드리면 파이썬 금융 시계열 분석의 성공은 복잡한 인공지능 모델이 아니라 가장 기초적인 데이터 전처리 과정에서 결정됩니다.

야심 차게 주식 데이터를 내려받고 판다스를 실행했지만 화면 가득 뜬 빈칸을 보고 어디서부터 손대야 할지 막막했던 경험이 있으실 것입니다. 이때 빈칸을 무작정 삭제하거나 내일의 데이터로 오늘을 채워 넣는 실수는 소중한 투자금을 잃게 만드는 가장 빠른 지름길입니다. 자본시장연구원 및 퀀트 투자 연구 통계 등에 따르면, 자동매매 알고리즘 실패 원인의 70퍼센트 이상이 과거 데이터에 미래 정보가 섞여 들어가는 기본적 오류에서 비롯된다고 합니다.

만약 여러분이 만든 백테스트 모델이 현실에서 불가능한 엄청난 수익률을 보여준다면 지금 당장 전처리 과정을 의심해 보아야 합니다. 남들이 겪는 치명적인 오류를 피하고 내 계좌를 안전하게 지키기 위해 반드시 알아야 할 전처리 핵심 3단계를 구체적으로 알려드리겠습니다.

금융 시계열 분석에서 이런 질문은 사소해 보이지만 실제 결과를 크게 좌우합니다.

1. 시계열 데이터의 생명은 날짜 정렬이다

일반적인 표 데이터와 금융 시계열 데이터의 가장 큰 차이는 바로 시간의 흐름과 순서입니다. 엑셀이나 CSV 파일을 불러온 뒤 가장 먼저 해야 할 일은 날짜 열을 시간 형식으로 변환하고 순서대로 정렬하는 것입니다.

날짜가 일반 문자열 상태로 남아 있으면 기간을 추출하거나 정렬할 때 데이터가 뒤죽박죽 섞이는 치명적인 문제가 발생합니다. 또한 중복된 날짜가 발견되었을 때도 무조건 지우는 것은 위험합니다. 같은 날짜의 데이터가 두 번 수집된 단순 수집 오류인지, 서로 다른 시장의 정보가 하나로 섞인 것인지 그 원인을 먼저 파악하는 것이 안전한 분석의 첫걸음입니다.

일반적인 표 데이터와 금융 시계열 데이터의 가장 큰 차이는 시간의 순서가 중요하다는 점입니다.

예를 들어 다음과 같은 데이터가 있다고 가정해보겠습니다.

import pandas as pd

df = pd.read_csv("stock_data.csv")

print(df.head())

데이터에는 보통 다음과 같은 열이 포함됩니다.

Date
Open
High
Low
Close
Volume

가장 먼저 날짜 열을 datetime 형식으로 바꾸고 시간순으로 정렬하는 것이 좋습니다.

df["Date"] = pd.to_datetime(df["Date"])

df = df.sort_values("Date")

df = df.set_index("Date")

print(df.head())

날짜가 문자열 상태로 남아 있으면 정렬이나 기간 추출 과정에서 예상하지 못한 결과가 나올 수 있습니다.

pandas의 Series와 DataFrame은 시계열을 포함한 인덱스 기반 데이터 처리를 지원하며, 현재 공식 문서에서도 날짜와 시계열 데이터를 다루는 기능을 별도로 제공하고 있습니다.

여기서 중복된 날짜도 확인해보겠습니다.

print(df.index.duplicated().sum())

중복 데이터가 발견됐다면 무조건 삭제하기 전에 왜 중복됐는지 먼저 확인해야 합니다.

같은 날짜 데이터가 단순히 두 번 수집된 것인지, 서로 다른 시장이나 종목 데이터가 섞여 있는 것인지에 따라 처리 방법이 달라지기 때문입니다.

중복의 원인이 확인된 뒤 삭제하려면 다음과 같이 처리할 수 있습니다.

df = df[~df.index.duplicated(keep="first")]

금융 데이터를 분석할 때는 모델을 선택하는 것보다 먼저 날짜가 제대로 정렬돼 있는지 확인하는 습관을 들이는 것이 좋습니다.

image 19

2. 결측치 무작정 지우면 계좌가 녹아내린다

데이터를 다루다 보면 비어있는 값을 자주 만나게 됩니다. 이때 단순히 빈 행을 지워버리거나 앞뒤 값의 평균을 내어 임의로 채우는 분들이 많습니다. 주식시장이 열리지 않는 주말이나 공휴일의 가격 데이터가 없다고 해서 금요일과 월요일 사이의 가짜 가격을 만들어 넣을 필요는 없습니다.

전처리 과정에서 가장 주의해야 할 점은 다음 날의 가격으로 과거의 빈 공간을 채우는 실수입니다. 분석 시점에서는 절대 알 수 없는 미래의 정보가 과거 데이터로 흘러 들어가는 이른바 “미래 정보 누수” 현상이 발생하기 때문입니다. 이런 오염된 데이터로 모델을 학습시키면 과거로 돌아가서 정답을 알고 주식을 사는 것과 같으므로, 반드시 직전 영업일의 유효한 값을 가져와 채우는 방식을 사용해야 합니다.

시계열 데이터를 다루다 보면 NaN이라고 표시되는 결측값을 자주 만나게 됩니다.

먼저 데이터에 결측치가 얼마나 있는지 확인해보겠습니다.

print(df.isna().sum())

결측치를 처리하는 대표적인 방법은 크게 세 가지입니다.

# 결측값이 있는 행 제거
df_drop = df.dropna()

# 이전 값을 이용해 채우기
df_ffill = df.ffill()

# 보간법을 이용해 채우기
df_interpolate = df.interpolate()

pandas 공식 문서에서도 dropna()는 결측값 제거, ffill()은 직전의 유효한 값을 다음 결측 구간에 전달하는 방식, interpolate()는 지정한 보간 방법을 이용해 빈 값을 채우는 기능으로 제공됩니다.

그렇다면 어떤 방법을 사용해야 할까요?

정답은 데이터의 의미에 따라 달라집니다.

주식시장의 토요일과 일요일 가격이 없다고 해서 금요일 종가와 월요일 종가 사이에 임의의 가격을 만들어 넣을 필요는 없습니다.

반대로 매일 기록되는 시장 데이터와 일정한 주기로 발표되는 경제지표를 합칠 때는 직전 발표값을 유지하는 것이 분석 목적에 맞는 경우도 있습니다.

하지만 금융 시계열에서는 특히 bfill()을 조심할 필요가 있습니다.

예를 들어 다음 값으로 과거의 빈 공간을 채우면 아직 발표되지 않았던 미래 정보가 과거 데이터에 들어갈 수 있습니다.

df["indicator"] = df["indicator"].bfill()

분석 시점에서는 알 수 없었던 값이 과거 데이터에 포함된다면 모델 성능이 실제보다 좋게 측정될 가능성이 있습니다.

이를 흔히 데이터 누수, Data Leakage라고 부릅니다.

따라서 결측치 처리에서는 단순히 NaN을 없애는 것보다 다음 질문을 먼저 해야 합니다.

“이 값은 해당 날짜의 사람이 실제로 알 수 있었던 정보인가?”

금융 데이터 전처리에서는 이 질문이 상당히 중요합니다.

3. 시장의 이상치는 오류가 아닌 핵심 정보다

일반적인 통계 데이터 분석에서는 평균에서 크게 벗어난 값을 이상치로 판단하고 조용히 제거해버립니다. 하지만 금융 데이터에서 하루 수익률이 비정상적으로 치솟거나 폭락한 날을 단순히 통계적 오류로 취급해 지워버리면 분석의 방향이 완전히 틀어집니다.

그날은 금리가 급격히 변했거나 기업의 어닝 쇼크가 발생한, 즉 실제 시장에서 위기 혹은 기회가 터진 결정적인 순간이기 때문입니다. 극단적인 움직임 그 자체가 금융시장에서는 가장 중요한 분석 대상이 됩니다. 따라서 이상치를 발견했다면 지워야 할 찌꺼기를 찾은 것이 아니라, 가장 먼저 경제 기사와 차트를 대조해 원인을 짚고 넘어가야 할 핵심 단서를 찾은 것으로 접근하셔야 합니다.

일반적인 데이터 분석에서는 평균에서 크게 벗어난 값을 이상치로 판단하고 제거하는 경우가 있습니다. 하지만 금융 데이터에서는 조금 더 조심해야 합니다.

예를 들어 하루 수익률이 평소보다 크게 움직였다고 가정해보겠습니다.

통계적으로는 이상치처럼 보일 수 있습니다.

하지만 그날 금리 발표, 기업 실적 발표, 금융위기, 정책 변화 같은 실제 사건이 있었다면 그 값은 오류가 아니라 시장에서 실제 발생한 중요한 정보입니다.

먼저 수익률의 분포를 간단하게 확인할 수 있습니다.

df["return"] = df["Close"].pct_change()

print(df["return"].describe())

IQR 방식을 이용해 잠재적인 이상치를 탐색하는 방법도 있습니다.

Q1 = df["return"].quantile(0.25)
Q3 = df["return"].quantile(0.75)

IQR = Q3 - Q1

lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

outliers = df[
    (df["return"] < lower) |
    (df["return"] > upper)
]

print(outliers)

여기서 중요한 것은 outliers에 포함됐다고 해서 바로 데이터를 삭제하지 않는 것입니다.

먼저 해당 날짜를 실제 시장 상황과 비교해볼 필요가 있습니다. 예를 들어 가격 입력 오류 때문에 종가가 비정상적으로 기록된 것이라면 수정 또는 제외를 검토할 수 있습니다.

반대로 시장 급락이나 급등이 실제로 발생한 날이라면 이를 삭제하면 오히려 중요한 시장 특성을 잃게 됩니다.

특히 금융시장 수익률에는 극단적인 움직임 자체가 분석 대상이 될 수 있습니다. 따라서 이상치 탐지는 “삭제할 데이터를 찾는 과정”보다 “확인해야 할 데이터를 찾는 과정”으로 접근하는 편이 안전합니다.

필요에 따라 원본 데이터는 그대로 보존하고 분석용 변수만 별도로 변환하는 방법도 사용할 수 있습니다.

예를 들어 극단값의 영향을 제한하기 위한 클리핑은 다음처럼 구현할 수 있습니다.

lower_q = df["return"].quantile(0.01)
upper_q = df["return"].quantile(0.99)

df["return_clipped"] = df["return"].clip(
    lower=lower_q,
    upper=upper_q
)

다만 이 역시 모든 금융 분석에 필요한 처리 방법은 아닙니다.

분석 목적과 모델 특성에 따라 선택해야 합니다.

4. 주가 자체보다 수익률 변환에 집중하라

주식 가격 자체를 모델에 그대로 넣으면 장기적인 인플레이션이나 우상향하는 상승 추세 때문에 분석 결과가 왜곡되기 쉽습니다. 금융 분석에서 중요한 것은 현재 가격이 얼마인가보다 “직전 시점에 비해 얼마나 변했는가”를 파악하는 것입니다.

이때 단순수익률과 로그수익률을 상황에 맞게 구분해서 사용하는 안목이 필요합니다. 단순수익률은 직관적으로 이해하기 쉽지만 여러 기간의 수익률을 누적해서 계산할 때는 수학적 오차가 발생합니다. 반면 로그수익률은 시간의 흐름에 따른 복리 효과를 자연스럽게 반영해주어, 장기적인 자산 흐름을 분석하고 알고리즘 백테스트를 진행할 때 훨씬 안정적이고 유리합니다.

금융 데이터 분석을 처음 시작하면 종가인 Close를 그대로 분석하는 경우가 많습니다. 하지만 주가와 주가지수에는 장기간의 추세가 포함될 수 있습니다.

예를 들어 어떤 종목의 가격이 다음처럼 움직였다고 가정해보겠습니다.

100
102
104
106
108

가격만 보면 지속적으로 상승합니다.

하지만 금융 분석에서는 가격이 얼마인가보다 “직전 시점에 비해 얼마나 변했는가”가 더 유용한 경우가 많습니다.

가장 간단한 방법이 단순수익률입니다.

df["return"] = df["Close"].pct_change()

현재 pandas 문서에서 pct_change()는 현재 값과 이전 값 사이의 fractional change, 즉 상대적인 변화량을 계산하는 기능으로 설명됩니다.

계산식으로 표현하면 다음과 같습니다.

단순수익률 = (현재 가격 - 이전 가격) / 이전 가격

예를 들어 가격이 100에서 105로 올랐다면 수익률은 0.05가 됩니다.

즉 5%입니다.

실무나 금융 연구에서는 로그수익률도 많이 사용합니다.

import numpy as np

df["log_return"] = np.log(
    df["Close"] / df["Close"].shift(1)
)

로그수익률은 다음처럼 표현할 수 있습니다.

로그수익률 = ln(현재 가격 / 이전 가격)

단순수익률과 로그수익률은 변화 폭이 작을 때 서로 비슷한 값을 보이지만 계산 방식과 해석에는 차이가 있습니다.

로그수익률의 장점 중 하나는 여러 기간의 로그수익률을 더해 누적된 로그 변화량을 계산하기 쉽다는 점입니다.

예를 들어 분석 데이터를 다음처럼 정리할 수 있습니다.

df["return"] = df["Close"].pct_change()

df["log_return"] = np.log(
    df["Close"] / df["Close"].shift(1)
)

print(
    df[
        ["Close", "return", "log_return"]
    ].head(10)
)

다만 “금융 데이터이므로 무조건 로그수익률을 써야 한다”라고 생각할 필요는 없습니다.

분석 목적과 사용하는 통계모형, 예측 대상에 따라 가격 수준, 차분값, 단순수익률, 로그수익률 가운데 적절한 변수를 선택해야 합니다.

마지막으로 전처리가 끝났다면 다음 항목을 한 번 확인해보는 것이 좋습니다.

  1. 날짜가 실제 시간순으로 정렬됐는가?
  2. 중복된 날짜나 행은 없는가?
  3. 결측치가 발생한 이유를 확인했는가?
  4. 미래 값으로 과거 결측치를 채우지 않았는가?
  5. 이상치가 입력 오류인지 실제 시장 움직임인지 확인했는가?
  6. 가격 자체와 수익률 중 어떤 변수가 분석 목적에 맞는가?
  7. 원본 데이터는 별도로 보존하고 있는가?

금융 시계열 데이터의 전처리는 단순히 지저분한 데이터를 깨끗하게 만드는 작업이 아닙니다.

어떤 데이터를 남기고 어떤 데이터를 변환할 것인지 결정하면서 실제 시장의 시간 구조를 분석 가능한 형태로 만드는 과정에 가깝습니다.

특히 결측값을 잘못 채우거나 실제 시장 급락을 이상치라는 이유로 삭제하면 이후 아무리 좋은 모델을 사용하더라도 결과가 왜곡될 수 있습니다.

그래서 파이썬 금융 데이터 분석에서는 복잡한 머신러닝 모델에 들어가기 전에 날짜 정렬, 결측치, 이상치, 수익률 변환부터 차근차근 확인하는 것이 중요합니다.

다음 단계에서는 이렇게 전처리한 금융 시계열이 통계적으로 어떤 특성을 가지고 있는지 살펴볼 수 있습니다.

특히 주가처럼 추세가 있는 데이터를 분석할 때 자주 등장하는 개념이 ‘정상성’입니다.

완벽한 전처리가 성공적인 투자의 시작입니다

지금까지 주가 데이터를 다운로드한 뒤 반드시 점검해야 할 날짜 정렬, 결측치 처리, 이상치 판단, 수익률 변환에 대해 알아보았습니다. 이러한 튼튼한 기초 공사 없이 남들이 좋다는 복잡한 인공지능 수식을 무작정 가져다 쓰는 것은 모래 위에 집을 짓는 것과 같습니다.

하지만 본업으로 바쁜 와중에 파이썬 코드를 하나하나 수정하며 완벽한 투자 시스템을 구축하기란 현실적으로 매우 벅찬 일입니다. 저는 14년간의 IT 시스템 엔지니어 경험과 10년 이상의 재무설계, 자산관리 실무 경력을 바탕으로 기술적 데이터 분석과 현실적인 금융 시장의 흐름을 누구보다 깊이 이해하고 있습니다. 매일 꾸준히 달리고 성실하게 일하며 주변 사람들에게 실질적인 이익을 드리는 것을 제 직업의 최우선 가치로 삼고 있습니다.

단순한 코딩 오류 해결을 넘어, 실제 계좌의 현금흐름을 안정적으로 창출하고 체계적인 은퇴 자산을 마련하는 종합적인 포트폴리오 점검이 필요하시다면 혼자 답답해하지 마시고 편하게 진단을 요청해 주십시오. 거창한 상품 가입을 밀어붙이는 것이 아닙니다. 현재 나의 투자 방향과 자산 배분 구조가 올바른지 점검해보는 그 한 번의 확인이 훗날 겪을 수 있는 큰 손실을 막아주는 든든한 방패가 될 것입니다.

질문 1. 파이썬을 전혀 모르는데 퀀트 투자나 자산관리 상담이 가능한가요? 답변. 네 가능합니다. 코딩 기술 자체보다 훨씬 중요한 것은 올바른 투자 원칙과 잃지 않는 자산 배분 전략입니다. 복잡한 시스템 구현 없이도 고객님의 성향과 재무 상황에 맞는 최적의 금융 포트폴리오를 알기 쉽게 제안해 드립니다.

질문 2. 기존에 가입한 금융 상품이나 보험도 함께 점검받을 수 있나요? 답변. 물론입니다. 투자의 가장 기본은 불필요하게 새는 돈을 막는 리스크 관리입니다. 기존에 유지 중이신 보험과 개인형 IRP, 퇴직연금 등을 꼼꼼히 분석하여 낭비되는 지출을 줄이고 투자 시드머니를 확보하는 첫 단추부터 확실히 꿰어 드립니다.

질문 3. 상담을 신청하면 비용이 발생하거나 무조건 상품에 가입해야 하나요? 답변. 그렇지 않습니다. 나의 재무 상태를 진단하고 포트폴리오 방향성을 설정하는 첫 점검은 부담 없이 진행하실 수 있습니다. 철저한 데이터 기반의 비교 분석을 충분히 들어보신 후, 고객님께서 스스로 합리적인 결정을 내리실 수 있도록 정직하고 투명하게 안내해 드립니다.

본 포스팅은 금융소비자보호법을 준수하여 작성되었습니다. 해당 내용은 주관적인 의견이 포함되어 있으며, 구체적인 투자 성과를 보장하거나 특정 상품의 무조건적인 가입을 권유하지 않습니다.

다음 글에서는 **「ADF 검정이란? 파이썬으로 시계열 정상성 확인하는 방법」**을 통해 정상성이 왜 필요한지, statsmodels를 이용해 ADF 검정을 어떻게 실행하고 결과를 어떻게 해석하는지 이어서 살펴보겠습니다.

참고 자료

pandas 공식 문서에서는 현재 Series와 DataFrame에서 dropna, ffill, bfill, fillna, interpolate 등의 결측 데이터 처리 기능을 제공하고 있습니다.

pandas 공식 API에서는 pct_change()를 이전 값과 비교한 상대 변화량을 계산하는 기능으로 제공하고 있습니다.

본 글은 파이썬과 금융 데이터 분석 방법을 설명하기 위한 교육·정보 제공 목적의 콘텐츠입니다. 특정 금융상품의 매수·매도 또는 투자 행동을 권유하기 위한 내용이 아닙니다. 데이터 전처리 방법과 분석 결과는 데이터 출처, 기간, 처리 기준과 분석 목적에 따라 달라질 수 있으며 과거 데이터에서 나타난 결과가 향후 시장 움직임이나 투자 성과를 보장하지 않습니다.

금알남

금알남
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.