본문 바로가기

Data & AI

AI 알고리즘 투자 - 몸풀기

YouTube : https://youtu.be/sUS1iNoepSA

 

 

데이터를 사용한 투자, 통계기법 전략과 AI전략의 차이

 제가 데이터를 통해서 투자를 한다는 것은 지금까지의 포스트를 보면 알 수 있을 것 같습니다. 데이터는 논리를 뒷받침하거나 확인할 수 있는 좋은 수단이자 이 시대를 살아가는데 유용한 재료라고 생각합니다. 투자를 떠나서 저는 데이터를 통해 가치를 찾아가는 게 즐겁습니다. 

 

 데이터를 통해서 투자를 한다고 모두 같은 투자를 하고있는것은 아닙니다. 데이터가 모이면서 우리는 통계적인 수치나 기법등을 통해 투자를 할 수 있습니다. 대표적으론 볼린저밴드, RSI, MACD 등의 기술적 지표들이 그렇습니다. 

이런 지표들도 좋은 투자 지표가 될 수 있고, 저의 많은 알고리즘들도 이런 통계적 기법들로 이루어진 전략들이 많이 있습니다. 하지만 인간이 정한 임의의 기준점들이 아닌 데이터에 기반한 기준들을 전략으로 만들고 싶은 마음이 생겼습니다. 

 

 

데이터 수집

데이터로 가치를 찾아나가면서 종목을 가리는건 아니지만 AI모델이 충분히 패턴을 찾고 학습할 수 있어야 한다고 생각했습니다. 그래서 일별 데이터로는 데이터양이 부족해서 최소 시간단위 데이터가 필요하고, 시간데이터 단위로 수집이 용이하고 새로운 금융 서비스 기회가 많은 블록체인, 암호화폐 데이터를 이용해 보면 좋겠다고 생각을 해서 이더리움 가격데이터로 인공지능 투자 모델을 만들기 위한 몸풀기를 해보려고 합니다.  

 

params = {
    'symbol': SYMBOL,
    'interval': '1h',
    'startTime': int(datetime(2020,1,1).timestamp() * 1000),
    'limit': 1500,
}

