이번 포스팅에선 비트파이넥스 API를 활용하여 비트코인 가격데이터를 요청해보겠다.

좀 더 자세한 설명은 코인베이스 API 사용 포스팅에 나와있으니 참고해도 좋다.


우선 비트파이넥스 API관련 링크에 접속한다

https://bitfinex.readme.io/v2/reference#rest-public-stats


왼쪽 candle을 눌러주면 아래와 같은 화면이 보인다.



우선 URL 방식중 GET과 POST방식에 대해서 간단히 설명하겠다.


GET(파란원)은 따로 암호화를 하지 않은 URL방식으로 URL을 보면 직관적으로 그 내용을 알 수 있다. 예시에 나와있는 링크를 봐도 어느정도 직관적으로 이해가 가능하다.


POST는 암호화를 거친 URL로 이상한 특수문자 알파벳 조합으로 이루어지기 떄문에 직관적으로 알 수 없다. 

우리는 GET방식의 URL을 통해 데이터를 요청해 보겠다.


친절하게 파라미터에 대한 예시까지 들어주었으므로, 바로 URL에 적용시켜 보겠다.

예시 URL(GET방식)은 아래와 같다.


https://api.bitfinex.com/v2/candles/trade:6h:tBTCUSD/hist?limit=100&start=&end=&sort=1


라인별로 간단하게 보면 6시간봉으로 이루어진 BTCUSD마켓 데이터를 hist 방식으로(사진 빨간원 참조) 정렬된 상태로 100개 요청하는 것이다.


이제 코드패드로 이동해 보겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
from datetime import datetime
import time
 
def unixtime(t): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))
'''
def unixtime_to_datetime(arr, interval, symbol): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))    
'''
timeframe = '6h'
symbol = 'tBTCUSD'
section = 'hist'
limit = 100
end = "2018-03-01"
start = "2018-02-25"
sort = 1 
 
= (requests.get("https://api.bitfinex.com/v2/candles/trade:%s:%s/%s?limit=%d&start=%d&end=%d&sort=%d" %(timeframe, symbol, section, limit, unixtime(start)*1000, unixtime(end)*1000, sort)))
 
data = r.json()
print(data)
    
cs


해당 코드를 실행하면 아래와 같다.



이런식으로 데이터를 받아올 수 있다.

이후 csv저장 등 필요한 작업을 진행하면 된다.

오늘부터 진행해볼 실습은 딥러닝을 통한 비트코인 가격 예측이다.

이를 위해서는 아래와 같은 프로세스를 통해 진행해 보겠다. 



따라서 오늘 진행할 것은 API를 통하여 비트코인의 과거 가격 데이터를 수집해보도록 하겠다 


우리가 API를 통해 받아올 거래소는 미국의 "Coinbase" 거리소이다. 

해당 거래소를 선택한 이유는 아래와 같다.


Coinbase (Gdax)

  • USDT가 아닌 USD를 사용 
  • 미국 내 거래량 1위 


Bitfinex와 Binance같은 거래소를 선택하지 않은 이유는 테더로 거래를 진행하기 때문이다. 

테더가 사실 우리가 진행할 예측에 크게 영향을 주진 않지만 때마침 테더 관련 이슈가 터진 상황이기 때문에 

향후에도 예측모델을 사용하기 위해 혹시모를 사태에 대비해 USD를 이용하는 Coinbase(Gdax)를 선택하였다. 


코인베이스의 API 설명 사이트는 이곳이며 클릭시 이동하게 된다.

해당 페이지에서 과거 데이터 수집을 위한 방법을 찾아보자.



대략적인 파라미터는 start(시작시간) 과 end(종료시간), 그리고 granulariy(몇시 봉으로 할건지)를 넣어줄 수 있다.

여기서 보여준 예시는 아래와 같다 


즉 종목과 TImeslice를 정해주면 지정해준 시간부터 지정해준 시간까지에 대한 데이터를 수집할 수 있다는 것이다.


