강화학습 기반 주식 트레이딩 시스템

머신러닝 알고리즘 분류(유형)는 크게 목적(라벨) 변수 유무에 따라 지도학습과 비지도학습으로 분류한다. 또 하나  재미있는 분류로는 강화학습이 있다. 강화학습은 에이전트와 환경이 주어질 때, 에이전트가 행하는 행위에 대한 보상(reward)으로 학습한다. 데이터 1건1건마다 라벨링값이 주어지는 지도학습과 달리 강화학습에서는 행위에 대한 보상(지도학습에서의 라벨링 역할)이 매번 주어질 필요가 없다. 이를 지연 보상(delayed reward)이라고 한다. 따라서 매번 행위 때마다 reward를 할 필요없이 행위가 여러번 시행된 이후 결과만 보상해도 학습이 된다라는 사실이다. 강화학습을 사용한 바둑을 생각하면 이해가 될 것이다. 매수하다 보상이 아니라 승패 결과만 보상해도 된다.

트레이딩 관점에서의 강화학습

트레이딩 관점에서 강화학습을 생각하면 에이전트는 트레이더(trader)이고 에이전트의 행위는 사고 팔고 그리고 아무런 행위도 안하는 것이다. 사고 나서 아무런 행위를 안하면 산 종목을 보유하겠다는 것으로 해석 가능하다. 에이전트가 구별할 수 있는 환경(에이전트가 인식할 수 있는 상태값)은 주식에서 얻을 수 있는 데이터들이다. 가장 기본적으로 차트 데이터가 있고 기타로는 지표 (PER 등), 뉴스 등 다양한 것들이 있을 수 있다. 강화학습이 제대로 학습만 된다면 너무나도 좋다. 사고 팔고 할 때 매번 보상을 줄 필요 없이 일정 기간 동안의 수익률(바둑에서의 승패)만 가지고도 학습이 왠지 쉬워 보일 듯 하다. 지도학습처럼 살 때 팔 때 따로 따로 모델을 만들어서 학습할 필요없이 강화학습 에이전트의 행위 자체가 사고 파는 그리고 보유(무행위)하는 인공지능 모델이 한번에 만들어지니 얼마나 좋겠는가…

실전 경험

강화학습을 접한지는 오래되었지만, 주식에 접하면 어떨까 싶어 시도를 해본 경험은 몇년 전이다. 뉴스나 논문을 봐도 강화학습을 이용한 로봇 트레이딩 시스템이 종종 있다. 그러나 필자가 시도한 바로는 학습이 쉽지 않았다. 사고 팔고 보유하는 단일 모델로 트레이딩 시스템을 구현해보고 싶었으나 현재까지도 보류(지금은 강화학습보다는 지도학습으로 변경) 상태이다. 강화학습에 대한 이해가 부족해서인지 아니면 에이전트 입력값(환경 상태)을 잘 못 잡아서인지 어려웠다. 강화학습 구현에는 텐서플로우 기반 오픈 소스를 활용해 DQN 이라는 딥러닝 강화학습 알고리즘을 사용했다. 시중에 나와있는 책을 사서도 봤지만 학습이 되질 않았다. 왜 학습이 안될까? 여기서 학습이 안된다는 의미는, 에이전트가 보지 못한 테스트 데이터셋에 적용을 해서 수익률이 나지 않음을 의미한다.  내 나름 주식 환경에서 강화학습이 어려운 점을 정리해 본다.

  1. 상태 공간이 너무 커 DQN 망 학습이 어려움.
    결국 DQN의 입력값은 상태값이 되며, 출력값은 가치(value) 값인데 상태에 대한 가치 추정이 어려움
  2. 에이전트 독립적인 환경
    보통 강화학습에서의 에이전트와 환경의 관계에는 에이전트 행위에 따라 환경이 상태값을 리턴하며 최종 목적지에 도착할 경우 보상을 준다. 그리드(grid) 월드나 바둑을 생각하면 된다. 그러나 주식 환경에서는 에이전트 행위와 거의 상관없이 환경이 변한다. 수십만 수백만 에이전트가 환경에 물려 있어 실제 거래하고 있는 에이전트는 환경에 거의 영향을 줄 수 없다는 의미다. 다시 말해, 목적 지향적인 패스가 주어지고 최종 보상이 주어지는 환경이 아니라는 것이다. 랜덤워크로 변화하는 차트를 기반으로 에이전트 입장에서는 마구 잡이로 보상하는 환경에 대해서 에이전트가 과연 학습을 할 수 있겠는가?