response = requests.get(BINANCE_API_DOMAIN + '/fapi/v1/klines', headers=header, params=params)
df = pd.DataFrame(response.json(), columns=['dt', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_asset_volume', 'number_of_trades', 'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore'])

 


요즘에는 데이터를 라이브러리로 쉽게 제공해주기도 하고 위와 같이 binance 거래소 API를 통해 1시간 데이터정도는 쉽게 데이터를 제공받을 수 있습니다. 학습을 위해선 1500개 정도의 데이터로는 부족하고 제공되는 시작시점부터 데이터 호출 시점까지 연속적으로 함수를 호출해서 준비해두었습니다.

 

 저는 거의 모든 개발 내용들을 독학해왔는데 그 과정에서 잘 설명하고 알려주는 것도 대단한 재능이라고 느끼고 제가 그런 쪽에는 뛰어난 역량이 상대적으로 부족하다고 생각하고 있습니다. 하지만 인공지능을 처음 접할 때 요리와 비유했던 것이 이해가 잘 되었어서 같은 방법으로 비유를 해서 설명하고자 합니다. 데이터를 수집하는 것은 요리를 하기 위한 재료를 준비하는 것과 같습니다. 

 

 

데이터 전처리

데이터 전처리는 요리재료를 손질하는 과정입니다. 목적에 맞는 요리를 위해 필요한 규격으로 재료를 썰거나 변형하는 과정이 필요합니다. 인공지능에서도 모델이 데이터를 잘 학습하고 이해하기 위해 변환하는 과정이 필요합니다. 우리가 목적으로 하는 수익률을 위해 모델이 고차원 영역의 실마리를 풀어내기 위해서 필요한 재료들을 준비해 주는 게 필요합니다. 

 

데이터를 제공받은곳마다 다르겠지만 기본적으론 시가 종가 고가 저가 거래량 정도 데이터를 제공받게 됩니다. 차트 가격만 보면서 거래를 하는 트레이더들이 많은데 이런 분들도 종가라는 하나의 값만 보는 게 아니라 과거의 가격 데이터가 그려낸 가격 추세, 지지선, 패턴 등을 보고 의사결정을 합니다. 우리도 우리의 모델이 잘 학습할 수 있도록 좋은 재료들을 준비해 주는 게 필요합니다. 저는 가볍게 많이 사용되는 기술적 지표들(RSI, MACD, OBV)에 단기, 중기, 장기적 시그널을 특성으로 준비해서 학습을 하려고 합니다.

 

제가 특성으로 정한 데이터들이 갖는 평균과 분산이 각각 다릅니다. 우리가 원하는 요리를 위해 재료들의 적절한 비율이 중요합니다. 예를 들어 방울토마토와 수박을 동일한 비율로 준비해야 하는 요리가 있는데 방울토마토 1개와 수박 1개를 준비해선 안 되겠죠. 모델이 학습하는 데이터들도 마찬가지로 특성들이 가지는 고유한 평균들에 얽메이지 않고 동등한 수치로 변환이 필요한데 이를 Scaling이라고 합니다. 저는 MinMaxScaling을 통해 데이터들의 Scaling을 진행해 주었습니다.

그리고 실제로 Scaling을 적용할때는 데이터가 딥러닝 레이어에 시퀀스로 잘라서 들어가게 되는데 그 길이를 24로 정하고 24시퀀스 단위마다 scaling을 진행해서 이상치 데이터에 크게 영향을 받지 않도록 적용했습니다.

 

from sklearn.preprocessing import MinMaxScaler
import seaborn as sns

scaler = MinMaxScaler()
scaler.fit(df)
scaled_data = scaler.transform(df)

sns.violinplot(data=scaled_data, palette="Set3", bw=.1, cut=2)
sns.set(rc={'figure.figsize':(30,10)})
sns.despine()

 

Scaling 이전의 특성들


Scaling 이후의 특성들

시계열 데이터 인공지능 예제를 보면 종가를 MLP에 넣고 다음 종가를 예측하는 글들이 많은데 저는 24시간의 데이터를 입력받아서 다음날 상승, 하락을 예측하는 어떻게 보면 복잡한 원 문제를 비교적 간단한 Binary Classification으로 해석해서 풀어보려고 합니다. Binary Classification이 가지는 특성들도 있고, 직관적으로 많은 사람들이 관심 갖는 지표란 생각도 듭니다. 

 

 

모델 학습

사실 저도 학습을 위해 완벽한 비율의 노드수와 은닉계층을 어떻게 해야 할지 무지한 상태입니다. 
하지만 가지고 있는 시계열 데이터를 잘 활용할 수 있는 RNN 모델을 기반으로 알고리즘을 작성해 보았습니다.
물론 Transformer가 등장하고 시계열에서 과거 Attention을 찾는 게 더 중요하다고 생각하면서 RNN 사용이 많이 줄어들긴 했으나 여전히 시퀀스데이터 처리에 활용가능한 가장 기본형태의 RNN을 사용해보려고 합니다.

 

Keras에서 제공하는 RNN레이어가 있지만
Gradient Vanishing을 제거하기 위해 Batch Normalization을 적용한 따로 구현한 RNN레이어를 사용하도록 했습니다. 

class LNSimpleRNNCell(keras.layers.Layer):
    def __init__(self, units, activation='tanh', **kwargs):
        super().__init__(**kwargs)
        self.state_size = units
        self.output_size = units
        self.simple_rnn_cell = keras.layers.SimpleRNNCell(units, activation=None)
        self.layer_norm = keras.layers.LayerNormalization()
        self.activation = keras.activations.get(activation)

    def call(self, inputs, states):
        outputs, new_states = self.simple_rnn_cell(inputs, states)
        norm_outputs = self.activation(self.layer_norm(outputs))
        return norm_outputs, [norm_outputs]

 

순차적으로 RNN 레이어를 쌓아 Deep RNN으로 구성하였고, 24시 퀀스를 입력으로 사용하고 각 레이어별로 노드수를 줄여가며 복잡성을 낮춰보도록 했습니다.

 

마지막은 RNN 1 Layer로 기본적으로 하이퍼볼릭 탄젠트 활성화 함수를 갖기 때문에 -1 ~ 1 사이의 값을 내놓습니다. 학습 라벨 자체를 하락, 상승으로 두었기 때문에 직관적으로 이해할 수 있을 것 같습니다. 

개인적으로 gpu장비가 있긴 하지만 앞으로 많은 AI 모델들 학습을 할 거고 학습량이 많이 필요한 Transformer기반 모델, 강화학습을 진행하기 위해 Google Colab Pro를 결제했습니다. 저와 제 사업에 대한 작은 투자라고 생각하고 투자를 통해 찾아낸 가치는 여러분들께 공유할 수 있도록 하겠습니다.  

 

학습 모델 시각화

 

데이터를 학습할 데이터와 학습하며 검증을 위한 데이터로 분리하고 학습을 진행시켰습니다. 

추후에 MLops 환경도 구축할 예정인데 그때는 대시보드와 학습되는 과정이 녹화되도록 해보겠습니다.

 

1년 전 시점인 2022년 5월까지의 데이터를 학습시켜 보았고 학습한 모델을 기반으로 학습 이후 모델이 입력 값들을 받았을 때 어떤 예측을 하는지, 그런 출력을 기반으로 매매를 했으면 어떤 수익을 얻을 수 있는지 시각화해보았습니다.  

 

위 차트가 이더리움의 수익률, 아래가 AI모델이 보내는 신호대로 매매했을 때의 수익률입니다.
x축에 수직으로 그어진 점선은 학습데이터가 사용된 시점입니다. 학습데이터 이전을 보면 모델이 학습데이터에 대해 Overfitting 되었기 때문에 학습데이터 이전 시점에 대해선 현실에선 불가능한 수준으로 완벽한 예측을 하고 있습니다. 

 

주목할 만한 점은 학습데이터를 소진한 바로 직후 AI가 예측하는 내용입니다. 이 부분을 조금 더 확대해 보겠습니다. 

 

대략 2~3달 정도의 기간인데 2배 정도의 수익을 올린 모습을 보입니다. 

 

해석하기 나름이지만 이더리움 가격이 지속적으로 하락할 때 우연히 숏포지션을 취하라고 학습되어서 운이 좋았던 것일 수 있고, 이더리움의 패턴을 학습해 둔 것이 어느 정도 지속되다가 소멸되었다고 해석할 수도 있을 것 같습니다. 하지만 더 긴 시간이 흐르면 학습시킨 패턴은 사라지고 수익률이 저조해집니다. 시장은 언제나 유기적으로 변화하고 패션처럼 늘 새롭고 기발한 아이디어로 전략을 만들어내는 게 필요한 이유입니다. 그 과정에 데이터와 AI가 도움이 된다면 좋을 것 같습니다. 

 

개선점

몸풀기에 가까울 정도로 가볍게 모델을 만들어보고 수익률을 확인해 보았습니다. 아쉽게도 학습데이터에 과적합되었지만 과적합된 데이터 그 나름 유의미한 해석을 주는 것 같습니다. 중요한 건 장기적로 안정적인 수익을 위해서 지속적으로 아이디어를 만들어내고 알고리즘으로 만들어 전략으로 사용시켜야 한다는 점입니다. 사실 인공지능 모델을 만드는 건 오히려 쉽습니다. 그보다 이 분야에 대해 조예 깊은 지식들과 경험에 기반한 생각들이라고 생각합니다.

 

 제가 예전에 도메인 지식의 중요성 영상에서도 이야기했듯 좋은 인공지능을 위해선 해당 도메인의 지식이 필요합니다. 인공지능이 지금에 와서는 인간보다 더 나은 성능을 내고 있지만, 시초는 인간처럼 문제를 해결하는 소프트웨어를 만들기 위함이었습니다. 우리가 더 많은 지식을 습득하고 그 지식을 공유하는 게 더 나은 모델을 만드는 과정이라고 생각합니다.

 

 오늘 내용을 포함해서 개선할 사항을 더 다져나가고 더 의미 있고 가치 있는 일들을 찾아서 여러분들에게 제공하도록 하겠습니다.

 

감사합니다.