본문 바로가기
Project/Predict Stock price Project

5. 주식 데이터 분석 - 가장 좋은 스케일링은? (주가 예측 프로젝트)

by inhovation97 2022. 3. 13.

학부 연구생으로서 진행한 주가 예측 프로그램의 일련의 과정을 차례로 포스팅합니다. 

위 그림처럼 어떤 종목이든 10일간의 데이터로

다음날 종가 상승 여부를 예측하는 머신러닝 프로젝트입니다.

 

주식 데이터는 여기저기 예제들도 굉장히 많이 있고,

비교적 얻기 쉬운 빅데이터이기 때문에 여러가지 프로젝트를 하시는 분들은 굉장히 많을 거라고 생각합니다. 

 

하지만 어려운 도메인인만큼 유의미한 모델링을 한 사례는 굉장히 적습니다. 

특히 주식을 잘 모르시는 분들에게는 정말 어려운 데이터죠...

제가 얻은 인사이트를 기록합니다.

주식 데이터 수집 - EDA - 전처리 - 모델링 - 성능 개선

이전 포스팅은 학습이 잘 되도록 EDA를 통해 주식 데이터의 질을 높이는 전처리 과정을 다루었습니다.

 

스케일링 방식에 따라서 얻는 결과의 차이가 굉장히 큽니다.

따라서 이번 포스팅은 4가지의 스케일링 방식의 성능을 비교하여,

가장 좋은 스케일링 방식을 선정합니다.

 

1. 주식 데이터에 대한 인사이트
2. 4가지 스케일링 방식
3. 4가지 스케일링의 성능 차이 비교하기 (LGBM) - 평가 지표 비교, 모의 수익률 비교

 

 

 

 

1. 주식 데이터에 대한 인사이트

 

저는 앞선 포스팅에서 모델도 선정했고, 그에 맞게 데이터 shape도 정하여 전처리 방식을 정했습니다.

1,561개의 기업들에 대해서 어떤 기업이든지 상관하지 않고, 거래대금이 10억 이상 터진 날을 기점으로 10일간의 데이터 흐름을 보고 다음날 11일차 주가가 상승하는지를 예측할 겁니다. 

그림 1

위 그림을 보면, 제가 정의한 문제가 쉽게 이해가실 겁니다.

하지만 수 천개의 상장사가 만들어 낸 금융 데이터는 아래와 같은 특징이 있습니다.

1. 액면가가 전부 다르다. 

(ex. 현 시점, 삼성전자 : 6만원대, 엔씨소프트 : 40만원대)

2. 모든 기업들의 주가 흐름은 다르다.

(ex. 현 시점, 삼성전자의 주가는 52주 최저가에 도달한 반면, 한일사료처럼 52주 신고가를 경신하고 있는 주식들이 있다. )

 

따라서 주식 데이터의 스케일링은 필수적인데, 이번 제 프로젝트에서는 4가지의 스케일링에 대한 방법이 제기됐습니다.선정한 모델에서 각각 4가지 스케일링 방식에 따른 성능을 비교하여 가장 좋은 스케일링 방식을 정합니다.

 

 

 

 

2. 4가지 스케일링 방식

 

10일치의 데이터(D-10 ~ D-1)로 다음 날의 주가(D-0) 상승 여부를 이진 분류합니다.

train : 1,561개 기업의 18~20년 주가 데이터
test : 1,561개 기업의 21년 주가 데이터

 

저의 경우 window size=10 이기 때문에 모델에 입력할 10일치의 데이터를 각각 스케일링 한 뒤, 전부 stack하여 train/test set을 구성합니다.

그림 1의 데이터에 대해 4가지 스케일링이 어떻게 인코딩 되는지 비교해봅시다.

 

※주의할 점

1. 기업마다 따로 데이터를 불러와 스케일링을 진행한 뒤 모든 데이터를 stack시켜야 합니다.

2. 주가로 계산된 지표들에 대해서만 스케일링을 진행해야합니다. ex) 이동평균선, 볼린저밴드 등등...

 

 

< 1번 방식 - MINMAX-240 스케일링 진행하기 >

