업비트 코인 자동매매-1
이 글은 파이썬을 이용해 업비트와 연동해서 차트에 맞춰 자동거래를 하는 툴을 제작했던 제작기이다.
개발을 하는 과정을 보여드리는 것에 초점을 맞출 예정이라 참조했던 블로그나 생각의 흐름을 그대로 볼 수 있다.
1. 어떻게 해야 거래를 할 수 있는가
가장 먼저 시작한 부분은 우선 Open API를 사용하도록 인증하는 것이다.
간단하게 설명하면 특정 IP에서 발급된 키가 있을 경우 본인의 코인 지갑(현금 포함)에 접근할 수 있도록 해주는 기능이다.
이게 없더라도 시세 조회는 다 가능하기 때문에 시세만 조회하는 자신만의 HTS를 만드는 거라면 굳이 발급받을 필요는 없지만 우리의 목적은 보통 이런 것이 아니니까
신청을 하는 부분은 간단하니 직접 해보면서 익혀보도록 하자.
Access Key와 Open API Key는 매우 중요하니 별도의 장소에 보관해두도록 하자
이 키만 있으면 허용된 IP일 경우 내 지갑에 접근이 가능하다.
2. 데이터를 받아오자
사용한 IDE는 Anaconda에서 지원하는 PyCharm을 이용하자
그리고 Jupyter Notebook도 주기적으로 사용해줘야 하기 때문에 개발 환경을 만들어 두기 위해 꼭 Anaconda를 설치하도록 하자.
그럼 기본 준비하는 부분은 건너뛰고 바로 코드로 들어가겠다.
아 그전에 반드시 확인해둬야 할 페이지가 있다.
pyupbit라고 하는 Upbit에서 자체 지원하는 API이다.
해당 API를 이용하면 Python으로 매우 편하게 매매 프로그램을 짤 수 있다.
pip도 지원하니 pip install pyupbit를 이용해서 모듈을 설치해두도록 하자
모듈 설치가 끝나고 나면 필요한 것들을 import 해두자
import pyupbit
from datetime import datetime
from threading import Timer
import numpy as np
import pandas as pd
import time
pyupbit는 Upbit에 접속하기 위한 기본이고,
아래로는 타이머와 데이터 프레임을 만들기 위한 Pandas를 가져오도록 하자
1차적인 준비는 다 끝났으니 시세를 불러오기 위한 함수를 바로 작성하자.
def call_coin_data(self, coinname):
try:
df = pyupbit.get_ohlcv(coinname, interval="minute30")
except:
print("오류발생")
데이터 테이블을 불러오는 방법 자체는 워낙 간단해서 위에서 공유했던 링크에 있는 데이터를 바로 확인하자.
여기서 coinname은 변수로 함수를 호출할 때 불러온다.
이것만으로도 시세를 불러오는 것은 완료다.
매우 간단하다.
3. 시세만 불러오면 되나?
시세를 불러왔으면 이제 기본적인 차트 분석 데이터를 붙여 넣어 줘야 한다.
개인적으로 주로 사용하는 차트 분석 기법은 RSI와 BB %B, 이동평균선이 있으니 이것들을 모두 만들어서 하나의 DataFrame으로 만들어 주자.
#이동평균선
ma20 = df['close'].rolling(window=20).mean()
ma100 = df['close'].rolling(window=100).mean()
ma20 = ma20.iloc[-1]
ma100 = ma100.iloc[-1]
#볼린저 밴드 %B
df['MA20'] = df['close'].rolling(window=20).mean()
df['stddev'] = df['close'].rolling(window=20).std()
df['upper'] = df['MA20'] + (df['stddev'] * 2) # 볼린저 밴드 상단선
df['lower'] = df['MA20'] - (df['stddev'] * 2) # 볼린저 밴드 하단선
df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower'])
#RSI
RSI_n = 14
df['updown'] = df['close'].diff()
df['RSI_U'] = df['updown'].apply(lambda x: x if x > 0 else 0)
df['RSI_D'] = df['updown'].apply(lambda x: x * (-1) if x < 0 else 0)
df['RSI_AU'] = df['RSI_U'].ewm(com=RSI_n - 1, min_periods=RSI_n).mean()
df['RSI_AD'] = df['RSI_D'].ewm(com=RSI_n - 1, min_periods=RSI_n).mean()
df['RS'] = df['RSI_AU'] / df['RSI_AD']
df['RSI'] = 100 - (100 / (1 + df['RS']))
이동평균선은 워낙 간단한 지표니 굳이 별다른 설명은 필요 없을 것이다.
볼린저 밴드 %B의 경우 변동성을 추적하기 위해서 만들어 두었고
계산식은 20일 이동평균선의 상단선과 하단선을 만들어 그 차이를 계산하는 방식이다.
RSI는 채결 강도를 추적하는데
여기서 중요한 것은 일반 평균이 아니라 ewm(지수 이동평균)을 사용해야 한다는 것이다.
지수 이동평균은 근시일일수록 높은 가중치를 주도록 계산하는 이동평균 계산 기법으로 아래 사이트에 원리가 설명되어 있다.
어쨌든 원리는 건너뛰고 우리는 지수 평활을 써야만 정확한 RSI값을 찾아낼 수 있음을 기억하자.
이렇게 완성된 데이터를 Jupyter Notebook에서 실행할 경우 아래와 같은 DataFrame이 만들어졌음을 확인할 수 있다.
다음 포스팅에는 이 데이터를 기반으로 매수 타이밍, 매도 타이밍을 잡는 법과 자동으로 매수 매도가 되게 처리하는 방법까지 만들었던 것에 대한 개발일지를 쓰도록 하겠다.
참고로 Pandas를 다루는 것이 익숙하지 않다면 아래 링크를 참조해보자