지난 번에는 비트코인 주가 예측을 위한 머신러닝 기술 활용을 위한 이론적인 부분을 전체적으로 정리해 보았습니다. 워낙 복잡하고 어려운 부분이라서 간단하게 대략적으로만 정리해 보려해도 내용이 무척 많았습니다. 이번에는 실제 코드로 작성하게되면 어떻게 구성되는지 한번 테스트 코드로 작성한 전체 내용 중 중요 부분만 블록별로 정리해 보도록 하겠습니다.
비트코인 주가 예측을 위한 머신러닝 모델
데이터 수집 및 전처리
비트코인 데이터는 업비트 거래소의 원화 마켓 데이터를 가져와서 엑셀 파일에 저장 후 사용했습니다. 작업환경 조건에 따라서 실시간 데이터를 사용해 볼 수도 있는 부분이므로 이런 데이터를 사용했구나 정도로 넘어가시면 됩니다. 이 데이터에는 날짜, 종가(Close), 거래량(Volume), 최고가(High), 최저가(Low) 등이 포함되어 있습니다.
file_path = 'bitcoin_주가_01.xlsx'
btc_data = pd.read_excel(file_path, engine='openpyxl')
기술 지표 계산
기술 지표는 주가의 미래 동향을 예측하는 데 도움을 줍니다. 여기서는 RSI, MACD, Bollinger Bands를 계산합니다.
- RSI (Relative Strength Index): 주가의 과매수 또는 과매도를 나타내는 지표입니다.
- MACD (Moving Average Convergence Divergence): 주가의 두 이동평균선 간의 차이를 이용한 지표입니다.
- Bollinger Bands: 주가의 변동성을 측정하고 예측하는 데 사용되는 지표입니다.
# RSI 계산
def compute_RSI(data, window):
delta = data.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
RS = gain / loss
RSI = 100 - (100 / (1 + RS))
return RSI
# MACD 계산
def compute_MACD(data, short_window=12, long_window=26, signal_window=9):
short_ema = data.ewm(span=short_window, adjust=False).mean()
long_ema = data.ewm(span=long_window, adjust=False).mean()
MACD = short_ema - long_ema
signal = MACD.ewm(span=signal_window, adjust=False).mean()
return MACD, signal, MACD - signal
# Bollinger Bands 계산
def compute_BB(data, window=20, num_sd=2):
rolling_mean = data.rolling(window=window).mean()
rolling_std = data.rolling(window=window).std()
upper_band = rolling_mean + (rolling_std * num_sd)
lower_band = rolling_mean - (rolling_std * num_sd)
return upper_band, rolling_mean, lower_band
특성 생성 및 전처리
우리는 주가 데이터에서 다양한 특성을 생성합니다. 여기에는 날짜와 관련된 연도, 월, 일, 요일, 주 등의 정보와 가격 변동성, 이동평균, RSI, MACD, Bollinger Bands 등이 포함됩니다. 생성된 특성들은 머신러닝 모델의 입력 변수로 사용됩니다.
# 추가 특성 생성
df = btc_data.rename(columns={'Date': 'ds', 'Close': 'y'})
df['volume'] = btc_data['Volume']
df['price_range'] = btc_data['High'] - btc_data['Low']
df['returns'] = btc_data['Close'].pct_change()
df['volatility'] = df['returns'].rolling(window=28).std()
df['avg_price'] = (btc_data['High'] + btc_data['Low']) / 2
df['moving_avg_20'] = btc_data['Close'].rolling(window=20).mean()
df['moving_avg_50'] = btc_data['Close'].rolling(window=50).mean()
df['RSI'] = compute_RSI(btc_data['Close'], window=28)
df['MACD'] = btc_data['MACD']
df['MACD_signal'] = btc_data['MACD_signal']
df['MACD_hist'] = btc_data['MACD_hist']
df['BB_upper'] = btc_data['BB_upper']
df['BB_middle'] = btc_data['BB_middle']
df['BB_lower'] = btc_data['BB_lower']
모델 학습
다양한 머신러닝 모델을 사용하여 주가를 예측합니다. 여기서는 Prophet, XGBoost, RandomForest, GradientBoosting, LightGBM 모델을 사용했습니다.
다양한 모델을 사용한 이유
주가 예측은 매우 복잡하고 불확실성이 높은 작업입니다. 단일 모델만으로는 모든 상황을 정확하게 예측하기 어렵기 때문에, 여러 모델을 사용하여 각 모델의 장점을 활용하고 단점을 보완하려는 목적으로 진행했습니다.
각 모델의 특징
a) Prophet
- 페이스북에서 개발한 시계열 예측 모델입니다.
- 주가의 계절성, 추세, 휴일 효과 등을 자동으로 감지하고 모델링할 수 있습니다.
- 비교적 간단하면서도 강력한 성능을 보입니다.
b) XGBoost, RandomForest, GradientBoosting, LightGBM
- 이들은 모두 결정 트리를 기반으로 한 앙상블 학습 방법을 사용합니다.
- 여러 개의 약한 예측 모델을 결합하여 강력한 예측 모델을 만듭니다.
- 비선형적인 관계를 잘 포착할 수 있어 복잡한 주가 패턴을 학습하는 데 적합합니다.
- XGBoost: 그래디언트 부스팅의 개선된 버전으로, 속도와 성능이 뛰어납니다.
- RandomForest: 여러 개의 결정 트리를 독립적으로 학습시켜 평균을 내는 방식으로, 과적합에 강합니다.
- GradientBoosting: 이전 모델의 오차를 줄이는 방향으로 순차적으로 모델을 만듭니다.
- LightGBM: XGBoost와 유사하지만 더 빠르고 메모리 효율적입니다.
모델 조합의 효과
- 예측 정확도 향상: 각 모델이 주가 데이터의 다른 측면을 포착할 수 있어, 전체적으로 더 정확한 예측이 가능합니다.
- 안정성 증가: 한 모델의 예측이 부정확하더라도 다른 모델들이 이를 보완할 수 있어 전체적인 예측의 안정성이 높아집니다.
- 다양한 시나리오 고려: 각 모델이 다른 가정과 방법론을 사용하므로, 다양한 시장 상황을 고려한 예측이 가능합니다.
- 과적합 위험 감소: 여러 모델을 사용함으로써 한 모델이 훈련 데이터에 과도하게 맞춰지는 것을 방지할 수 있습니다.
- 해석 가능성 향상: 다양한 모델의 결과를 비교분석함으로써, 주가 변동의 원인을 더 깊이 이해할 수 있습니다.
이러한 방식으로 여러 모델을 조합하면, 단일 모델을 사용할 때보다 더 견고하고 신뢰할 수 있는 주가 예측 시스템을 구축할 수 있습니다. 물론, 이는 완벽한 예측을 보장하지는 않지만, 불확실성이 높은 금융 시장에서 더 나은 의사결정을 내리는 데 도움이 될 수 있습니다.
# Prophet 모델 학습
prophet_model = Prophet(changepoint_prior_scale=0.5, seasonality_prior_scale=20, changepoint_range=0.95, seasonality_mode='multiplicative')
for feature in selected_features:
prophet_model.add_regressor(feature)
prophet_model.fit(train_df)
# XGBoost 모델 학습
param_grid_xgb = {'learning_rate': (0.01, 0.3, 'log-uniform'), 'max_depth': (3, 11), 'n_estimators': (100, 1500), 'subsample': (0.6, 1.0), 'colsample_bytree': (0.6, 1.0), 'gamma': (0, 0.3), 'reg_alpha': (0, 1), 'reg_lambda': (0, 1)}
xgb_model = xgb.XGBRegressor(objective='reg:squarederror')
bayes_search_xgb = BayesSearchCV(estimator=xgb_model, search_spaces=param_grid_xgb, n_iter=50, scoring='neg_mean_absolute_error', cv=5, verbose=1, random_state=42)
bayes_search_xgb.fit(x_train, y_train)
# 다른 모델도 동일한 방식으로 학습
모델 예측 및 성능 평가
각 모델의 예측 결과를 결합하여 최종 예측을 생성합니다. 그리고 실제 주가와 예측 주가를 비교하여 모델의 성능을 평가합니다. 여기서는 MAE(Mean Absolute Error)와 MAPE(Mean Absolute Percentage Error)를 사용하여 성능을 평가했습니다.
# 성능 평가
mae = mean_absolute_error(actual, combined_forecast['Final_Prediction'])
mape = mean_absolute_percentage_error(actual, combined_forecast['Final_Prediction'])
print(f'Mean Absolute Error: {mae:.2f}')
print(f'Mean Absolute Percentage Error: {mape * 100:.2f}%')
이 결과로 다음의 결과를 얻었습니다. 좋은 성능은 아니지만, 시계열 모델만을 사용했을 경우보다 그래도 상당히 높은 수준의 결과입니다.
이상으로 비트코인 주가 예측을 위한 머신러닝 모델 개발 과정을 수행해 보았습니다. 머신러닝을 활용한 주가 예측은 단순히 모델을 학습시키는 것뿐만 아니라, 다양한 기술 지표와 특성을 생성하여 모델의 성능을 향상시키는 것이 중요한 것같습니다.