MINMAX-240
X는 액면가 관련 지표

첫번째 스케일링은 대상 종목에 대해서 240일 기간의 MAX와 MIN값을 구하여, MIN-MAX Scaling을 진행한 것입니다. 대상 종목의 이동MAX(240일), 이동MIN(240일)을 구하여 스케일링하는 방식으로 인코딩하였습니다. y축의 스케일을 보시면, 위 데이터는 240거래일 동안 하락세에 있다는 정보가 내포된 것을 알 수 있습니다.

 

특징 : 해당 기업의 1년간의 주가 흐름을 고려하여, 현 시점의 가격지표들이 스케일링된다.

 

 

 

 

< 2번 방식 - MINMAX-window size 스케일링 진행하기 >

MINMAX-10
X는 액면가 관련 지표

두번째 스케일링은 대상 종목에 대해서 오직 10일 기간의 MAX와 MIN값을 구하여, MIN-MAX Scaling을 진행한 것입니다. 저의 경우 window size가 10이므로 MINMAX-10을 한 것입니다. 오직 10일 기간내에서만 스케일링을 진행했기에 window size내에서 max, min값이 전부 들어있습니다.

 

특징 : 오로지 windowsize내에서의 주가흐름만 반영된다.

trainset의 전체 기간(trainset 18년 ~ 20년)에 대해서 현 주가 수준은 알 수 없다.(상승세인지 하락세인지) 

 

 

< 3번 방식 - D-1의 종가로 나누기 >

DIV-LAST_CLOSE
X는 액면가 관련 지표

위 수식에서 D_0Close는 D-1거래일의 종가를 의미합니다.  

스케일링 2번 방식처럼 오로지 10일(window size)만 고려하여 스케일링을 진행하는데, 모든 액면가 관련 지표에 대해서 D-1의 종가로 나누어 1을 빼주는 스케일링을 진행합니다.

 

특징 : 오로지 windowsize내에서의 주가흐름만 반영된다.

D-1의 종가를 기준으로 지표들이 스케일링 된다.

trainset의 전체 기간(trainset 18년 ~ 20년)에 대해서 현 주가 수준은 알 수 없다.(상승세인지 하락세인지) 

 

< 4번 방식 - 매일매일의 종가로 나누기 >

 

DIV_EACH_CLOSE
X는 액면가 관련 지표

이 스케일링 방식은 어떤 기간(240일, window size)을 고려하지 않고, 매일매일의 가격 관련 지표를 전날의 종가에 대비하여 스케일링해줍니다. (가령 D-10은 D-11의 종가로전부 나눈뒤 1을 빼준 스케일입니다.)

따라서 인코딩된 데이터의 형태가 위 3가지 방법과는 다르게 인코딩되어 캔들 차트의 모양이 바뀐 것을 볼 수 있습니다. 

 

특징 : 오로지 전날 종가에 대비 변동폭을 표현한다.

전날 대비 변동 폭을 잘 설명한다.

trainset의 전체 기간(trainset 18년 ~ 20년)에 대해서 현 주가 수준은 알 수 없다.(상승세인지 하락세인지)

10일 기간에 대해서 현 주가 수준은 알 수 없다.(상승세인지 하락세인지)

 

 

스케일링 방법에 따른 시각화 비교

 

확실히 4번 스케일링이 인코딩되는 방식이 크게 다릅니다.  

작은 변동의 값들에는 0근처로 보내면서 큰 변동을 잘 표현하는 것 같습니다.

 

 

 

이제 각 스케일링 방법대로 인코딩된 4개의 데이터셋에 대해 모델을 학습시키고,

결과를 비교하여 가장 좋은 스케일링 방법을 비교합니다.

 

 

 

 

3. 4가지 스케일링의 성능 차이 비교하기 (LGBM)

 

사실 베이스 모델이 XGBoost였는데, 하이퍼 파라미터도 거의 똑같고 성능도 비슷한데 명성에 맞게 LGBM이 몇 배는 빠르게 학습하더라구요.

시행착오를 겪는 베이스 모델을 만들 때는 LGBM이 XGBoost보다 나은 것 같습니다.