Gdax는 UnixTIme을 쓰는데, 이는 우리가 쓰고있는 2018-02-16 이런 시간대신, 뭔가 다른 계산 프로세스를 통해서 시간을 표시하는 것이다.

해당 프로세스의 장점은 현실에서 2월은 30일까지 있고 3월은 31일까지 있고 이런 귀찮은 프로세스를 처리하지 않아도 자연스럽게 타임라인을

표시할 수 있다는 것이지만, 직관성이 매우 떨어진다는 단점을 가진다. 


자세한 시간계산 프로세스는 모르겠고, 우선 우리가 쓰는 시간을 Unixtime으로 바꿔줄 수 있는 코드는 아래와 같다. 


1
2
3
4
5
6
from datetime import datetime
 
def unixtime(t): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))
 
cs

활용 예시는 아래에서 다시 확인하겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import gdax
from datetime import datetime
import csv
import time
 
#########데이터 수집################
public_client = gdax.PublicClient()
= open("./get_bitcoin_data.csv"'a', newline='')
wr = csv.writer(o)
 
granularity = 3600*6#3600*6 #6시간봉
interval = 3600*24*50
start_time = '2015-02-28'
last_time = '2018-01-17'
 
result = []
#for i in range(unixtime('2015-02-28'), unixtime('2018-01-17'), interval): #i는 15-02-28 ~ 18-01-17 이지만 (i, i+777600)(2015-02-28~2018-01-25까지) 뽑으니깐 오늘인 18-01-18까지 다 뽑아짐.
for i in range(unixtime(start_time), unixtime(last_time), interval): #i는 15-02-28 ~ 18-01-17 이지만 (i, i+777600)(2015-02-28~2018-01-25까지) 뽑으니깐 오늘인 18-01-18까지 다 뽑아짐.
    start = str(datetime.fromtimestamp(i)).split(' ')[0]
    if i + interval > unixtime(last_time): 
        end = str(datetime.fromtimestamp(unixtime(last_time) + 3600*24)).split(' ')[0# 이렇게 하면 새벽3시까지만 나오므로 18시간 뒤까지 뽑게 24시간의 초를 더해줌
    else:
        end = str(datetime.fromtimestamp(i+interval)).split(' ')[0]
    
    r = public_client.get_product_historic_rates('BTC-USD', start=start, end=end, granularity=granularity)
    for k in r:
        result.append([str(datetime.fromtimestamp(k[0])), k[1], k[2], k[3], k[4], k[5]])
 
    last_r_size = len(r) #마지막 넣을때 사이즈 - 예를들어 마지막에 12만 저장되면 
    print(last_r_size)
 
 
popped = result.pop(-1*last_r_size) #그냥 17일까지로 뽑으면 17일 새벽3시까지만 뽑힘. 그래서 하루 더 뽑은다음 제일 마지막 시간만 빼게 되면 17일 저녁 9시까지 뽑을수 있음 
print('del',popped)
for i in result:
    wr.writerow(i)
 
o.close()
##########################
cs

위 코드는 Gdax API를 활용하여 비트코인 과거 데이터를 뽑아온 것이다.

자세한 과정을 라인별로 설명하면 다음과 같다. 


우선 Gdax API를 사용하기 위하여 gdax를 import 해주고, 이를 csv 파일로 저장해주기 위한 코드 역시 삽입한다.


Granularity 는 3600 (한시간은 3600초) * 6을 하여 여섯시간 봉을 뽑아오게 된다.

Interval에 준 3600*24*50의 뜻은 한번에 뽑을때 50일치를 가지고 오는데 거기서 *4를 하니깐 200일치를 가지고 온다는 것이다.

즉 하루 4개(24시간 = 6시간 *4) * 50일치는 200개 봉.


그 아래 포문은 계속 뽑아오는 과정이고, 이 과정에서 한가지 짚고 넘어가야 할 것이 있다.

유닉스 타임을 사용해서인지 어떤건지 우리가 지정한 last_time이 전부 받아오는 것이 아닌, 해당 일의 새벽 3시까지 봉만 받아오는 문제점이 발생하였다.


따라서 last_time에서 하루를 더 받아온다음, 제일 마지막에 받아온 봉을 날리는 방법으로 우리가 원하는 last_time까지 데이터를 수집하기로 하였다.

해당 코드는 주석이 달린 부분에서 확인할 수 있다.


따라서 마지막까지 데이터를 다 받아온 후, 이에 대한 사이즈를 구해야 삭제하는 코드를 진행하였다. (result.pop~) 


해당 코드를 돌려보면 아래와 같이 뜬다. 



위에서 설명한 것처럼 200개씩 받아온 후, 마지막 행을 del을 프린트하며 삭제하도록 한다. 


받아온 csv파일을 열어보니 데이터 순서도 뒤죽박죽이고 무엇보다 중복된 데이터들이 있었다.

정확한 이유는 모르겠다. 아마 gdax api가 구려서 그런것 같은데.. 


여튼 이를 해결하기 위해 파이썬 딕셔너리를 사용하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
############ 중복제거##################   
= open("./get_bitcoin_data.csv"'r', newline='')
rdr = csv.reader(f)
dic = {}
for i in rdr: # 한줄씩 보겠다 
    key = str(i[0]) #0번인덱스 = 날짜 / 이걸 키로 설정함 
    value = str(i[1]) + ' ::: ' + str(i[2]) + ' ::: ' + str(i[3]) + ' ::: ' + str(i[4]) + ' ::: ' + str(i[5])
    #temp = str(i[0]) +' ::: ' + str(i[1]) + ' ::: ' + str(i[2]) + ' ::: ' + str(i[3]) + ' ::: ' + str(i[4]) + ' ::: ' + str(i[5])
    dic[key] = value
 
f.close()
 
= open("./duplication_eliminated_bitcoin_data.csv"'w', newline=''# 저장 
wr = csv.writer(o)
wr.writerow(['time','low','high','open','close','volume']) # 필터 자리 놔둠
 
for i in dic: # i 는 키 
    temp = dic[i].split(' ::: '# 딕셔너리는 랜덤하게 긁어옴 - 그래서 엑셀에서 정렬해줘야 
    temp.insert(0, i) #맨앞에 날짜 추가
    wr.writerow(temp)
    #wr.writerow(i.split(' ::: '))
 
 
o.close()
###########################
cs


파이선 자료형중 하나인 딕셔너리에 대해 간단하게 설명하면, 인덱스별로 짝을 맞게 삽입하여 인덱스를 입력하면 짝이 튀어나오도록 하는 것이다.

이 과정에서 중복되는 인덱스가 있으면(키) 둘 중 하나가 랜덤으로 삭제되게 된다.


csv파일을 보았는데 우리가 가진 데이터의 중복 튜플들은 소수점을 올림했냐 버림했냐 반올림했냐 등의 사소한 문제였기 때문에 뭐가 삭제되어도 

딱히 상관이 없으므로 그냥 딕셔너리에 삽입후 꺼내도록 한다. 


key는 0번 인덱스로 설정 - CSV파일을 TIme 칼럼을 뜻한다. 

그 뒤 해당 행의 가격 값들 (high, low, close, volum 등등등) 을 짝을 맞추어 딕셔너리에 삽입한다.(for i in rdr문) 

":::" 를 경계로 각 값을 붙였기 때문에 해당 값을 기준으로 다시 나눠주게 되고, 해당 행의 0번자리(제일 앞자리)에 i(날짜)를 추가하게 된다. (for i in dic문) 


이렇게 저장된 csv파일을 확인해보면 


이렇게 중복 데이터가 삭제된 것을 확인할 수 있다. 

물론 정렬은 안 된 상태여서 그냥 액셀에서 필터를 활용하여 오름차순 정렬을 하였다. 


이렇게 해서 API를 활용한 비트코인 가격 데이터 수집을 마치고, 

이제 모델 학습에 활용할 변수 획득을 위한 보조지표(기술분석을 위한 보조지표)를 추가하여 보겠다. 


+ Recent posts