Pythonを用いたビットフライヤーの仮想通貨APIの使い方

ビットフライヤーのAPIを使って、仮想通貨botを作りましょう。

この記事では、Pythonを使ってビットフライヤーのAPIを呼び、実際に動作するコードを紹介します。

前準備

bitFlyerに口座を開設する

この記事を読み終わるころには、実際にAPIでビットコインを購入できるようにビットプライヤーで口座を開設しておきましょう。

Private API を使うときには、口座開設をしてAPIキーを取得する必要があります。

かそつーくん
かそつーくん

ビットフライヤーには「友達招待プログラム」があります。
招待URLからアクセスして、招待コードを入力して口座開設すると、1,500円分のビットコイン を受け取ることができます。読者様と私の両者にプレゼントされます。ぜひ受け取ってください。

招待URL: https://bitflyer.com/invitation?id=50xhjxbl&lang=ja-JP
招待コード:50xhjxbl
達成条件:招待された友達が bitFlyer の本人確認のお手続きを完了し、口座を開設

bitFlyerのAPI仕様書

ビットフライヤーのAPI仕様書はこちらになります。
サンプルコードでは入力パラメータの説明は省いていますので、必須パラメータなどはAPI仕様書でご確認ください。

requestsモジュールのAPI仕様書

botでつまづくところは、APIを呼んでも思った通りに動かないことです。
requestsの使い方が良くない場合があるので、そのときはrequestsの仕様書を見ましょう。

HTTP レスポンスのステータスコードは、こちらで確認しましょう。

Pythonモジュールのインストール

サンプルコードで必要なモジュールは以下です。未インストールの場合は pip install してください。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import requests
import json
import time
from datetime import datetime
import hmac
import hashlib
import requests import json import time from datetime import datetime import hmac import hashlib
import requests
import json
import time
from datetime import datetime
import hmac
import hashlib

Public API を使う

APIの練習をしたい方は、Public APIを使用してお試しされるのもアリです。PCさえあれば、口座開設なしで今すぐAPIを使えます。

短時間にAPIを何度も呼ぶと負荷がかかるのでAPI制限があります。お気をつけください。

取引所の状態の取得 gethealth

bot運用を開始すると、取引所がメンテナンス状態のときは取引しないようなコードを書きます。そんなときに取引所の状態取得APIを使用します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
endPoint = "https://api.bitflyer.com"
path = "/v1/gethealth"
url = endPoint + path
response = requests.get(url)
res = response.json()
print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com" path = "/v1/gethealth" url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com"
path     = "/v1/gethealth"
url = endPoint + path

response = requests.get(url)
res = response.json()
print(json.dumps(res, indent=4))

取引所のステータスが返ってきます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"status": "NORMAL"
}
{ "status": "NORMAL" }
{
    "status": "NORMAL"
}

取り扱い通貨の取得 getmarkets

ビットフライヤーは、販売所と取引所で扱っている通貨の種類が異なります。このAPIを使えば、取引できる通貨を確認できます。ですが、取り扱い通貨取得APIはあまり使いどころがないかもしれませんね。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
endPoint = "https://api.bitflyer.com"
path = "/v1/getmarkets"
url = endPoint + path
response = requests.get(url)
res = response.json()
print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com" path = "/v1/getmarkets" url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com"
path     = "/v1/getmarkets"
url = endPoint + path

response = requests.get(url)
res = response.json()
print(json.dumps(res, indent=4))

