ビットコインAPIを使って板情報の取得と新規注文を行う
今回は、bitFlyerのAPIを使用して自分の口座の資産残高と
現在の板情報を取得、新規注文を出す処理を実装してみます。
APIを呼び出すプログラムと、それを呼び出して使うプログラムとに
分けて実装しました。
APIを呼び出すプログラム
まずは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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# -*- coding: utf-8 -*- """ Created on Thu Mar 9 12:00:27 2017 @author: ichizo """ import json import requests import time import hmac import hashlib class ApiCall: def __init__(self,api_key,api_secret,api_endpoint): self.api_key = api_key self.api_secret = api_secret self.api_endpoint = api_endpoint def get_api_call(self,path): method = 'GET' timestamp = str(time.time()) text = timestamp + method + path sign = hmac.new(bytes(self.api_secret.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest() request_data=requests.get( self.api_endpoint+path ,headers = { 'ACCESS-KEY': self.api_key, 'ACCESS-TIMESTAMP': timestamp, 'ACCESS-SIGN': sign, 'Content-Type': 'application/json' }) return request_data def post_api_call(self,path,body): body = json.dumps(body) method = 'POST' timestamp = str(time.time()) text = timestamp + method + path + body sign = hmac.new(bytes(self.api_secret.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest() request_data=requests.post( self.api_endpoint+path ,data= body ,headers = { 'ACCESS-KEY': self.api_key, 'ACCESS-TIMESTAMP': timestamp, 'ACCESS-SIGN': sign, 'Content-Type': 'application/json' }) return request_data |
ほぼ参考サイトのままです。
ただ、以下のエラーが発生しました。
1 2 3 |
raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) TypeError: key: expected bytes or bytearray, but got 'str' |
これはどうもPython2では発生しないけれども、
Python3になると発生するもののようです。
参考サイト
hmacのキーはbytesかbytearrayにしろということで、
「self.api_secret」の部分を「bytes(self.api_secret.encode('ascii'))」
に書き換えます。
キー部分のみを書き換えただけでは、以下のエラーを吐かれます。
1 |
TypeError: Unicode-objects must be encoded before hashing |
メッセージ部分もエンコードするために「text」を
「bytes(text.encode('ascii'))」に書き換えます。
該当の行を以下のようにすることでエラーは解消しました。
1 |
sign = hmac.new(bytes(self.api_secret.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest() |
自分の口座の資産残高を取得する
「資産残高を取得」APIを呼び出すプログラムを実装します。
リクエストは「GET /v1/me/getbalance」です。
プログラムソースは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# -*- coding: utf-8 -*- """ Created on Thu Mar 9 12:14:31 2017 @author: ichizo """ import ApiCall api_key = 'APIキー' api_secret = 'APIシークレット' api_endpoint = 'https://api.bitflyer.jp' path = '/v1/me/getbalance' if __name__ == '__main__': api = ApiCall.ApiCall(api_key,api_secret,api_endpoint) result = api.get_api_call(path).json() print(result) |
レスポンスは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[ { 'currency_code': 'JPY', 'available': 0.0, 'amount': 0.0 }, { 'currency_code': 'BTC', 'available': 0.0, 'amount': 0.0 }, { 'currency_code': 'ETH', 'available': 0.0, 'amount': 0.0 } ] |
板情報を取得する
次は板情報を取得します。
リクエストは「GET /v1/board」で、
クエリパラメータにproduct_code: "BTC_JPY", "FX_BTC_JPY"
または "ETH_BTC" を指定します。
プログラムは、pathの指定を以下に書き換えるだけです。
1 |
path = '/v1/board?product_code=BTC_JPY' |
レスポンスは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "mid_price": 33320, "bids": [ { "price": 30000, "size": 0.1 }, { "price": 25570, "size": 3 } ], "asks": [ { "price": 36640, "size": 5 }, { "price": 36700, "size": 1.2 } ] } |
新規注文を行う
引き続いては新規注文を行います。
リクエストは「POST /v1/me/sendchildorder」で、
クエリパラメータに注文情報を渡します。
プログラムは以下のようになりました。
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 |
# -*- coding: utf-8 -*- """ Created on Thu Mar 9 12:14:31 2017 @author: ichizo """ import ApiCall api_key = 'APIキー' api_secret = 'APIシークレット' api_endpoint = 'https://api.bitflyer.jp' path = '/v1/board?product_code=BTC_JPY' order_path = '/v1/me/sendchildorder' body = { "product_code": "BTC_JPY", "child_order_type": "LIMIT", "side": "SELL", "price": 300000, "size": 0.001, "minute_to_expire": 10000, "time_in_force": "GTC" } if __name__ == '__main__': api = ApiCall.ApiCall(api_key,api_secret,api_endpoint) result = api.get_api_call(path).json() print(result) result = api.post_api_call(order_path,body).json() print(result) |
post_api_callを呼び出している部分が
注文処理を実行している箇所になります。