필자의 실전 경험과 이해를 바탕으로 작성한 글이니 잘못 작성된 부분도 있을 것이다. 혹시 다른 의견을 가지고 계신 분이나 주식 환경에서의 강화학습이 가능하다라고 주장하시는 분, 기타 등등 관련 내용을 공유해 주시면 정말 고마울 것이다. ㅎ 정말로 궁금하다 과연 강화학습으로 수익이 날 수 있는지… 가끔 강화학습 기반 로보트레이더 기사를 보면 더욱 궁금해진다. 세계 최고 강화학습 기술을 보유하고 있는 그 유명한 딥마인드(DeepMind)는 왜 주식에 적용하지 않을까? ㅎㅎ

(강화학습에 관심있는 여러분의 의견 내지는 조언을 듣고 싶습니다.)

LDA 토픽 모델링

가끔 주식 관련 특징주 기사를 보면 주가에 영향을 줄만한 기사가 뜨는 경우가 있다. 물론 좋은 기사가 뜬다고 해서 주가가 항상 오르지는 않는다. 다만 테스트를 해보고 싶었다.

데이터 수집

먼저 기계 학습을 위해 관련 데이터 수집이 필요하다. 특정 사이트 URL를 선정해서 인터넷 기사와 주가와의 연관성 분석을 위해 5년간의 특징주 관련 기사를 수집했다. 그런 다음 기사가 뜬 시점의 주가와 2일 후 변동 주가를 기록하여 데이터를 수집하였다.

데이터 학습

데이터 학습은 LDA(Latent Dirichlet Allocation)라는 토픽 모델링 방법을 사용하였다. 신규 기사가 뜰 경우 LDA 토픽 벡터와 유사한 기사들을 검색하고 검색된 기사들의 주가 전후 변동값을 비교한 후, 신규 기사에 대한 주가 변동량으로 추정하는 방법을 이용하였다.

아래는 pseudo code


if new_article:
    tpv = lda_topic_vec(new_article)
    sims = find_similarity(tpv)
    ss = sort(sims, 10)  # get top 10 of similarity
    for article in ss:
        sumret += calc_change_rate(article)
    avgret = sumret/N
    if avgret > 0.02
        buy(ar)

LDA 란…

LDA는 잠재 디리클레 할당이라고 하는데, 문서에 잠재되어 있는 토픽(topic)을 이용해 분류(cluster)하는 방법론이다. 비지도 학습(unsupervised learning)의 일종이다. 나이브분류기(Naive Classifier)와 같은 예전 방법에는  문서를 포함하고 있는 단어들의 확률적인 분포로 문서를 분류했는데 LDA에서는 보이지 않은 토픽이라는 잠재(latent, hidden) 변수를 더 활용하는 점이 다르다. 단어는 직접적으로 확인 가능하지만 토픽은 추상적인 존재이기에 잠재라는 단어를 사용한다. 또 LDA는 디리클레라는 확률적인 분포를 가정하는 것이 특징이다. 반면 pLSA 와 같은 방법론은 확률적인 분포를 가정하지 않는다.

LDA 의 확률 분포는 다시 말해, 토픽 벡터의 요소가 양수이며 모든 요소를 더한 값이 1인 경우에 대해서 확률값이 정의되는 분포이다.

가령 토픽이 경제, 정치 2가지 뿐이라면 경제와 정치 2가지 토픽을 더해서 1이 되는 경우라 이해할 수 있다. 즉, 경제가 0.9, 정치가 0.1 정도의 토픽 비율의 문서는 가능한데, 경제 0.9, 정치 0.9 비율로 토픽이 구성된 문서는 사전 가정에서 배제하는 것이다.

