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

나스닥100 상승·하락, 금리·VIX·달러로 예측 가능할까? 파이썬 LSTM으로 직접 분석

금알남 읽는 시간 약 23분
ai thumbnail illustration 나스닥100 상승·하락 파이썬 LSTM으로 직접 분석 1789544407

나스닥100을 볼 때 가격 차트만 보는 것보다 미국채 금리, 장단기 금리차, VIX, 달러 흐름을 함께 보면 시장 환경을 조금 더 구조적으로 볼 수 있습니다. 이 글에서는 이 변수들을 실제 데이터로 연결하고 LSTM으로 향후 나스닥 방향 확률을 계산하는 과정을 정리했습니다. 미국 성장주나 나스닥 ETF를 장기적으로 투자하고 있다면 모델의 결과보다 어떤 변수를 왜 보는지에 초점을 맞춰 읽어보시면 좋습니다.

나스닥100은 주가 차트만 보고 예측할 수 있을까?

주식 투자를 하다 보면 이런 생각을 한 번쯤 하게 됩니다.

“내일 나스닥이 오를지 미리 알 수는 없을까?”

조금 더 공부하면 질문이 바뀝니다.

“미국채 금리가 오르고 VIX도 상승하는데 달러까지 강해지고 있다면 나스닥에는 어떤 영향을 줄까?”

여기서부터 투자 분석은 단순한 차트 읽기를 넘어갑니다.

나스닥100은 100개의 대형 나스닥 상장 비금융 기업을 추적하는 지수이며 수정 시가총액 방식으로 구성됩니다. Nasdaq은 2026년에도 지수 방법론을 일부 개정했기 때문에 장기간 데이터를 분석할 때는 지수 구조 자체도 시간에 따라 조금씩 달라질 수 있다는 점을 기억할 필요가 있습니다.

이번에는 나스닥100 가격 하나만 넣지 않겠습니다.

미국 10년물 국채금리.

미국 2년물 국채금리.

10년물과 2년물의 장단기 금리차.

VIX 공포지수.

미국 달러지수.

그리고 최근 나스닥100의 수익률과 변동성.

이 변수들을 LSTM 신경망에 넣고 앞으로 5거래일 뒤 나스닥100이 현재보다 높을 확률을 학습시켜보겠습니다.

여기서 중요한 것은 “AI가 미래를 맞힌다”는 이야기를 하려는 것이 아닙니다.

오히려 반대입니다.

정말 예측력이 있는지, 없는지를 데이터 밖의 테스트 구간에서 확인해보는 것이 목적입니다.

금리·VIX·달러를 함께 보는 이유

먼저 미국채 금리입니다.

미국 10년물 국채금리는 장기 금리 환경을 살펴볼 때 널리 사용되는 지표입니다. FRED의 DGS10은 연방준비제도 H.15 자료를 기반으로 일별 미국 10년물 국채 수익률을 제공합니다.

2년물 금리도 같이 보겠습니다.

DGS2 역시 연준 H.15 기반의 일별 2년물 국채 수익률입니다.

여기서 하나의 변수를 더 만들 수 있습니다.

10년물 금리 – 2년물 금리

즉 장단기 금리차입니다.

나스닥100 상승·하락, 금리·VIX·달러로 예측 가능할까? 파이썬 LSTM으로 직접 분석
df["spread_10y_2y"] = df["DGS10"] - df["DGS2"]

단순히 금리 수준 하나를 보는 것보다 수익률곡선의 형태를 같이 보는 것입니다.

두 번째는 VIX입니다.

VIXCLS는 CBOE의 VIX 종가를 일별로 제공하는 데이터입니다. 시장 불안과 변동성 환경을 설명하는 변수로 많이 활용됩니다.

마지막은 달러입니다.

이번 분석에서는 흔히 말하는 특정 선물 기반 DXY 대신 연방준비제도가 제공하는 광의의 명목 무역가중 달러지수 DTWEXBGS를 사용하겠습니다.

이 지수는 미국의 주요 교역 상대국 통화를 가중해 계산하며 FRED에서 일별 데이터로 제공됩니다.

그리고 나스닥100 자체도 FRED에서 일별 종가 NASDAQ100 시계열로 불러올 수 있습니다. 원자료 제공자는 Nasdaq입니다.