ビットフライヤー取引所では、”Spot”が現物で8種類、”FX”がCFDで1種類が取り扱われています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[
{
"product_code": "BTC_JPY",
"market_type": "Spot"
},
{
"product_code": "XRP_JPY",
"market_type": "Spot"
},
{
"product_code": "ETH_JPY",
"market_type": "Spot"
},
{
"product_code": "XLM_JPY",
"market_type": "Spot"
},
{
"product_code": "MONA_JPY",
"market_type": "Spot"
},
{
"product_code": "ELF_JPY",
"market_type": "Spot"
},
{
"product_code": "ETH_BTC",
"market_type": "Spot"
},
{
"product_code": "BCH_BTC",
"market_type": "Spot"
},
{
"product_code": "FX_BTC_JPY",
"market_type": "FX"
}
]
[ { "product_code": "BTC_JPY", "market_type": "Spot" }, { "product_code": "XRP_JPY", "market_type": "Spot" }, { "product_code": "ETH_JPY", "market_type": "Spot" }, { "product_code": "XLM_JPY", "market_type": "Spot" }, { "product_code": "MONA_JPY", "market_type": "Spot" }, { "product_code": "ELF_JPY", "market_type": "Spot" }, { "product_code": "ETH_BTC", "market_type": "Spot" }, { "product_code": "BCH_BTC", "market_type": "Spot" }, { "product_code": "FX_BTC_JPY", "market_type": "FX" } ]
[
    {
        "product_code": "BTC_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "XRP_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "ETH_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "XLM_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "MONA_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "ELF_JPY",
        "market_type": "Spot"
    },
    {
        "product_code": "ETH_BTC",
        "market_type": "Spot"
    },
    {
        "product_code": "BCH_BTC",
        "market_type": "Spot"
    },
    {
        "product_code": "FX_BTC_JPY",
        "market_type": "FX"
    }
]

Ticker情報の取得 getticker

Ticker、つまりシンボルですね。もしくは通貨ペアと言ってもいいと思います。

主に、LTP(Last Traded Price: 最終取引価格)を取得したいときにTicker情報取得APIを使います。下の例ではBTC_JPYの情報を取得しています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
endPoint = "https://api.bitflyer.com"
path = "/v1/getticker"
url = endPoint + path
parameters = {
"product_code": "BTC_JPY",
}
response = requests.get(url, params=parameters)
res = response.json()
print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com" path = "/v1/getticker" url = endPoint + path parameters = { "product_code": "BTC_JPY", } response = requests.get(url, params=parameters) res = response.json() print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com"
path     = "/v1/getticker"
url = endPoint + path

parameters = {
    "product_code": "BTC_JPY",
}

response = requests.get(url, params=parameters)
res = response.json()
print(json.dumps(res, indent=4))

レスポンスは長くなるので省略していますが、LTPやbid/askの情報が返ってきます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"product_code": "BTC_JPY",
"state": "RUNNING",
"best_bid": 8518626.0,
"best_ask": 8521664.0,
"best_bid_size": 0.003,
"best_ask_size": 0.02,
"ltp": 8521666.0,
"volume": 2054.49467602,
}
{ "product_code": "BTC_JPY", "state": "RUNNING", "best_bid": 8518626.0, "best_ask": 8521664.0, "best_bid_size": 0.003, "best_ask_size": 0.02, "ltp": 8521666.0, "volume": 2054.49467602, }
{
    "product_code": "BTC_JPY",
    "state": "RUNNING",
    "best_bid": 8518626.0,
    "best_ask": 8521664.0,
    "best_bid_size": 0.003,
    "best_ask_size": 0.02,
    "ltp": 8521666.0,
    "volume": 2054.49467602,
}

板情報の取得 getboard

LTPではなく、最新のbid/ask価格で売買価格を決めたい場合は、板情報取得APIを使ってもいいと思います。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
endPoint = "https://api.bitflyer.com"
path = "/v1/getboard"
url = endPoint + path
parameters = {
"product_code": "BTC_JPY",
}
response = requests.get(url, params=parameters)
res = response.json()
print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com" path = "/v1/getboard" url = endPoint + path parameters = { "product_code": "BTC_JPY", } response = requests.get(url, params=parameters) res = response.json() print(json.dumps(res, indent=4))
endPoint = "https://api.bitflyer.com"
path     = "/v1/getboard"
url = endPoint + path

parameters = {
    "product_code": "BTC_JPY",
}

response = requests.get(url, params=parameters)
res = response.json()
print(json.dumps(res, indent=4))