위키에서 발췌한 아래 그림은 토픽 3개인 경우로 이해하면 되고 중앙이 큰 값을 가진다는 의미는 토픽이 어느정도 골고루 섞힌 문서가 많이 존재한다.(확률적으로 높은 값을 가짐)라는 의미로 해석할 수 있다.

(위키 그림 발췌)

 

LDA 토픽 모델링 결과, 주가에 긍적적인 기사 예

결과로만 보면, 신약 개발 관련 기업들의 기사 관련 내용들이 주가에 단기적으로 긍정적인 영향을 주는 것으로 파악되었다. 그래서 필자는 LDA 토픽 모델링 기법을 써서 특정 사이트를 모니터링 하다가 신약 개발 관련 기사들이 뜰 때는 자동으로 매수하도록 프로그램을 돌리기도 했다. 하지만 역시 소문에 팔고 기사에 팔라는 말이 맞는 듯…ㅎ

순환 신경망 (LSTM) 활용 주가 예측

시계열 데이터 예측에 좋은 성능을 낸다는 순환 신경망을 통해 제가 현재 보유하고 있는 내츄럴엔도텍 주식에 대한 예측을 해보고자 합니다. 내츄럴엔도텍은 한 때 백수오로 알려진 업체이며 최근 홈쇼핑 판매 개시로 많은 관심을 받고 있습니다.

 LSTM이란…

순환 신경망은 보통 RNN(Recurrent Neural Network)라고 하는데 그레디언트 소실(Gradient Vanishing Problem)을 해결하고자 메모리를 도입한 LSTM(Long-Short Term Memory)을 주로 이용합니다.

LSTM은 시계열 데이터 처리에 있어서는 ARIMA 등 기존 알고리즘보다 좋은 성능을 내는 것으로 알려져 있습니다. LSTM에 대한 자세한 내용은 여기를 참조하시기 바랍니다. 순환 신경망의 놀라운 효과 라는 안드레 카파시 블로그 글 (영문)도 참고하시기 바랍니다. 순환 신경망으로 세익스피어 글도 짓고 자바 프로그래밍도 합니다.

LSTM 소개에 대한 이미지 검색결과

기존 MLP 신경망은 은닉층의 노드값을 계산할 때 입력에 가중치를 곱해서 은닉층의 노드값(상태)값을 업데이트 합니다. 그러나 순환 신경망은 그와 달리 은닉층의 노드값을 계산할 때 이전 히든(hidden) 노드에 대한 상태값과 입력을 모두 활용합니다. (아래 수식 참조)

Alt text

 

 

이런 방법으로 은닉층 상태를 업데이트 하기에 시계열 데이터에서의 패턴 변화를 감지할 수 있게 됩니다. 또한 LSTM은 순환신경망에 메모리까지를 가지고 있어 과거 시계열 데이터의 패턴 변화를 더 잘 잡아내는 특징을 가지고 있습니다.

좀 더 자세히 설명을 드리면 LSTM은 메모리가 있으며 메모리 입출력 컨트롤을 위한 소자(논리적인 장치)가 있는데 게이트(gate)라고 합니다. 게이트에는 입력(input), 출력(output) 게이트 그리고 망각(forget) 게이트가 있습니다.

LSTM 게이트에 대한 이미지 검색결과

LSTM을 학습하는 방법은 조금 복잡합니다. 기본적으로는 BPTT (Backpropagation Through Time) 을 사용합니다. 알고리즘은 BP와 유사하지만 순환 신경망에서는 시계열 데이터를 다루다보니 그리고 은닉층이 이전 은닉층 상태값까지 고려하다보니 그로 인해 조금은 복잡합니다. 순환 신경망 그래프 안에 네트워크가 연결된 구조를 펼쳐(unfold) 오차에 준한만큼 역으로 따라가며 전파하여 가중치를 학습합니다. 자세한 내용은 밑바닥부터 시작하는 딥너링이라는 책을 한번 읽어보시면 좋을 듯 합니다. 또는 Graphically Determining Backpropagation Equations 블로그 자료를 참고하시길 바랍니다.

 학습 데이터

LSTM 학습에 사용한 데이터로는 아래와 같은 형태로 저장된 csv 포맷을 읽어서 처리했습니다(다운로드:  A168330) 미리 아래와 같은 포맷으로 데이터를 저장해두고 나서 학습한 것입니다. 그리고 간단히 종가(Close) 데이터만을 이용해서 학습했습니다.