그래서 이번에는 데이터 출처를 하나로 통일할 수 있습니다.

파이썬으로 바로 시작해보겠습니다.

파이썬으로 LSTM 나스닥 방향 예측 모델 만들기

먼저 필요한 라이브러리를 설치합니다.

pip install pandas numpy pandas-datareader scikit-learn tensorflow matplotlib

이제 데이터를 가져옵니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from pandas_datareader import data as web

from sklearn.preprocessing import StandardScaler
from sklearn.metrics import (
    accuracy_score,
    roc_auc_score,
    confusion_matrix,
    classification_report
)

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping

np.random.seed(42)
tf.random.set_seed(42)

start = "2010-01-01"
end = pd.Timestamp.today()

series = [
    "NASDAQ100",
    "DGS10",
    "DGS2",
    "VIXCLS",
    "DTWEXBGS"
]

df = web.DataReader(
    series,
    "fred",
    start,
    end
)

print(df.tail())

변수들의 휴일이 조금씩 다르기 때문에 결측값을 정리합니다.

df = df.sort_index()

# 경제지표가 발표되지 않는 휴일 등의 짧은 공백 처리
df[
    ["DGS10", "DGS2", "VIXCLS", "DTWEXBGS"]
] = df[
    ["DGS10", "DGS2", "VIXCLS", "DTWEXBGS"]
].ffill(limit=5)

# 나스닥 거래일이 없는 날짜 제거
df = df.dropna(subset=["NASDAQ100"])

이제 모델이 학습할 변수를 만들어보겠습니다.

# 나스닥 수익률
df["ndx_ret_1d"] = df["NASDAQ100"].pct_change()
df["ndx_ret_5d"] = df["NASDAQ100"].pct_change(5)
df["ndx_ret_20d"] = df["NASDAQ100"].pct_change(20)

# 최근 변동성
df["ndx_vol_20d"] = (
    df["ndx_ret_1d"]
    .rolling(20)
    .std()
    * np.sqrt(252)
)

# 금리 변화
df["dgs10_chg_1d"] = df["DGS10"].diff()
df["dgs10_chg_5d"] = df["DGS10"].diff(5)

df["dgs2_chg_1d"] = df["DGS2"].diff()
df["dgs2_chg_5d"] = df["DGS2"].diff(5)

# 장단기 금리차
df["spread_10y_2y"] = (
    df["DGS10"] - df["DGS2"]
)

# VIX 변화율
df["vix_ret_1d"] = df["VIXCLS"].pct_change()
df["vix_ret_5d"] = df["VIXCLS"].pct_change(5)

# 달러 변화율
df["usd_ret_1d"] = df["DTWEXBGS"].pct_change()
df["usd_ret_5d"] = df["DTWEXBGS"].pct_change(5)

이번 모델이 맞히려는 목표도 만들어야 합니다.

오늘을 기준으로 5거래일 후 나스닥100이 지금보다 높으면 1.

낮거나 같으면 0으로 설정합니다.

df["future_ret_5d"] = (
    df["NASDAQ100"].shift(-5)
    / df["NASDAQ100"]
    - 1
)

df["target"] = (
    df["future_ret_5d"] > 0
).astype(int)

이제 입력 변수를 정합니다.

features = [
    "DGS10",
    "DGS2",
    "spread_10y_2y",

    "dgs10_chg_1d",
    "dgs10_chg_5d",
    "dgs2_chg_1d",
    "dgs2_chg_5d",

    "VIXCLS",
    "vix_ret_1d",
    "vix_ret_5d",

    "DTWEXBGS",
    "usd_ret_1d",
    "usd_ret_5d",

    "ndx_ret_1d",
    "ndx_ret_5d",
    "ndx_ret_20d",
    "ndx_vol_20d"
]

data = df[
    features + ["target", "future_ret_5d"]
].dropna()

print(data.shape)

여기서 일반적인 머신러닝과 LSTM의 차이가 나옵니다.

LSTM은 오늘 하루의 데이터만 보는 것이 아니라 최근 일정 기간의 흐름을 하나의 묶음으로 학습할 수 있습니다.

이번에는 최근 20거래일을 사용하겠습니다.

즉,

최근 20일의 금리

최근 20일의 VIX

최근 20일의 달러

