태그 보관물: 피처엔지니어링

시계열 피처 엔지니어링: RSI 지표 구현과 데이터 누수 방지 설계

시계열 피처 엔지니어링: RSI 지표 구현과 데이터 누수 방지 설계

금융 데이터의 특수성을 고려해 미래 정보가 학습에 유입되는 '데이터 누수'를 차단하고, 신뢰할 수 있는 RSI 피처를 구축하는 방법

예전에 금융 시계열 모델을 만들던 후배가 아주 자신만만하게 찾아온 적이 있어요. 검증 셋 성능이 90%가 넘는다며 환호하더군요. 그런데 이상했습니다. 주가 예측에서 그런 수치가 나오는 건 보통 두 가지 경우뿐이거든요. 천재거나, 아니면 ‘데이터 누수(Data Leakage)’가 발생했거나.

결국 코드를 뜯어보니 롤링 평균을 계산할 때 미래 시점의 데이터가 슬쩍 포함되어 있었더라고요. 훈련 때는 완벽해 보이지만 실제 운영 환경에 배포하는 순간 처참하게 무너지는, 그야말로 ‘조용한 살인자’ 같은 상황이었죠 [2, 8].

시계열 데이터 기반의 ML 모델에서 이런 성능 과대평가를 막으려면, RSI와 같은 기술적 지표를 계산할 때 예측 시점 이전의 데이터만 사용하는 ‘Point-in-Time’ 설계가 필수적입니다.

시계열 피처 엔지니어링과 RSI의 역할

우선 RSI가 뭔지부터 가볍게 짚고 넘어갈게요. RSI(상대강도지수)는 최근 일정 기간의 종가를 바탕으로 시장이 지금 과하게 올랐는지(강세), 아니면 너무 떨어졌는지(약세)를 측정하는 모멘텀 지표예요 [7]. 쉽게 말해 “지금 시장의 힘이 어느 정도인가?”를 숫자로 나타낸 거죠.

그런데 왜 이걸 ML 모델에 넣을까요? 그냥 가격 데이터만 넣어도 될 것 같지만, 원시 시계열 데이터(Raw Data)는 노이즈가 너무 많습니다. 이걸 RSI 같은 의미 있는 피처로 변환해주면, 모델이 “아, 지금은 과매수 구간이라 곧 꺾이겠구나” 같은 숨겨진 패턴을 훨씬 더 잘 포착하게 됩니다 [9]. 결국 금융 도메인의 지식을 ML 피처로 잘 녹여내는 과정이 모델 성능을 끌어올리는 핵심 동력이 되는 셈이죠.

데이터 누수(Data Leakage): 시계열 모델의 치명적 함정

여기서 우리가 정말 조심해야 할 게 바로 ‘데이터 누수’입니다. 한마디로 정의하면, 모델이 예측 시점에는 절대 알 수 없는 미래의 정보를 학습 중에 엿보는 현상을 말해요.

“Data leakage happens when your model gets a peek at information it shouldn’t have, like future data or the target variable, during feature engineering.” [2]

피처 엔지니어링 과정에서 모델이 미래 데이터나 타겟 변수처럼 알아서는 안 될 정보를 엿볼 때 데이터 누수가 발생합니다.

시계열 데이터에서 특히 자주 발생하는 실수 몇 가지를 말씀드릴게요. 가장 흔한 게 ‘랜덤 스플릿(Random Split)’입니다. 일반적인 정형 데이터라면 데이터를 무작위로 섞어서 학습/테스트 셋을 나누는 게 정석이지만, 시계열에서는 절대 금물이에요. 미래의 관측치가 과거의 학습에 영향을 주게 되어 인과 관계가 완전히 깨져버리거든요 [5].

또 하나 무서운 게 ‘전체 데이터셋 기반의 집계(Global Aggregations)’입니다. 예를 들어 전체 기간의 평균값을 구해서 결측치를 채우거나 피처로 쓴다면, 모델은 이미 미래에 가격이 어떻게 변했는지에 대한 힌트를 가진 채로 학습하게 됩니다. 결과는? 훈련 점수는 환상적이지만, 실전에서는 아무짝에도 쓸모없는 모델이 탄생하죠 [2, 8].

Leakage-Safe RSI 구현을 위한 설계 전략

그럼 어떻게 해야 누수 없이 안전하게 RSI 피처를 만들 수 있을까요? 핵심은 “예측 시점에 내가 이 데이터를 알 수 있었는가?”라는 질문에 답하는 것입니다. 이를 위해 ‘Point-in-Time’ 엔지니어링 전략을 사용해야 해요 [1, 12].

가장 실무적인 방법은 Pandas의 shift() 함수를 활용하는 겁니다. 윈도우 피처를 만들 때 현재 시점($t$)의 값을 포함하지 않고, 반드시 $t-1$ 시점까지의 데이터만 참조하도록 강제하는 거죠 [4]. 슬라이딩 윈도우 방식을 적용해 특정 시점 기준의 요약 통계량만 산출하는 것이 안전합니다.