Date Open High Low Close Volume
20170816 27250 32450 27100 31500 3341469
20170814 25700 26800 24400 26750 1384477
20170811 25300 25750 24050 24950 2019038

 케라스 활용 LSTM 구현

LSTM을 파이썬으로 돌리는 방법은 여러 가지가 있지만 많이 사용되는 케라스(Keras) 라이브러리를 이용했습니다. 케라스는 텐서플로우를 기반으로 쉽게 사용할 수 있도록 하기 위한 일종의 래핑(wrapping) 라이브러리 입니다.

import os
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
import math
from sklearn.metrics import mean_squared_error

look_back = 1
def create_dataset(dataset, look_back=1):
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back-1):
        a = dataset[i:(i + look_back)]
        dataX.append(a)
        dataY.append(dataset[i + look_back])
    return np.array(dataX), np.array(dataY)

# file loader
sydtpath = "D:sydt"
naturalEndoTekCode = "A168330"
fullpath = sydtpath + os.path.sep + naturalEndoTekCode + '.csv'
pandf = pd.read_csv(fullpath, index_col="Date")

# convert nparray
nparr = pandf['Close'].values[::-1]
nparr.astype('float32')
print(nparr)

# normalization
scaler = MinMaxScaler(feature_range=(0, 1))
nptf = scaler.fit_transform(nparr)

# split train, test
train_size = int(len(nptf) * 0.9)
test_size = len(nptf) - train_size
train, test = nptf[0:train_size], nptf[train_size:len(nptf)]
print(len(train), len(test))

# create dataset for learning
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)

# reshape input to be [samples, time steps, features]
trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))

# simple lstm network learning
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=2)

# make prediction
testPredict = model.predict(testX)
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform(testY)
testScore = math.sqrt(mean_squared_error(testY, testPredict))
print('Train Score: %.2f RMSE' % testScore)

# predict last value (or tomorrow?)
lastX = nptf[-1]
lastX = np.reshape(lastX, (1, 1, 1))
lastY = model.predict(lastX)
lastY = scaler.inverse_transform(lastY)
print('Predict the Close value of final day: %d' % lastY)  # 데이터 입력 마지막 다음날 종가 예측

# plot
plt.plot(testPredict)
plt.plot(testY)
plt.show()

결과 화면

아래 차트 오른쪽 부분이 내츄럴엔도텍이 최근(2017년 8월) 홈쇼핑 판매 개시로 주가가 오르고 있는 부분입니다. 실제 주가(파란색)와 예측 주가(노란색)로 출력되어 있습니다. 예측은 현재일 (1일)을 이용해서 다음날 (1일)을 예측합니다. 마지막 날 예측이 어긋나는게 아쉽습니다

stocksLSTM2

위 소스에 대해 문의가 있거나 틀린 점, 보완할 점이 있으면 아래 댓글 남겨주시면 감사하겠습니다. 그리고 위 소스 내용은 아래 사이트(Machine Learning Mastery) 자료를 참고해서 개발한 것입니다.
Machine Learning Mastery

참고

RBM (제한된 볼츠만 머신) 이해

요즘 한창 뜨고 있고 있는 딥러닝을 공부하고자 한다면 RBM (Restricted Boltzmann machine)이라는 제한된 볼츠만 머신이라는 알고리즘을 최소 한번은 들어 보았을 것이다. 확률적인 개념이라 다소 이해하기 어려운 면도 있어 가급적 쉽게 설명해보고자 한다. RBM을 로봇 트레이딩에 어떻게 활용할지는 아직 잘 모르겠지만… (아래 등장하는 수식에 있어서는 설명의 편의를 위해 간소화시킨 부분도 있음을 미리 언급해둔다.)

RBM은 우선 DBN(DBN, Deep Belief Network)이라고 하는 딥러닝의 일종인 심층신뢰신경망을 구성하는 기본적인 요소이다. 즉 RBM을 여러겹 쌓아서 심층신뢰신경망을 만든다.