최근 20일의 나스닥 흐름

을 보고 향후 5거래일 방향을 판단하게 만드는 것입니다.

하지만 여기서 매우 중요한 원칙이 있습니다.

금융 시계열에서 데이터를 무작위로 섞으면 안 됩니다.

미래 데이터를 학습 과정에서 간접적으로 볼 수 있기 때문입니다.

따라서 과거 → 현재 순서대로 나눕니다.

n = len(data)

train_end = int(n * 0.70)
val_end = int(n * 0.85)

X = data[features].values
y = data["target"].values

scaler = StandardScaler()

# scaler 역시 과거 학습 데이터만 사용
scaler.fit(X[:train_end])

X_scaled = scaler.transform(X)

LSTM용 시퀀스를 만듭니다.

sequence_length = 20

X_seq = []
y_seq = []
end_index = []

for i in range(sequence_length, len(data)):

    X_seq.append(
        X_scaled[
            i - sequence_length:i
        ]
    )

    y_seq.append(
        y[i]
    )

    end_index.append(i)

X_seq = np.array(X_seq)
y_seq = np.array(y_seq)
end_index = np.array(end_index)

이제 학습·검증·테스트 데이터로 나눕니다.

train_mask = end_index < train_end

val_mask = (
    (end_index >= train_end)
    & (end_index < val_end)
)

test_mask = end_index >= val_end

X_train = X_seq[train_mask]
y_train = y_seq[train_mask]

X_val = X_seq[val_mask]
y_val = y_seq[val_mask]

X_test = X_seq[test_mask]
y_test = y_seq[test_mask]

print(X_train.shape)
print(X_val.shape)
print(X_test.shape)

이제 LSTM 모델을 만듭니다.

model = Sequential([
    LSTM(
        64,
        return_sequences=True,
        input_shape=(
            sequence_length,
            len(features)
        )
    ),

    Dropout(0.20),

    LSTM(
        32
    ),

    Dropout(0.20),

    Dense(
        16,
        activation="relu"
    ),

    Dense(
        1,
        activation="sigmoid"
    )
])

model.compile(
    optimizer=tf.keras.optimizers.Adam(
        learning_rate=0.001
    ),
    loss="binary_crossentropy",
    metrics=["accuracy"]
)

model.summary()

과적합을 조금이라도 줄이기 위해 EarlyStopping을 적용합니다.

early_stop = EarlyStopping(
    monitor="val_loss",
    patience=15,
    restore_best_weights=True
)

history = model.fit(
    X_train,
    y_train,

    validation_data=(
        X_val,
        y_val
    ),

    epochs=200,
    batch_size=32,

    callbacks=[
        early_stop
    ],

    verbose=1
)

그리고 가장 중요한 테스트 구간입니다.

prob = model.predict(
    X_test,
    verbose=0
).flatten()

pred = (
    prob >= 0.5
).astype(int)

accuracy = accuracy_score(
    y_test,
    pred
)

auc = roc_auc_score(
    y_test,
    prob
)

print(
    "Test Accuracy:",
    round(accuracy, 4)
)

print(
    "Test ROC-AUC:",
    round(auc, 4)
)

print(
    confusion_matrix(
        y_test,
        pred
    )
)

print(
    classification_report(
        y_test,
        pred,
        digits=4
    )
)

여기서 숫자가 나왔다고 바로 좋아하면 안 됩니다.

예를 들어 정확도가 높게 나왔더라도 상승일 자체가 더 많은 데이터라면 단순히 항상 상승을 예측해도 제법 높은 정확도가 나올 수 있습니다.

그래서 반드시 기준 모델과 비교해야 합니다.

baseline = max(
    y_test.mean(),
    1 - y_test.mean()
)

print(
    "Naive Baseline Accuracy:",
    round(baseline, 4)
)

LSTM의 정확도가 이 기준과 거의 차이가 없다면 복잡한 딥러닝을 사용했지만 실제 정보는 거의 추가하지 못했다는 뜻일 수 있습니다.

ROC-AUC 역시 함께 확인하는 것이 좋습니다.

0.5 부근이라면 상승과 하락을 구분하는 능력이 제한적일 가능성이 있고, 테스트 구간마다 결과가 크게 달라진다면 모델 안정성을 더 검증해야 합니다.