아래는 누수를 방지하며 RSI를 계산하는 간단한 구현 예시입니다.

import pandas as pd
import numpy as np

def calculate_leakage_safe_rsi(df, window=14):
    # 1. 가격 변화량 계산
    delta = df['close'].diff()
    
    # 2. 상승분과 하락분 분리
    gain = (delta.where(delta > 0, 0))
    loss = (-delta.where(delta < 0, 0))
    
    # 3. 지수이동평균(EMA)으로 평균 상승/하락폭 계산
    avg_gain = gain.ewm(com=window-1, min_periods=window).mean()
    avg_loss = loss.ewm(com=window-1, min_periods=window).mean()
    
    # 4. RS 및 RSI 계산
    rs = avg_gain / avg_loss
    rsi = 100 - (100 / (1 + rs))
    
    # [핵심] shift(1)을 통해 '오늘'의 RSI를 '내일'의 예측 피처로 사용
    # 이렇게 해야 예측 시점(t)에서 미래 데이터(t)를 참조하는 누수를 막을 수 있습니다.
    return rsi.shift(1) 

# 샘플 데이터 생성
data = {'close': [100, 102, 101, 105, 107, 110, 108, 109, 115, 120, 118, 117, 121, 125, 130, 128]}
df = pd.DataFrame(data)
df['rsi_feature'] = calculate_leakage_safe_rsi(df)

print(df.tail())

이 코드에서 가장 중요한 부분은 마지막 .shift(1)입니다. 오늘 계산된 RSI 값은 내일의 가격을 예측하는 피처로 쓰여야지, 오늘 가격을 예측하는 데 쓰이면 안 되기 때문입니다.

흔히 저지르는 시계열 피처링 안티패턴

제가 현업에서 본 가장 안타까운 실수들을 몇 가지 공유할게요. 여러분은 절대 이렇게 하지 마세요.

  • 미래 타임스탬프가 포함된 롤링 평균: 윈도우를 설정할 때 center=True 옵션을 주면 현재 시점을 기준으로 앞뒤 데이터를 모두 참조하게 됩니다. 이건 시계열에서는 명백한 반칙입니다 [5].
  • 전체 기간 통계량을 이용한 결측치 처리: 훈련 셋과 테스트 셋을 나누기 전에 전체 데이터의 평균이나 중앙값으로 Imputation을 수행하면, 미래의 정보가 과거의 빈칸으로 스며들게 됩니다 [5].
  • 시간 순서를 무시한 데이터 셔플링: 시계열 데이터는 시간의 흐름이라는 강력한 제약이 있습니다. 이걸 무시하고 섞어서 교차 검증을 수행하면, 모델은 인과 관계가 아니라 단순한 ‘암기’를 하게 됩니다 [5, 6].

신뢰성 검증: 모델 성능의 ‘착시’ 제거하기

구현을 마쳤다면 이제 이 성능이 ‘진짜’인지 검증할 차례입니다. 랜덤 스플릿 대신 전진 체이닝(Forward Chaining)이나 확장 윈도우(Expanding Window) 검증법을 도입하세요. 과거 데이터로 학습하고 그다음 짧은 미래 구간을 예측하는 과정을 반복하며 성능을 측정하는 방식입니다 [5].

또한, 피처 중요도(Feature Importance)를 꼭 확인하세요. 만약 특정 피처 하나가 비정상적으로 압도적인 기여도를 보인다면, 알고리즘이 효율적인 게 아니라 그 피처에 미래 정보가 누수되었을 가능성이 매우 높습니다 [2]. 마지막으로 훈련 데이터와 테스트 데이터의 시간적 경계를 칼같이 분리한 뒤 Sanity Check를 수행해, 경계 지점에서 성능이 급락하지 않는지 확인하는 습관이 필요합니다.

짚고 넘어갈 한계와 트레이드오프

물론 이런 엄격한 설계가 항상 정답만은 아닐 때도 있습니다. 너무 보수적으로 시간을 분리하다 보면 학습 데이터가 부족해져서 모델의 일반화 성능이 떨어지는 트레이드오프가 발생하거든요 [2].

또한, RSI 같은 기술적 지표 자체가 효율적 시장 가설(EMH) 관점에서는 예측력이 없다고 보는 시각도 있습니다. 과거의 가격 패턴이 미래를 보장하지 않는다는 주장인데, 사실 이 논쟁은 퀀트 세계에서 아주 오래된 것이죠 [10]. 중요한 건 지표의 절대적 정답 여부보다, 우리가 세운 가설을 ‘누수 없이’ 검증할 수 있는 파이프라인을 갖췄느냐 하는 점입니다.

핵심 요약

  • 시계열 피처 엔지니어링의 제1원칙은 ‘미래 정보의 완전한 차단’입니다.
  • RSI 구현 시 Pandas shift()를 활용해 예측 시점 이전의 데이터만 사용하는 Point-in-Time 정합성을 확보하세요.
  • Random Split은 금기입니다. Forward Chaining 같은 시간 기반 검증을 도입해야 합니다 [5].
  • 모델 성능이 비정상적으로 좋다면 알고리즘의 승리가 아니라 데이터 누수의 신호일 가능성을 항상 의심하세요 [2, 5].