그리고 RBM의 구조는 단순하다. 관찰 가능한 가시층(visible layer)과 은닉층(hidden)으로만 구성된다. 아래 그림에서 아래층이 가시층, 윗층이 은닉층인 것이다.

rbm
<RBM>

다만 같은 층 내부 노드간의 연결은 없고 층과 층 사이와의 연결만이 있다. 이런 점에서 제한적(Restricted)라고 불리운다. 그럼 이제 RBM의 주요 개념을 간단히 살펴보자

확률 기반 단층 신경망 RBM

역전파 신경망과 비교해보면 이해가 쉬울 수 있다. 역전파와 비슷하게 RBM도 입력노드에 가충치를 곱한 다음 시그노이드 함수를 적용해 은닉층의 값을 구하는 방법은 비슷하다. 다만 확률적으로 샘플링해서 구한다. 역적파 신경망에서는 시그모이드(Sigmoid) 결과값이 바로 노드의 출력값이 되지만, RBM에서는 노드의 값을 결정짓기 위한 확률값이다. 가령 0.8이라고 하면 역전파 신경망에서는 0.8이 바로 노드 출력값이겠지만 RBM에서는 0.8이 확률값이기에 노드 출력값이 확률에 따라 결정된다. (아래 관련 수식, 가시층 l번째 노드가 1일 때의 확률 분포)

 p(V_l = 1 |h) = sigma (sumlimits_{i=1}^n w_{il} h_i)

확률은 미지의 세계를 모델링하는 데 좋은 도구이다. 가령 내일 비가 올지 예측하는 문제에 대해서 분석적으로 접근하면 아직 미지의 변수가 너무 많아 어렵지만 확률은 그 미지의 것들을 덮어버리고 다만 숫자로 표현하면 그만인 것이다. RBM에서는 머신만이 이해할 수 있는 수치적(가충치) 정보를 확률적으로 학습하는 것이다. 신경망에 확률 개념을 도입하는 이유도 그와같은 이유이다. 다시 말해, 미지의(Unknown) 패턴이 많기 때문이다.

RBM은 에너지라는 개념이 있다. 역전파 신경망을 생각하면 목표치가 있기에 오류치를 계산하고 오류치 만큼 역전파시켜 학습을 시키는 데 RBM은 단층이기에 목표치가 없다. 그래서 다른 방식의 개념이 필요한데 바로 에너지라는 개념이다. 에너지(E)는 마이너스(-) 부호를 가지고 가중치가 0보다 큰 수이기에 입력과 출력이 양의 상관 관계에 있을수록 에너지가 작아진다. 예로 입력이 -1일 때 은닉층 결과가 -1이면 에너지가 최소가 된다.  홉필드 네트워크에서도 비슷한 에너지 개념을 사용하고 있으니 참고하길 바란다.

E(v,h) = - sumlimits_{i=1}^n sumlimits_{j=1}^m w_{ij} h_i v_j

RBM의 학습 방법은 입력층 노드값에 가충치를 곱하고 더하고 확률을 구하고 확률에 근거하여 샘플링하여 은닉층의 노드값을 결정한다. 은닉층의 노드값이 결정되면 또 다시 입력층의 노드값들을 같은 방식으로 결정한다. 그러면서 에너지를 최소화하는 방향으로 가충치를 학습하는 것이다.

참조

나이브 베이즈 분류 개념 이해

나이브 베이즈(Naïve Bayes Classification)는 확률 기반 분류기의 일종으로 1950대 이후 광범위하게 연구되고 있다.

쉽게 설명하면 다음과 같다. 예로 흡연과 간암과의 상관 관계는 널리 알려진 사실이다. 하지만 흡연을 할 경우에 간암에 걸릴 확률을 추정할 수 있을까? 이때 사용하는 방법이 나이브 베이즈 방법이다. 

p(간암|흡연) = p(흡연|간암)*p(간암)/p(흡연)

간암 확률과 흡연 확률 그리고 간암이 걸린 상태일 때의 흡연 확률을 알면 흡연할 때 간암이 걸린 확률, 다시말해 원인이 주어질 때 결과가 될 확률을 추론할 수 있다. 범위를 좁혀 우리 나라 인구만 적용한다면 간암에 걸린 사람의 확률, 흡연 확률 그리고 간암에 걸린 사람들을 대상으로 흡연하고 있는 확률을 구할 수 있다.