大量のbidとaskの情報が返るので、レスポンスの一部だけ載せます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"mid_price": 8517738.0,
"bids": [
{
"price": 8515627.0,
"size": 0.02
},
{
"price": 8515612.0,
"size": 0.01
}
],
"asks": [
{
"price": 8519849.0,
"size": 0.20557575
},
{
"price": 8519850.0,
"size": 0.011
}
]
}
{ "mid_price": 8517738.0, "bids": [ { "price": 8515627.0, "size": 0.02 }, { "price": 8515612.0, "size": 0.01 } ], "asks": [ { "price": 8519849.0, "size": 0.20557575 }, { "price": 8519850.0, "size": 0.011 } ] }
{
    "mid_price": 8517738.0,
    "bids": [
        {
            "price": 8515627.0,
            "size": 0.02
        },
        {
            "price": 8515612.0,
            "size": 0.01
        }
    ],
    "asks": [
        {
            "price": 8519849.0,
            "size": 0.20557575
        },
        {
            "price": 8519850.0,
            "size": 0.011
        }
    ]
}

Private API を使う

Private API にはAPIキーが必要なので、口座開設が必要になります。

APIキーを使ってもAPIコールでエラーが返る状態に陥っている方は、ビットフライヤーのサイトでAPIのパーミッション設定を見てみるといいかもしれません。

APIのパーミッションは、bitFlyer lightning => 左MenuのAPI => APIキーのActionsの編集 で変更できます。

下のサンプルコード内に apiKeysecretKey という変数が出てきますが、ご自身のものに置き換えてください。
・apiKey : ご自身の API Key
・secretKey: ご自身の API Secret

資産残高の取得 getbalance

資産残高取得APIは、自分の口座の各通貨や日本円の残高がわかります。

botで日本円の残高が少ないときはビットコインのみ取引し、アルトコインは売買しないということも実現できます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
method = "GET"
endPoint = "https://api.bitflyer.com"
path = "/v1/me/getbalance"
url = endPoint + path
timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()
headers = {
"ACCESS-KEY": apiKey,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))
method = "GET" endPoint = "https://api.bitflyer.com" path = "/v1/me/getbalance" url = endPoint + path timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple()))) text = timestamp + method + path sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest() headers = { "ACCESS-KEY": apiKey, "ACCESS-TIMESTAMP": timestamp, "ACCESS-SIGN": sign, "Content-Type": "application/json", } response = requests.get(url, headers=headers) res = response.json() print(json.dumps(res, indent=4))
method   = "GET"
endPoint = "https://api.bitflyer.com"
path     = "/v1/me/getbalance"
url = endPoint + path

timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()

headers = {
    "ACCESS-KEY": apiKey,
    "ACCESS-TIMESTAMP": timestamp,
    "ACCESS-SIGN": sign,
    "Content-Type": "application/json",
    }

response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))

ハイライトしている行の secretKey と apiKey はご自身のものに置き換えてください。

以下のように、通貨名と残高が返ってきます。
※”残高の数字”の箇所は、実際はfloat型の数値です。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[
{
"currency_code": "JPY",
"amount": 残高の数字,
"available": 残高の数字
},
{
"currency_code": "BTC",
"amount": 残高の数字,
"available": 残高の数字
}
]
[ { "currency_code": "JPY", "amount": 残高の数字, "available": 残高の数字 }, { "currency_code": "BTC", "amount": 残高の数字, "available": 残高の数字 } ]
[
    {
        "currency_code": "JPY",
        "amount": 残高の数字,
        "available": 残高の数字
    },
    {
        "currency_code": "BTC",
        "amount": 残高の数字,
        "available": 残高の数字
    }
]

新規注文 sendchildorder

ビットフライヤーの新規注文APIには、親注文(parent order)と子注文(child order)と2種類ありますが、ここでは child order で説明します。指値のときは child order を使うので。

