[bithumb API 3]빗썸 코인 마켓코드별 가격 입수
시세캔들 조회
빗썸은 API를 통해서 시세 캔들을 조회할 수 있는 서비스를 제공하고 있다. 빗썸 API Docs 홈페이지에서 아래와 같이 시세 캔들 조회 항목을 클릭하면, API 요청 방법과 예시 코드를 확인할 수 있다.([bithumb API 1] 엑셀로 마켓 코드 조회 참조)
엑셀로 마켓코드 조회하는 방식과 마찬가지로 특정 URL에 데이터를 요청하면, 요청 결과를 JSON 형식으로 받는 형식이다. 위 그림 1에서 확인할 수 있는 것처럼 API 요청 시 우리가 투입할 수 있는 변수는 market, to, count이다. market은 어떤 코인 시세를 조회할 것인지, to는 몇일까지의 데이터를 받을 것인지, count는 몇 개의 데이터를 받을 것인지(최대 200개)를 나타낸다. 주어진 정보를 바탕으로 응답결과를 "price"라는 시트에 받아오는 코드를 만들 수 있다.
Sub 시세캔들조회()
Dim http요청 As Object
Dim url As String
Dim 응답결과 As String
'Main Sheet 설정
Set 가격시트 = ThisWorkbook.Worksheets("price")
마켓코드 = "KRW-BTC"
캔들구분 = "일"
요청개수 = 10
If 캔들구분 = "분" Then
urladd = "minutes/1?"
ElseIf 캔들구분 = "일" Then
urladd = "days?"
ElseIf 캔들구분 = "주" Then
urladd = "weeks?"
ElseIf 캔들구분 = "월" Then
urladd = "months?"
Else
Exit Sub
End If
params = "market=" & 마켓코드 & "&count=" & 요청개수
apiurl = "https://api.bithumb.com/v1/candles/" & urladd & params
' HTTP요청 객체 생성
Set http요청 = CreateObject("MSXML2.XMLHTTP.6.0")
' GET 요청 보내기
With http요청
.Open "GET", apiurl, False
.setRequestHeader "accept", "application/json"
.send
응답결과 = .responseText
End With
가격시트.Cells.ClearContents
가격시트.Cells(1, 1) = 응답결과
End Sub
JSON데이터 편집
응답결과는 [bithumb API 2]JSON 데이터 편집에서 만들어 본 딕셔너리변환 함수를 쓰면 된다. 하지만 마켓코드 조회 시에 사용했던 딕셔너리변환 함수를 그대로 쓰기엔 문제가 있다. 위 그림 2에서 확인할 수 있는 것처럼 "market" 데이터는 콜론(":") 뒤에 나오는 데이터가 큰따옴표(")에 씌워진 반면, "opening_price"의 콜론(":") 뒤에 나오는 데이터는 큰따옴표가(") 씌워져 있지 않고 숫자 그대로 표현된 것을 알 수 있다.
그 결과 "키값:데이터"로 구성된 JSON형식 문서에서 데이터의 성격이 무엇이냐에 따라서 아이템을 추출하는 방법이 달라진다. 데이터가 문자열이면, 쌍따옴표(")를 감안해줘야 하고, 그 외의 경우 큰따옴표(")를 감안해 줄 필요가 없기 때문이다. 따라서 [bithumb API 2]JSON 데이터 편집에서 구현한 아이템 추출 함수는 항목, 키값, 키타입(=문자인지, 숫자인지) 세 가지 변수를 받게 되고, 키 타입에 따라서 아래와 같이 다르게 작업하는 함수로 바꾸어 준다.
' 문자열 항목에서 특정 키값에 해당하는 값을 추출
' 키타입은 "문자" 또는 "숫자" 중 하나
Public Function 아이템추출(항목 As String, 키값 As Variant, 키타입 As Variant)
' 키의 시작 위치 찾기
시작점 = InStr(항목, 키값)
' 키 이름의 길이
키값크기 = Len(키값)
' 전체 항목의 길이
항목끝점 = Len(항목)
' 값 시작 위치 계산
' 문자형이면 ": " 다음에 " 로 감싸져 있으므로 +3, 숫자면 +2
If 키타입 = "문자" Then
아이템시작점 = 시작점 + 키값크기 + 3
Else
아이템시작점 = 시작점 + 키값크기 + 2
End If
' 다음 콤마 위치 찾기 (다음 항목의 시작 지점)
아이템콤마위치 = InStr(아이템시작점, 항목, ",")
' 콤마가 없으면 문자열 끝까지가 값임
If 아이템콤마위치 = 0 Then
아이템끝점 = 항목끝점
Else
아이템끝점 = 아이템콤마위치
End If
' 값의 길이 계산
If 키타입 = "문자" Then
아이템길이 = 아이템끝점 - 아이템시작점 - 1 ' 문자열은 맨 뒤 " 제외
Else
아이템길이 = 아이템끝점 - 아이템시작점
End If
' 최종 값 추출
아이템추출 = Mid(항목, 아이템시작점, 아이템길이)
End Function
시세캔들 조회 구현
아이템추출 함수를 사용하는 딕셔너리 변환 함수도 아래와 같이 키값에 대한 속성값 Array를 추가적으로 변수로 받도록 변형한다.
Public Function 딕셔너리변환(응답결과 As String, 키값 As Variant, 키타입 As Variant)
Dim 딕셔너리 As Dictionary
Dim 항목 As String
Dim Items() As String
Dim 최대번호 As Long
If UBound(키값) - LBound(키값) <> UBound(키타입) - LBound(키타입) Then
MsgBox "키값과 키타입의 배열 크기가 일치하지 않습니다.", vbCritical
Exit Function
End If
' Scripting.Dictionary 생성
Set 딕셔너리 = CreateObject("Scripting.Dictionary")
응답대괄호제거 = Mid(응답결과, 2, Len(응답결과) - 2)
응답배열분리 = Split(응답대괄호제거, "},{")
최대번호 = UBound(키값)
' 각 객체를 2차원 배열로 변환
For i = LBound(응답배열분리) To UBound(응답배열분리)
' 객체의 대괄호 제거
항목 = Replace(응답배열분리(i), "{", "")
항목 = Replace(항목, "}", "")
ReDim Items(최대번호)
' Key-Value 추출
For j = 0 To 최대번호
' 키타입 Array 중 해당 항목값이 아이템추출 함수에 변수로 추가
Items(j) = 아이템추출(항목, 키값(j), 키타입(j))
Next
딕셔너리.Add i, Items
Next
Set 딕셔너리변환 = 딕셔너리
End Function
기본적으로 구현한 시세캔들 조회라는 함수에 위의 딕셔너리변환 함수를 조합하면 아래와 같이 기본적인 시세캔들 조회 함수를 구현할 수 있다. 단, 복잡성을 줄이기 위해서 API 요청 시 시간은 변수로 요청하지 않았다.
Sub 시세캔들조회(마켓코드 As String, 캔들구분 As String, 요청개수 As Long)
' HTTP 요청 관련 변수 선언
Dim http요청 As Object
Dim url As String
Dim 응답결과 As String
Dim 응답딕셔너리변환 As Dictionary
' JSON 파싱을 위한 키 목록 (필드명)과 각 키의 데이터 타입 정의
Dim 키값 As Variant
Dim 키타입 As Variant
Set 응답딕셔너리변환 = CreateObject("Scripting.Dictionary")
키값 = Array("market", "candle_date_time_utc", "candle_date_time_kst", _
"opening_price", "high_price", "low_price", _
"trade_price", "timestamp", "candle_acc_trade_price", _
"candle_acc_trade_volume", "unit")
키타입 = Array("문자", "문자", "문자", "숫자", "숫자", "숫자", _
"숫자", "숫자", "숫자", "숫자", "숫자")
' 데이터를 출력할 시트 설정
Set 가격시트 = ThisWorkbook.Worksheets("price")
' 캔들 구분에 따라 URL 세부 경로 결정
If 캔들구분 = "분" Then
urladd = "minutes/1?"
ElseIf 캔들구분 = "일" Then
urladd = "days?"
ElseIf 캔들구분 = "주" Then
urladd = "weeks?"
ElseIf 캔들구분 = "월" Then
urladd = "months?"
Else
Exit Sub ' 잘못된 캔들구분인 경우 종료
End If
' API 호출용 URL 구성
params = "market=" & 마켓코드 & "&count=" & 요청개수
apiurl = "https://api.bithumb.com/v1/candles/" & urladd & params
' HTTP 요청 객체 생성
Set http요청 = CreateObject("MSXML2.XMLHTTP.6.0")
' GET 요청 수행
With http요청
.Open "GET", apiurl, False
.setRequestHeader "accept", "application/json"
.send
응답결과 = .responseText
End With
' 결과 출력 전 기존 시트 내용 삭제
가격시트.Cells.ClearContents
' JSON 응답을 Dictionary로 파싱 (jsonparse 모듈 사용)
Set 응답딕셔너리 = jsonparse.딕셔너리변환(응답결과, 키값, 키타입)
' 결과 시트에 헤더 출력
작업ROW = 1
컬럼작업 = 1
For Each i In 키값
가격시트.Cells(작업ROW, 컬럼작업) = i
컬럼작업 = 컬럼작업 + 1
Next
' 데이터 출력
작업ROW = 작업ROW + 1
For Each i In 응답딕셔너리.Keys()
For j = 0 To UBound(키값)
가격시트.Cells(작업ROW, j + 1) = 응답딕셔너리(i)(j)
Next
작업ROW = 작업ROW + 1
Next
' 메모리 해제
Set http요청 = Nothing
End Sub
아래 그림 3의 왼쪽과 같이 KRW-BTC를 "분" 캔들로 100 개 데이터 요청시 그림 3의 오른쪽과 같인 데이터를 얻을 수 있다. 추가적으로 지금까지의 코드가 구현된 파일을 올려놨으니 참고하면 된다.