단순히 라이브러리를 호출해 RSI를 계산하는 건 누구나 할 수 있는 쉬운 일입니다. 하지만 이를 MLOps 관점에서 ‘안전하게’ 파이프라인에 녹여내고, 미래 정보가 단 한 방울도 섞이지 않게 설계하는 것은 결국 엔지니어의 디테일과 집요함에 달려 있습니다.


참고 자료 (References)

1. [ikvibhav.medium.com] MLOps Systems: Feature Engineering: Building a Leakage-Safe RSI Feature in Python for Stock… — https://ikvibhav.medium.com/mlops-systems-feature-engineering-building-a-leakage-safe-rsi-feature-in-python-for-stock-1b72c88492e6 2. [statsig.com] Common pitfalls in feature engineering — https://www.statsig.com/perspectives/feature-engineering-pitfalls 3. [statsig.com] Feature engineering for time-series data — https://www.statsig.com/perspectives/feature-engineering-timeseries 4. [medium.com] Introduction to feature engineering for time series forecasting – Medium — https://medium.com/data-science-at-microsoft/introduction-to-feature-engineering-for-time-series-forecasting-620aa55fcab0 5. [medium.com] Feature Engineering Pitfalls: Bias, Leakage, and the Illusion of Model Performance — https://medium.com/towards-data-engineering/feature-engineering-pitfalls-bias-leakage-and-the-illusion-of-model-performance-93d3cf343e8a 6. [bitpeak.com] Data leakage in time-dependent feature engineering – BitPeak — https://bitpeak.com/data-leakage-in-time-dependent-feature-engineering 7. [en.wikipedia.org] Relative strength index — https://en.wikipedia.org/wiki/Relative_strength_index 8. [en.wikipedia.org] Leakage (machine learning) — https://en.wikipedia.org/wiki/Leakage_(machine_learning) 9. [en.wikipedia.org] Feature engineering — https://en.wikipedia.org/wiki/Feature_engineering 10. [en.wikipedia.org] Technical analysis — https://en.wikipedia.org/wiki/Technical_analysis 11. [alishaang.github.io] safefeat: Leakage-Safe Feature Engineering for Event Logs (Python) — https://alishaang.github.io/projects/SafeFeat/ 12. [pypi.org] safefeat · PyPI — https://pypi.org/project/safefeat/

관련 글 추천

  • https://infobuza.com/2026/06/20/20260620-0tua4b/
  • https://infobuza.com/2026/06/20/20260620-yv6hck/

FAQ

시계열 모델에서 '데이터 누수(Data Leakage)'란 무엇인가요?

모델이 예측 시점에는 절대 알 수 없는 미래의 정보나 타겟 변수를 학습 중에 엿보는 현상을 말합니다. 이 경우 훈련 성능은 매우 높게 나타나지만, 실제 운영 환경에서는 성능이 급격히 떨어지게 됩니다.

RSI(상대강도지수)를 ML 모델의 피처로 사용하는 이유는 무엇인가요?

원시 시계열 데이터(Raw Data)는 노이즈가 너무 많기 때문입니다. RSI와 같은 의미 있는 피처로 변환하면 모델이 과매수 구간과 같은 숨겨진 패턴을 더 잘 포착할 수 있어 모델 성능을 끌어올리는 동력이 됩니다.

시계열 데이터 처리 시 '랜덤 스플릿(Random Split)'을 사용하면 안 되는 이유는 무엇인가요?

데이터를 무작위로 섞으면 미래의 관측치가 과거의 학습에 영향을 주게 되어, 시계열 데이터의 핵심인 인과 관계가 완전히 깨지기 때문입니다.

누수 없이 안전하게 RSI 피처를 구현하는 방법은 무엇인가요?

'Point-in-Time' 설계 전략을 사용해야 합니다. 구체적으로는 Pandas의 `shift()` 함수를 활용하여 현재 시점($t$)의 값을 포함하지 않고, 반드시 $t-1$ 시점까지의 데이터만 참조하도록 강제하는 방법이 있습니다.

데이터 누수로 인한 성능 착시를 방지하기 위한 검증 방법은 무엇이 있나요?

랜덤 스플릿 대신 전진 체이닝(Forward Chaining)이나 확장 윈도우(Expanding Window) 검증법을 도입해야 합니다. 또한 피처 중요도를 확인하여 특정 피처가 비정상적으로 압도적인 기여도를 보이는지 체크하는 것이 좋습니다.

이정엽 · 10년차 IT 엔지니어 · 테크 에디터
현업 개발·인프라 경험을 바탕으로 기술 트렌드를 직접 검증하고 풀어 씁니다. 모든 글은 작성 후 사람이 사실관계를 검토합니다.