サンプルコードは、BTC_JPYを指値で800万円で0.001サイズ注文しています。
練習なので、絶対に約定しないような価格設定でAPIを呼びます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
method = "POST"
endPoint = "https://api.bitflyer.com"
path = "/v1/me/sendchildorder"
url = endPoint + path
parameters = {
"product_code": "BTC_JPY",
"child_order_type": "LIMIT", # 指値
"side": "BUY",
"size": 0.001,
"price": 8000000,
}
timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path + json.dumps(parameters)
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()
headers = {
"ACCESS-KEY": apiKey,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json",
}
response = requests.post(url, headers=headers, data=json.dumps(parameters))
res = response.json()
print(json.dumps(res, indent=4))
method = "POST" endPoint = "https://api.bitflyer.com" path = "/v1/me/sendchildorder" url = endPoint + path parameters = { "product_code": "BTC_JPY", "child_order_type": "LIMIT", # 指値 "side": "BUY", "size": 0.001, "price": 8000000, } timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple()))) text = timestamp + method + path + json.dumps(parameters) sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest() headers = { "ACCESS-KEY": apiKey, "ACCESS-TIMESTAMP": timestamp, "ACCESS-SIGN": sign, "Content-Type": "application/json", } response = requests.post(url, headers=headers, data=json.dumps(parameters)) res = response.json() print(json.dumps(res, indent=4))
method   = "POST"
endPoint = "https://api.bitflyer.com"
path     = "/v1/me/sendchildorder"
url = endPoint + path

parameters = {
    "product_code": "BTC_JPY",
    "child_order_type": "LIMIT", # 指値
    "side": "BUY",
    "size": 0.001,
    "price": 8000000,
}

timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path + json.dumps(parameters)
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()

headers = {
    "ACCESS-KEY": apiKey,
    "ACCESS-TIMESTAMP": timestamp,
    "ACCESS-SIGN": sign,
    "Content-Type": "application/json",
    }

response = requests.post(url, headers=headers, data=json.dumps(parameters))
res = response.json()
print(json.dumps(res, indent=4))

戻り値は”受付ID”が返ってきます。※”nn”の部分は数字が入ります。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn"
}
{ "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn" }
{
    "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn"
}

注文一覧の取得 getchildorders

新規注文が正しく通っているかを確認するために、注文一覧取得APIを使います。

4行目のハイライトしている行でハマりました。
url内にproduct_codeを入れ込むのですが、”?product_code=”形式じゃないとエラーになりました。
そのときのエラーは”error_message”: “Invalid signature” でした。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
method = "GET"
endPoint = "https://api.bitflyer.com"
path = "/v1/me/getchildorders"
path += "?product_code=BTC_JPY"
url = endPoint + path
timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()
headers = {
"ACCESS-KEY": apiKey,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))
method = "GET" endPoint = "https://api.bitflyer.com" path = "/v1/me/getchildorders" path += "?product_code=BTC_JPY" url = endPoint + path timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple()))) text = timestamp + method + path sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest() headers = { "ACCESS-KEY": apiKey, "ACCESS-TIMESTAMP": timestamp, "ACCESS-SIGN": sign, "Content-Type": "application/json", } response = requests.get(url, headers=headers) res = response.json() print(json.dumps(res, indent=4))
method   = "GET"
endPoint = "https://api.bitflyer.com"
path     = "/v1/me/getchildorders"
path += "?product_code=BTC_JPY"
url = endPoint + path

timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()

headers = {
    "ACCESS-KEY": apiKey,
    "ACCESS-TIMESTAMP": timestamp,
    "ACCESS-SIGN": sign,
    "Content-Type": "application/json",
    }

response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))