중요한 점은 나이브 베이즈는 특징(feature)이 독립적이라고 가정하면 1개 이상 여러 개로 확장할 수 있다. 쉽게 말해 흡연 외에 간암이 될 요인들을 여러 개로 확장할 수 있다는 것이다. 특징이 어려개 이고 확률적으로 각각의 특징으로 확률적으로 조사만 된다면 가령 아래와 같이 현재 그 사람의 습관이나 상태에 따라 간암에 대한 발생확률을 기계적으로 학습 가능할 것이다.

p(간암|흡연, 간염, 성별, 직업, ...)

로봇 트레이딩에서는 어떤 식으로 활용 가능할까? 가령 간단하게는 기업 공시를 나이브 베이즈로 학습해서 주가에 영향을 긍정적으로 주는 단어들을 학습하고자 할 때 나이브 베이즈를 사용할 수 있을 것이다. 

 

챠트 패턴 매칭을 위한 DTW

주가는 관성의 원리에 따라 추세를 지속하려는 속성이 있으며 파동과 사이클을 반복하려는 속성이 있다. 주가의 추세를 담고 있는 챠트는 그런 면에서 의미가 있다. 차트의 대표적인 유형으로는 상승 추세와 하강 그리고 횡보 추세 등 다양하게 존재한다. 이러한 점은 로봇 트레이딩에서 중요한 정보로 사용된다. 로봇 트레이딩에서 기계적으로 챠트 유형이나 패턴을 분석하고자 할 때 DTW(Dynamic Time Warping)이라는 알고리즘을 사용하기도 한다.  DTW 소개 자료를 찾다 유용한 자료를 찾아 내용을 정리해본다.(아래 참고자료에서 내용 발췌함을 표기함)

기본 DTW 알고리즘

DTW는 패턴간 유사도를 검색하기 위한 알고리즘이다. 찾고자 하는 패턴을 주어지면 DTW 알고리즘으로 가장 유사하게 생긴 주가 챠트를 찾을 수 있는 것이다.

dtw_intro

조금 수학적인 용어를 사용한다면 비교하고자 하는 패턴을 X, Y라고 하면 X := (x_1 , x_2, ..., x_N) 이고 Y := (y_1 , y_2 , ..., y_M)으로 표기 가능하다. 여기서 중요한 점은 X의 개수와 Y의 개수가 다를 수 있다는 점이다. X의 개수와 Y의 개수가 다르다면 패턴 매칭에 있어 고려해야할 사항이 많을 것이다.

DTW는 패턴 매칭에 있어 아래와 같은 조건을 만족해야 한다.

  • 끝점 제약의 조건(Boundary condition): 입력 패턴(X)과 참조 패턴(Y)의 시작점과 끝을 일치시킨 상태에서 패턴 비교
  • 단조 증가 제약 조건(Monotonicity condition): 최적 경로는 항상 단조로 증가해야 한다
  • 단계 증가 조건(Step size condition): 입력 패턴과 참조 패턴 비교 시 격자상의 한 노드에서 다른 노드에 도달하기 위해 필요한 단계 사이즈에 제한을 둠. 가령 스텝 사이즈가 1일 경우 (1, 1)과 비교를 하였다면 다음 격자는(1, 2) 또는 (2, 1), (2, 2) 등의 비교가 가능해짐

각 X와 Y 격자별 각각에 대하여 거리값(difference)를 구하면 가령 아래와 같은 매트릭스(matrix) 형태가 나올 것이다. (검은 색이 가깝고, 밝은 색이 거리값이 큼)

dtw_cost

DTW로 X, Y 패턴의 거리는 결국 거리값 매트릭스에서 가장 최저(최선)의 솔루션(경로)을 찾는 것이다. (아래 그림 참조)

dtw_find_path

