적어도 2주에 한 번씩은 모델을 개선하고 전략을 찾아 추가하려고 했으나, 일을 하며 부수적으로 무엇인가 한다는 것은 매우 어려웠다...
앞 포스터에서 언급한 것처럼 "조코딩"님의 유튜브를 참고하여 strategies.py에는 변동성 돌파 전략을, models.py에는 페이스북의 시계열 모델인 Prophet을 추가했다. 그 외에도 validation.py에 모델의 성능을 검증하는 model_validation
함수와 이전 데이터로 수익률을 판단해보는 backtesting
함수, 그리고 backtesting
을 시각화하는 기능을 추가하였다.
Strategy: 변동성 돌파 전략 (Volatility Break-out Strategy)
해당 전략은 위 그림을 통해 설명할 수 있다. 전 날의 시가와 종가 사이에서 최솟값과 최댓값의 차이를 변동폭으로 정의한다. 금일 시가를 기준으로 가격이 변동폭 * K
배보다 커지면 매수를 진행하고 금일 장이 끝날 때, 구매한 주를 매도하여 수익을 낸다. (여기서 K
는 하이퍼파라미터로 최적 값을 찾아야 하고 코인은 장이 열리는 시간이 따로 없기 때문에 이 시간을 임의로 설정해야 한다.)
이는 전 날 변동폭을 기준으로 하여 금일 장이 충분히 (변동폭 * K
배만큼) 증가하였다면 탄력을 받아 더 오를 것이라 가정하고 매수를 진행하는 전략이다.
이를 이해했다면 모델을 적용시키기도 어렵지 않다. 금일 장이 변동성 돌파 전략의 매수 조건을 만족하였다면 바로 매수를 하지 않고 예측 모델을 이용하여 금일 종가의 가격을 예측하는 것이다. 만약, 예측 값이 매수 조건을 만족한 시점의 가격보다 클 때, 매수를 진행한다.
결국 "전략의 매수 조건 만족"과 "모델의 예측 값이 현재가보다 높음", 이 두 가지 모두가 만족될 때, 매수를 진행하는 것이다.
나는 더욱 안전한 매수를 위해 단순히 모델의 예측 값이 현재가보다 높은 것이 아닌 현재가 * increase_rate
보다 높을 때 매수를 진행하는 더 높은 조건을 걸어두었다.
Model: Prophet
첫 번째 예측 모델로 추가한 Prophet은 페이스북에서 공개한 시계열 예측 모델이다. 정확도가 높고 하이퍼 파라미터 튜닝이 쉽다는 장점을 가지고 있다.
Prophet은 y를 예측할 때, Trend, Seasonality, Holiday를 결합하여 나타낸다.
Trend는 선형 또는 logistic 곡선으로 표현되며 이는 주기적이지 않은 변화를 나타낸다.
Seasonality는 일 단위, 주 단위, 혹은 연 단위 등의 계절성을 나타내는 패턴을 나타낸다.
Holiday는 특정 기간의 비정상적인 값의 증가 또는 감소 같은 불규칙한 이벤트를 나타낸다.
현재는 단순히 모델을 학습하고 예측하는 것만 구현하여 하이퍼파라미터의 종류와 튜닝 과정은 추후에 포스팅할 것이다.
Validation: Model Validation
앞으로 모델을 추가하고 모델의 하이퍼파라미터를 튜닝하여 최적의 모델을 찾기 위해서는 모델을 검증해야 한다. 이는 정의된 데이터셋으로 모델을 학습하고 예측하여 실제 값과의 Loss를 산출하는 과정을 뜻한다.
모델 검증에서 정해야 할 것은 코인 가격을 예측할 날짜, 예측 값과 실제 값을 비교할 Loss이다.
먼저 예측할 날짜는 매월 1일, 16일의 장이 열리는 시간과 장이 열리는 시간+12로 설정하였다. 이렇게 연속적인 날이 아닌 큰 간격을 두고 예측하는 이유는 최대한 학습 데이터의 중복을 막기 위해서이다. 예를 들어, 시간 단위로 트레이딩을 진행하고 200개의 학습 데이터셋을 구성한다면 특정 날의 가격을 예측할 때, 200/24일 이전까지의 데이터를 학습 데이터로 사용하게 된다. 따라서 3월 1일 9시, 10시, 11시와 같이 연속적인 날로 검증한다면 대부분의 학습 데이터셋이 겁쳐 다양한 케이스에 대한 검증을 할 수 없게 된다.
다음으론 Loss이다. Loss는 단순하게 MSE(Mean Squared Error)와 MAE(Mean Absolute Error) 중에 선택하기로 하였다. 비트코인의 가격은 천만원대로 예측값의 대부분에서 십만원의 오차가 있다면 MSE는 \(100,000^2\) 으로 매우 커져 해석하기에도 어려워진다. 따라서 직관적인 MAE를 사용하기로 하였다.
모델 검증 함수를 돌렸을 때, 아래와 같이 로깅이 된다.
...
0번째 행의 설명 추가한다. 1월 1일 9시를 현재 시간으로 설정하고 이를 포함하여 200개의 데이터셋을 학습 데이터로 설정하였다. 장이 열리는 시간을 9시로 설정했기 때문에 1일 9시까지의 데이터를 학습하고 2일 9시의 코인 가격을 예측한다. 2일 9시의 실제 가격을 y
, 예측 가격을 yhat
으로 표현하였다.
모델 검증까지만 구현되었을 뿐, 아직 모델 성능을 올리기 위한 과정은 진행하지 않아 MAE가 매우 높은 1,594,453인 것을 확인할 수 있다.
Validation: Back-Testing
백테스팅은 과거 데이터를 사용해서 투가 전략이 어느 정도의 수익률이 나는지 확인하는 과정이다. 실제 내 돈을 투자하여 전략과 모델을 평가하기 전에 과거의 데이터를 사용해보고 전체적인 검증을 하는 필수적인 알고리즘이다.
stratigies.py와 models.py에서 매수 전략과 예측 모델을 받아 백테스팅 되도록 구현하였으며 전체적인 파악을 위해 시각화까지 하였다.
백테스팅 함수를 돌렸을 때, 아래와 같이 로깅이 된다.
...
...
2022년 2월 1일 9시부터 3월 1일 8시까지 1시간 단위로 자동매매를 했을 때의 수익률을 보도록 백테스팅 함수를 돌렸다. 156번째 행과 같이 전략의 매수 조건을 만족하고 예측 값이 현재 값보다 높을 때, 코인을 매수하였고 168번째 행과 같이 다음 날 새로운 장이 열리는 시간인 9시에 모든 코인을 매도하였다.
위와 같이 매 시간별로 현재가, 예측가, 사고 파는 여부와 돈/코인이 모두 로깅되며 이를 시각화하면 아래와 같다.
회색 선은 시간별 현재가를 나타내며 주황색 점선은 코인을 매수했을 때의 시간, 직선은 모델의 예측 값을 나타낸다. 직사각형의 모서리에 위치한 초록색 점은 매수/매도하는 지점이며 파란색 직사각형은 매수가보다 매도가가 높아 이윤이 났음을 의미하고 빨간색 직사각형은 매수가보다 매도가가 낮아 손해가 났음을 의미한다.
모델 검증에서 언급한 것과 같이 아직 모델의 성능은 보장되지 않고 전략에 대한 파라미터도 튜닝되지 않았기 때문에 수익률이 음수가 되었다. (성능이 높아도 양수를 보장할 수 없다...)
Future Works
이후에는 모델 성능 향상을 위해 파라미터 튜닝 함수를 구현할 것이며 다른 전략이나 모델도 추가할 것이다. Prophet은 결국 y값을 이용하여 y값을 예측하는 것이므로 높은 성능을 기대하기 어렵다. 이후, 여러 변수를 추가하여 모델을 고도화한다면 더 나은 검증 결과가 나올 수 있을 것이다.
또한, 파라미터 튜닝과 파라미터별 성능 비교를 용이하게 하기 위해 wandb나 mlflow를 도입하는 것도 고민하고 있다.
구현 코드를 확인하고 싶다면 저의 Github에서 module 디렉토리에 존재하는 py 파일들과 test_notebook.ipynb를 참고해주세요.
'Projects > System Trading' 카테고리의 다른 글
[코인 자동 매매 개발기 1] 초기 시스템 설계 (1) | 2022.05.01 |
---|
댓글