注文一覧を取得できます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[
{
"id": 0,
"child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn",
"product_code": "BTC_JPY",
"side": "BUY",
"child_order_type": "LIMIT",
"price": 8000000.0,
"average_price": 0.0,
"size": 0.001,
"child_order_state": "ACTIVE",
"expire_date": "yyyy-mm-ddT00:00:00",
"child_order_date": "yyyy-mm-ddT00:00:00",
"child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn",
"outstanding_size": 0.001,
"cancel_size": 0.0,
"executed_size": 0.0,
"total_commission": 0.0,
"time_in_force": "GTC"
}
]
[ { "id": 0, "child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn", "product_code": "BTC_JPY", "side": "BUY", "child_order_type": "LIMIT", "price": 8000000.0, "average_price": 0.0, "size": 0.001, "child_order_state": "ACTIVE", "expire_date": "yyyy-mm-ddT00:00:00", "child_order_date": "yyyy-mm-ddT00:00:00", "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn", "outstanding_size": 0.001, "cancel_size": 0.0, "executed_size": 0.0, "total_commission": 0.0, "time_in_force": "GTC" } ]
[
    {
        "id": 0,
        "child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn",
        "product_code": "BTC_JPY",
        "side": "BUY",
        "child_order_type": "LIMIT",
        "price": 8000000.0,
        "average_price": 0.0,
        "size": 0.001,
        "child_order_state": "ACTIVE",
        "expire_date": "yyyy-mm-ddT00:00:00",
        "child_order_date": "yyyy-mm-ddT00:00:00",
        "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn",
        "outstanding_size": 0.001,
        "cancel_size": 0.0,
        "executed_size": 0.0,
        "total_commission": 0.0,
        "time_in_force": "GTC"
    }
]

注文のキャンセル cancelchildorder

注文キャンセルAPIにも、親注文用と子注文用がありますが、子注文用の例を示します。

キャンセルする注文の指定は新規注文時の”受付ID”で”JRF”で始まる文字列となります。
※”order_id”を”受付ID”に置き換えてください。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
method = "POST"
endPoint = "https://api.bitflyer.com"
path = "/v1/me/cancelchildorder"
url = endPoint + path
parameters = {
"product_code": "BTC_JPY",
"child_order_acceptance_id": order_id,
}
timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path + json.dumps(parameters)
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()
headers = {
"ACCESS-KEY": apiKey,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json",
}
response = requests.post(url, headers=headers, data=json.dumps(parameters))
print(response)
print(response.status_code)
method = "POST" endPoint = "https://api.bitflyer.com" path = "/v1/me/cancelchildorder" url = endPoint + path parameters = { "product_code": "BTC_JPY", "child_order_acceptance_id": order_id, } timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple()))) text = timestamp + method + path + json.dumps(parameters) sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest() headers = { "ACCESS-KEY": apiKey, "ACCESS-TIMESTAMP": timestamp, "ACCESS-SIGN": sign, "Content-Type": "application/json", } response = requests.post(url, headers=headers, data=json.dumps(parameters)) print(response) print(response.status_code)
method   = "POST"
endPoint = "https://api.bitflyer.com"
path     = "/v1/me/cancelchildorder"
url = endPoint + path

parameters = {
    "product_code": "BTC_JPY",
    "child_order_acceptance_id": order_id,
}

timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path + json.dumps(parameters)
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()

headers = {
    "ACCESS-KEY": apiKey,
    "ACCESS-TIMESTAMP": timestamp,
    "ACCESS-SIGN": sign,
    "Content-Type": "application/json",
    }

response = requests.post(url, headers=headers, data=json.dumps(parameters))
print(response)
print(response.status_code)

戻り値はHTTPレスポンスのステータスコードだけで、中身はありませんでした。
ステータスコード=200ならOKです。
中身が無いので response.json() するとエラーになります。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<Response [200]>
200
<Response [200]> 200
<Response [200]>
200

約定一覧の取得 getexecutions

botで注文の約定を確認するために、約定一覧取得APIを使います。注文サイズが最小注文数量よりも大きい場合は、一度に約定せず、複数の取引に分かれることがあるので、bot作成では注意が必要です。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
method = "GET"
endPoint = "https://api.bitflyer.com"
path = "/v1/me/getexecutions"
path += "?product_code=BTC_JPY"
url = endPoint + path
timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()
headers = {
"ACCESS-KEY": apiKey,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))
method = "GET" endPoint = "https://api.bitflyer.com" path = "/v1/me/getexecutions" path += "?product_code=BTC_JPY" url = endPoint + path timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple()))) text = timestamp + method + path sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest() headers = { "ACCESS-KEY": apiKey, "ACCESS-TIMESTAMP": timestamp, "ACCESS-SIGN": sign, "Content-Type": "application/json", } response = requests.get(url, headers=headers) res = response.json() print(json.dumps(res, indent=4))
method   = "GET"
endPoint = "https://api.bitflyer.com"
path     = "/v1/me/getexecutions"
path += "?product_code=BTC_JPY"
url = endPoint + path