실제 숫자는 데이터 조회일, 학습 기간, TensorFlow 버전, 초기값과 모델 설정 등에 따라 달라질 수 있으므로 여기서는 임의의 결과를 제시하지 않겠습니다.

직접 실행한 테스트 결과를 기준으로 판단하는 것이 맞습니다.

상승 확률이 높으면 바로 매수하면 될까?

여기서 가장 조심해야 할 부분입니다.

모델이 예를 들어

상승 확률 0.72

라는 값을 출력했다고 가정해보겠습니다.

이 숫자를 그대로

“5일 뒤 상승할 확률이 72%다”

라고 받아들이면 곤란합니다.

신경망의 sigmoid 출력값은 모델이 계산한 분류 점수에 가깝고, 그 숫자가 실제 발생확률과 정확하게 일치한다는 보장은 없습니다.

확률 자체를 투자에 활용하려면 calibration까지 추가로 검증해야 합니다.

또 하나 중요한 문제가 있습니다.

금융시장의 관계는 계속 변합니다.

과거에는 금리 상승에 민감했던 시장이 다른 시기에는 기업이익 증가를 더 중요하게 볼 수 있습니다.

VIX의 의미도 시장 국면에 따라 달라질 수 있고 달러 강세의 영향 역시 매번 같지 않습니다.

따라서 전체 기간을 한 번 나누어 성능을 확인하는 것만으로 끝내기보다 궁극적으로는 Walk-Forward Validation을 하는 편이 좋습니다.

예를 들면 이런 구조입니다.

  1. 2010~2016년 학습 → 2017년 테스트
  2. 2010~2017년 학습 → 2018년 테스트
  3. 2010~2018년 학습 → 2019년 테스트
  4. 이후 같은 방식 반복

이렇게 해야 특정 한 시기에만 우연히 잘 맞은 모델인지 조금 더 구체적으로 확인할 수 있습니다.

그리고 여기에서 더 중요한 질문도 나옵니다.

정확도가 몇 퍼센트인가?

보다 실제 투자에서는

“모델 확신도가 높은 구간만 투자했을 때 결과가 달라지는가?”

가 더 중요할 수 있습니다.

예를 들어 모든 날 매매하는 것이 아니라

long_signal = prob >= 0.60

처럼 모델이 상대적으로 강한 상승 신호를 보낸 시점만 별도로 분석해볼 수도 있습니다.

반대로

risk_off_signal = prob <= 0.40

인 시기를 위험관리 구간으로 사용할 수도 있습니다.

다만 여기서부터는 반드시 거래비용, 세금, 슬리피지, 매매 빈도까지 함께 고려해야 합니다.

백테스트 수익률만 보고 판단하면 실제 투자 결과와 큰 차이가 생길 수 있기 때문입니다.

결국 AI보다 중요한 것은 투자 판단 구조입니다

이번 모델에서 가장 중요한 결론은 LSTM이 내일의 나스닥을 맞혀준다는 것이 아닙니다.

오히려 시장을 바라보는 변수를 구조적으로 정리할 수 있다는 점입니다.

예전에는 뉴스를 보면서

“10년물 금리가 올랐네.”

“VIX가 올라갔네.”

“달러가 강해졌네.”

각각 따로 봤다면 이제는 하나의 데이터 구조로 연결해서 볼 수 있습니다.

특히 다음 질문을 계속 확장할 수 있습니다.

  1. 10년물보다 2년물 금리가 나스닥에 더 중요한 시기는 언제인가?
  2. 장단기 금리차가 확대될 때와 축소될 때 나스닥 반응은 다른가?
  3. VIX가 높은 상황에서는 금리의 영향력이 더 커지는가?
  4. 달러 강세와 금리 상승이 동시에 나타나면 결과가 달라지는가?
  5. 나스닥 상승확률 모델의 성능은 시장 국면에 따라 어떻게 달라지는가?

이런 질문들이 쌓이기 시작하면 단순히 “주가를 맞히는 모델”에서 끝나지 않습니다.

자신만의 시장 진단 시스템으로 발전시킬 수 있습니다.

다만 딥러닝이라는 단어에 기대를 너무 크게 걸 필요도 없습니다.

복잡한 모델이 단순한 모델보다 항상 좋은 것은 아닙니다.