(아래는 베이스 모델이며, 하이퍼 파라미터는 따로 다시 조정하였습니다.)

 

 

<베이스 모델>

from lightgbm import LGBMClassifier
import os
import time

# pos 8.2 & lr 0.08하면 더 좋음

start_time=time.time()

model = LGBMClassifier(
                       learning_rate=0.1, 
                       num_iterations = 1000,
                       max_depth = 4,
                       n_jobs=-1,
                       boost_from_average=False)

trained_model = model.fit( trainX,trainY, 
          eval_set=[(testX,testY)],
          early_stopping_rounds=25, 
          verbose = 5, 
          eval_metric = 'auc')​

 

<평가 지표>

def plot_roc_curve(trainY, testY, train_pred, test_pred, train_prob, test_prob):
    from sklearn.metrics import roc_curve, roc_auc_score, f1_score, f1_score, accuracy_score, recall_score, precision_score
    
    fpr, tpr, thresholds = roc_curve(testY, test_prob) # output 3개가 나오는데, 각 threshhold 마다의 fpr, tpr값 인듯
    
    train_f1 = f1_score(trainY, train_pred)
    test_f1 = f1_score(testY, test_pred)
    
    train_recall = recall_score(trainY, train_pred)
    test_recall = recall_score(testY, test_pred)
    
    train_pre = precision_score(trainY, train_pred)
    test_pre = precision_score(testY, test_pred)  
    
    train_acc = accuracy_score(trainY, train_pred)
    test_acc = accuracy_score(testY, test_pred)
    
    plt.plot(fpr, tpr, color='red', label='ROC')
    plt.plot([0, 1], [0, 1], color='green', linestyle='--')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('test ROC : {}'.format(round(roc_auc_score(testY, test_prob),3)),fontsize=16)
    plt.legend()
    plt.show()
    print('train_f1 score: ',train_f1)
    print('test_f1 score: ',test_f1,'\n')
    
    print('train_recall score: ',train_recall)
    print('test_recall score: ',test_recall,'\n')

    print('train_pre score: ',train_pre)
    print('test_pre score: ',test_pre,'\n')
    
    print('train acc score: ',train_acc)
    print('test acc score: ',test_acc, '\n')

LGBM으로 ROC커브, f1스코어, 재현율, 정밀도, 정확도 등등을 체크하여 성능을 비교합니다.

데이터는 위에서 소개한 스케일링을 진행하여,

이전 포스팅에서 언급한 전처리를 통해 train/test셋을 만듭니다. 

 

<거래 대금 10억 이상인 날(D-1)로부터 약 10일간의 데이터로 다음날(D-0) 주가의 5% 상승 여부 이진분류>

train : 1,561개 기업의 18~20년 주가 데이터 
test : 1,561개 기업의 21년 주가 데이터

 

<스케일링 비교하기>

 

스케일링 방법에 따른 시각화 비교
평가지표 비교 결과
모의 투자 시뮬레이션의 수익률 비교

저도 이렇게 스케일링 방법만으로 큰 차이가 날 줄은 몰랐습니다. 

수익률에서 굉장한 차이를 발생시키네요.

 

주가 데이터는 소음이 많이 섞인 데이터라서 평가 지표로만 해석하기에는 큰 무리가 있는 것 같습니다.

과연 모델이 유의미한 패턴을 학습했는지 예측한 값들의 분포와 예측하기 전 분포를 비교하여 해석을 많이 다룬 것 같습니다. (해당 포스팅에는 생략함.)

 

이것 저것 비교한 결과 4번 방식의 스케일링이 가장 좋다고 결론을 내렸습니다.

저는 앞으로 4번 스케일링으로 주가 데이터를 전처리하기로 결정했습니다.

 

스케일링 방식도 정했으니 다음 포스팅은 데이터 불균형을 해소시키는 성능 개선에 대해서 다룹니다.

 

 

주식 데이터는 정말 전처리할 것도 많고 생각해야 할 변수도 많아서, 시간도 정말 많이 들었습니다.

주식 데이터는 정말 어렵네요... 

 

댓글