timestamp = "{0}000".format(int(time.mktime(datetime.now().timetuple())))
text = timestamp + method + path
sign = hmac.new(bytes(secretKey.encode("ascii")), bytes(text.encode("ascii")), hashlib.sha256).hexdigest()

headers = {
    "ACCESS-KEY": apiKey,
    "ACCESS-TIMESTAMP": timestamp,
    "ACCESS-SIGN": sign,
    "Content-Type": "application/json",
    }

response = requests.get(url, headers=headers)
res = response.json()
print(json.dumps(res, indent=4))

約定一覧が返ってきます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[
{
"id": 0,
"side": "BUY",
"price": 8000000.0,
"size": 0.001,
"exec_date": "yyyy-mm-ddT00:00:00.000",
"child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn",
"commission": 7e-07,
"child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn"
}
]
[ { "id": 0, "side": "BUY", "price": 8000000.0, "size": 0.001, "exec_date": "yyyy-mm-ddT00:00:00.000", "child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn", "commission": 7e-07, "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn" } ]
[
    {
        "id": 0,
        "side": "BUY",
        "price": 8000000.0,
        "size": 0.001,
        "exec_date": "yyyy-mm-ddT00:00:00.000",
        "child_order_id": "JORnnnnnnnn-nnnnnn-nnnnnn",
        "commission": 7e-07,
        "child_order_acceptance_id": "JRFnnnnnnnn-nnnnnn-nnnnnn"
    }
]

APIのレスポンス

APIコールには requests を使います。
requests の戻り値の型は、requests.Response です。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
response = requests.get(url)
print(response)
print(response.status_code)
response = requests.get(url) print(response) print(response.status_code)
response = requests.get(url)
print(response)
print(response.status_code)

上記のように request.get() を呼ぶと、以下のようになります。
botでは、HTTPレスポンスのstatus_codeを使ってIF文を書くのもアリだと思います。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<Response [200]>
200
<Response [200]> 200
<Response [200]>
200

requestsの戻り値ではなく、ビットフライヤーのAPIのレスポンスの中身は以下のようにして取得します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
res = response.json()
res = response.json()
res = response.json()

エラーコード

API使用時にエラーで引っかかることがあると思います。仕様書を読んでもわからないエラーもあるので、なかなか解決できずムキムキしてしまいます。私が遭遇したエラーの例を書き出してみました。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"status": -500,
"error_message": "Invalid signature",
"data": null
}
{ "status": -500, "error_message": "Invalid signature", "data": null }
{
    "status": -500,
    "error_message": "Invalid signature",
    "data": null
}

“Invalid signature” は、timestampの作成方法がおかしかったり、signatureの構造がおかしいと、このエラーになります。
NGになっているAPIに関して、私のサンプルコードと比べていただけると原因がわかるかもしれません。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"status": -109,
"error_message": "Price should be 0",
"data": null
}
{ "status": -109, "error_message": "Price should be 0", "data": null }
{
    "status": -109,
    "error_message": "Price should be 0",
    "data": null
}

priceパラメータの設定が不要なのに設定してしまった。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"status": -209,
"error_message": "You have reached the maximum open special orders.",
"data": null
}
{ "status": -209, "error_message": "You have reached the maximum open special orders.", "data": null }
{
    "status": -209,
    "error_message": "You have reached the maximum open special orders.",
    "data": null
}

ビットフライヤーはある一定の時間内に注文できる数に上限がありそうです。確かではないのですが、各通貨で10回/分くらいです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"status": -200,
"error_message": "Insufficient funds",
"data": null
}
{ "status": -200, "error_message": "Insufficient funds", "data": null }
{
    "status": -200,
    "error_message": "Insufficient funds",
    "data": null
}

資金不足です。