다만 위와 같은 비용 매트릭스(cost matrix) 를 모든 영역에 대하여 산출하면 많은 연산을 해야 되기에 (1, 1)에서부터 누적 비용 매트릭스 (accumulated cost matrix)를 계산한다.  이로써 전체 비용 매트릭스가 아닌 누적해가며 최소가 되는 매트릭스 일부를 구하게 된다. 누적 비용 매트릭스를 수식화하면 아래 공식과 같다. c(x_n , y_m)x_n y_m간의 거리 비용을 의미한다.

D(n, m) = min {D(n-1, m-1), D(n-1, m), D(n, m-1)}+c(c_n , y_m)

누적 비용 매트릭스가 계산하고 나면 이제 x_n, y_m 부터 역으로 최저 패스를 찾아가는 방법으로 X, Y 패턴간 최소 거리를 찾는다.

찾고자 하는 패턴을 Y라고 하면, 종목별 각각의 챠트데이터를 가져와 DTW를 적용하고 나면 가장 가까운 X 패턴을 찾을 수 있을 것이다. 그러면 찾고자 하는 패턴(예로 상승패턴)에 가장 가까운 챠트에 대한 종목을 알 수 있게 된다.

DTW 확장 알고리즘

기본 DTW을 확장한 여러 알고리즘이 있다.

  • 단계 증가를 변경: 기존 DTW의 단계 증가는 0 또는 1인데 이를 2~3으로 증가시켜 변경하는 식으로 응용
  • 가중치 적용: 경로에 있어 가중치를 부여함. 가령 비용 매트릭스에서 x축, y축 보다는 대각선 방향 가중치를 높일 수 있음
  • 전역 경로 제약: 경로 생성에 있어 영역을 제한하는 방식(아래 그림)

dtw_global

  • 멀티스케일(Multiscale) DTW: 매칭시 큰 영역에서 작은 영역으로 하향(Top-down) 방식으로 경로를 찾아가는 방식
  • 부분 매칭 (subsequence) DTW: X, Y 전체가 아닌 X와 Y 일부만 매칭하는 방식

참조

의사 결정 트리 (Decision Tree)를 활용한 주식 예측 방법

의사 결정 트리는 데이터 마이닝에서 일반적으로 사용되는 방법으로 입력 변수에 대하여 분류/예측하는 모델을 생성하는 것을 목표로 한다.

(위키백과에서 그림 발췌)

위 그림은 타이타닉 생존자에 대한 결정 트리를 나타낸 것이다. 의사 결정 트리는 화이트 박스(white box)로 분류 기준을 쉽게 파악할 수 있는 장점이 있다.

주식에 있어서는 비슷한 방법으로 활용 가능하다. 가령 다음날 주가를 예측한다면 주가에 영향을 줄만한 항목을 선정한다. 가령 종가, 거래량, 이동평균선 등 여러 가지 지표가 선정 가능할 것이다. 그리고 선정된 종목에 대해서 데이터를 모아야 한다. (아래는 예)

5000, 10000, 4500, 상승
5500, 3000, 4700, 하락,

위와 같이 수집된 데이터에 대해서 의사결정트리 방법을 적용하면 위에서 위 타이타닉 그림과 같은 트리 형태의 구조가 도출되는 것이다.

의사결정 트리가 학습하는 원리는 엔트로피(Entropy)와 분류 전후 엔트로피 차이에 따른 정보 획득량(Information gain)이 주로 사용된다. 엔트로피 식은 아래식과 같다. 직관적으로 학습하는 원리만을 설명하면 주어진 데이터를 분석하여 주가 상승에 가장 많은 영향을 미치는 속성이 루트(root)에 위치하게 된다. (마치 타이타닉 생존자 여부를 판단하는 데 있어 남자 여부가 가장 중요한 역할이며 루트에 위치한 것처럼)

E = - sum_{i=1}^{n} p_i log_2 p_i

참고로 자바 머신러닝 라이브러리인 웨카(Weka)에서 J48(C4.5 기반) 분류기를 사용하면 학습 결과뿐 아니라 관련 소스 코드까지 얻을 수 있어 관심있는 분은 시도해볼만 하다. 주가 관련 여러 가지 데이터들을 전부 입력하여 의사 결정 트리로 학습하면 최소한 어떤 데이터 속성이 가장 큰 영향을 미치는지 기계적으로 분석 가능하다.

참조