로지스틱 회귀, Random Forest, XGBoost, LSTM을 같은 테스트 구간에서 비교했는데 성능이 비슷하다면 오히려 단순하고 해석하기 쉬운 모델이 실전에서는 더 유용할 수도 있습니다.

그리고 모델 성능이 좋더라도 한 번 더 확인해야 합니다.

미래 정보를 실수로 사용하지 않았는가.

스케일링 과정에서 테스트 데이터가 들어가지 않았는가.

백테스트에서 거래비용을 고려했는가.

시장 상승 편향 때문에 정확도가 높아 보이는 것은 아닌가.

특정 시기에만 잘 맞은 모델은 아닌가.

이 다섯 가지를 확인하지 않은 머신러닝 투자모델은 숫자가 화려해도 실제 활용가치는 크게 떨어질 수 있습니다.

NASDAQ-100의 일별 종가는 FRED에서 Nasdaq 제공 데이터로 확인할 수 있으며 미국 10년물·2년물 국채금리는 연준 H.15, 달러지수는 연준 H.10, VIX는 CBOE 자료를 기반으로 제공됩니다.

자주 묻는 질문

Q1. LSTM을 사용하면 나스닥 방향을 정확하게 예측할 수 있나요?

그렇게 단정할 수 없습니다. 금융시장은 정책, 기업 실적, 지정학적 사건, 투자심리 등 학습 데이터에 포함되지 않은 다양한 변수의 영향을 받습니다. LSTM은 과거 데이터의 패턴을 학습하는 도구이지 미래를 보장하는 도구가 아닙니다.

Q2. 금리, VIX, 달러 중 어떤 변수가 가장 중요하나요?

시장 국면에 따라 달라질 수 있습니다. 그래서 특정 변수 하나만 중요하다고 가정하기보다 Permutation Importance, SHAP 분석이나 변수 제거 실험을 이용해 테스트하는 방법이 더 적절합니다.

Q3. 실제 투자에 바로 사용할 수 있나요?

모델 결과만으로 매수·매도 결정을 내리는 것은 신중할 필요가 있습니다. Walk-Forward 검증, 거래비용, 슬리피지, 세금, 포지션 크기, 최대 손실폭 등을 추가로 검토해야 실제 투자 전략에 가까워집니다.

이번 분석의 핵심은 AI가 시장을 맞히느냐가 아닙니다.

금리와 변동성, 달러, 주가를 따로 보는 대신 하나의 데이터 시스템으로 연결하고 내가 가진 투자 가설이 실제 데이터에서도 유지되는지 확인하는 것입니다.

그 과정이 반복되면 뉴스에 흔들리는 투자에서 조금씩 벗어나 자신만의 판단 기준을 만들 수 있습니다.

다음 단계에서는 이 모델에 한 가지를 더 추가해볼 수 있습니다.

바로 LSTM, XGBoost, 로지스틱 회귀를 동일한 데이터로 학습시키고 실제 Out-of-Sample 구간에서 누가 더 잘 작동하는지 비교하는 것입니다.

딥러닝이 정말 더 나은지. 아니면 단순한 모델이 오히려 더 안정적인지. 그 비교부터가 실제 퀀트 분석의 시작입니다.

본 글은 금융시장과 데이터 분석 방법에 대한 교육 및 정보 제공을 목적으로 작성되었습니다. 특정 금융상품의 매수·매도 또는 투자수익을 보장하거나 권유하기 위한 내용이 아닙니다. 과거 데이터와 백테스트 또는 머신러닝 모델의 결과가 미래 성과를 보장하지 않으며 투자 과정에서 원금 손실이 발생할 수 있습니다.

데이터 출처: Nasdaq, Inc., Board of Governors of the Federal Reserve System, CBOE, Federal Reserve Bank of St. Louis FRED.

개인 유의사항: 본문의 파이썬 코드는 교육용 예시입니다. 데이터 조회일, 결측값 처리 방법, 학습 기간, 변수 구성, 모델 초기값과 라이브러리 버전에 따라 결과가 달라질 수 있습니다. 실제 투자 결정은 투자자의 재무상황, 투자기간, 투자목적과 손실 감내 수준을 충분히 고려하여 판단하시기 바랍니다.

금알남

금알남
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

광고 차단 알림

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

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