GMOコインのAPIを使って仮想通貨botを作りましょう。
この記事ではPythonでGMOコインのAPIを使う方法を動作するコードを使って紹介します。
前準備
GMOコインに口座を開設する
この記事を呼んだらすぐにAPIを使えるように、GMOコインで口座開設しておきましょう。
GMOコインのAPI仕様書
GMOコインはAPIのサンプルコードをサイトで公開してくれています。
Python・Go・Rubyなど。
requestsモジュールのAPI仕様書
APIコールに使用するrequestsモジュールの仕様書です。
HTTPレスポンスのステータスコードの概要です。
必要なPythonモジュール
サンプルコードでimportするモジュールです。
import requests import json import time from datetime import datetime import hmac import hashlib
Public API
まずはPublic APIの使い方です。
口座開設していなくても使用可能なので、練習でAPIを呼んでみましょう。
取引所ステータス
取引所の状態の取得方法です。
MAINTENANCEのときはbotで新規注文しないようにしましょう。
# 取引所ステータス取得 endPoint = 'https://api.coin.z.com/public' path = '/v1/status' url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
レスポンスはこうなります。
{ "status": 0, "data": { "status": "OPEN" }, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
最新レート
最新レートの取得方法です。
ask、bid、LTP(Last Traded Price:最終取引価格)などがわかります。
例として、ビットコイン現物の最新レートを取得しています。
# 最新レート取得 symbol = 'BTC' # ビットコイン現物 endPoint = 'https://api.coin.z.com/public' path = '/v1/ticker?symbol=' + symbol url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
レスポンスはこうなります。
{ "status": 0, "data": [ { "ask": "8678508", "bid": "8678507", "high": "8682990", "last": "8678507", "low": "8629493", "symbol": "BTC", "timestamp": "yyyy-mm-ddTHH:MM:SS.FFFZ", "volume": "109.2559" } ], "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
板情報
板情報の取得方法です。
買いと売りの注文の入り具合がわかります。
例として、ビットコイン現物の板情報を取得します。
# 板情報取得 symbol = 'BTC' # ビットコイン現物 endPoint = 'https://api.coin.z.com/public' path = '/v1/orderbooks?symbol=' + symbol url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
一部省略しますが、レスポンスはこうなります。
{ "status": 0, "data": { "asks": [ { "price": "8673900", "size": "0.2476" }, { "price": "8674461", "size": "0.02" } ], "bids": [ { "price": "8673313", "size": "0.0005" }, { "price": "8671450", "size": "0.0002" } ], "symbol": "BTC" }, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
KLine情報
KLine情報を取得できます。
KLine情報とは、ローソク足情報(OHLCVデータ)のことです。
例として、2024/8/1のビットコイン現物の1分足のOHLCVを取得してみます。
# KLine取得 symbol = 'BTC' # ビットコイン現物 interval = '1min' # 1分足 date_str = '20240801' # 日付 endPoint = 'https://api.coin.z.com/public' path = '/v1/klines?symbol={}&interval={}&date={}' .format( symbol, interval, date_str, ) url = endPoint + path response = requests.get(url) res = response.json() print(json.dumps(res, indent=4))
4時間足より長いローソク足の場合は、dateパラメータのフォーマットが変わります。詳細はAPI仕様書でご確認ください。
一部省略しますが、レスポンスはこうなります。
{ "status": 0, "data": [ { "openTime": "1722459600000", "open": "9710660", "high": "9710660", "low": "9708500", "close": "9708500", "volume": "0.0228" }, { "openTime": "1722459660000", "open": "9708500", "high": "9708500", "low": "9708001", "close": "9708025", "volume": "0.0766" } ], "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
レスポンスにopenTimeがあります。
API仕様書を見ると「openTime:開始時刻のunixタイムスタンプ(ミリ秒)」となっています。
UNIXタイムスタンプとは、Wikipediaによると「協定世界時(UTC)での1970年1月1日午前0時0分0秒(UNIXエポック)から形式的な経過秒数」です。
レスポンスのUNIX時間を実時間に変換してみます。
from datetime import datetime, timezone # openTimeは、開始時刻のunixタイムスタンプ(ミリ秒)。 # UNIX時間をdatetimeに変換する。 dt = datetime.fromtimestamp(1722459600000/1000, timezone.utc) print(dt) # 2024-07-31 21:00:00+00:00 dt = datetime.fromtimestamp(1722459660000/1000, timezone.utc) print(dt) # 2024-07-31 21:01:00+00:00
サンプルでAPIを呼んだときのdateパラメータは”20240801“を設定しました。レスポンスのopenTimeの先頭の実時間は”2024-07-31 21:00:00+00:00“でした。
UTC(協定世界時)とJST(日本標準時)の時差は9時間です。
dateパラメータの仕様は、「日本時間朝6:00に新しい日付に切り替わります。」となっています。
つまり、dateに”20240801″を設定すると、2024-08-01 06:00:00+09:00(JST)で指定していることになり、OHLCVデータは指定したJSTの9時間前の2024-07-31 21:00:00+00:00(UTC)からのデータを返してくれています。
APIのパラメータミスがあれば、以下のようなレスポンスが返ります。
{ "status": 2, "messages": [ { "message_code": "ERR-5207", "message_string": "Not found" } ] }
{ "status": 1, "messages": [ { "message_code": "ERR-5106", "message_string": "Invalid request parameter. date" } ] }
Private API
Private APIを使うには、APIキーが必要となります。
口座開設して、APIキーを取得しましょう。
下に示すサンプルコードで、apiKey と secretKey という変数を使用しています。
これら変数はご自身のものに置き換えてください。
・apiKey: APIキー
・secretKey: APIシークレット
GMOコインは現物取引とレバレッジ取引の両方可能ですが、この記事では主に現物取引で使用するAPIのサンプルコードを紹介します。
資産残高
口座の資産残高を取得します。
# 資産残高の取得 method = 'GET' endPoint = 'https://api.coin.z.com/private' path = '/v1/account/assets' 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 = { "API-KEY": apiKey, "API-TIMESTAMP": timestamp, "API-SIGN": sign } response = requests.get(url, headers=headers) res = response.json() print(json.dumps(res, indent=4))
ハイライトしている行のapiKeyとsecretKeyは置き換えてください。
レスポンスはこうなります。
{ "status": 0, "data": [ { "amount": "nnn", "available": "nnn", "conversionRate": "1", "symbol": "JPY" }, { "amount": "nnn", "available": "nnn", "conversionRate": "8447664", "symbol": "BTC" } ], "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
nnnの部分には数値が入り、値は文字列で返ってきます。
注文
新規注文APIを使ってみます。
ビットコイン現物を指値800万円、サイズ0.001の買いの例です。
# 新規注文 method = 'POST' endPoint = 'https://api.coin.z.com/private' path = '/v1/order' url = endPoint + path parameters = { "symbol": 'BTC', # ビットコイン現物 "side": 'BUY', # 買い "executionType": 'LIMIT', # 指値 "price": str(8000000), "size": str(0.001) } 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 = { "API-KEY": apiKey, "API-TIMESTAMP": timestamp, "API-SIGN": sign } response = requests.post(url, headers=headers, data=json.dumps(parameters)) res = response.json() print(json.dumps(res, indent=4))
レスポンスはこうなります。
dataに注文IDが入っています。nは数字で、dataは文字列になっています。
{ "status": 0, "data": "nnnnnnnnnn", "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
有効注文一覧
サンプルで注文したので、注文一覧APIを使ってみます。
# 有効注文一覧の取得 method = 'GET' endPoint = 'https://api.coin.z.com/private' path = '/v1/activeOrders' url = endPoint + path parameters = { "symbol": 'BTC', # ビットコイン現物 } 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 = { "API-KEY": apiKey, "API-TIMESTAMP": timestamp, "API-SIGN": sign } response = requests.get(url, headers=headers, params=parameters) res = response.json() print(json.dumps(res, indent=4))
レスポンスはこうなります。
サンプル注文の内容と一致しています。
{ "status": 0, "data": { "list": [ { "executedSize": "0", "executionType": "LIMIT", "losscutPrice": "0", "orderId": nnnnnnnnnn, "orderType": "NORMAL", "price": "8000000", "rootOrderId": nnnnnnnnnn, "settleType": "OPEN", "side": "BUY", "size": "0.001", "status": "ORDERED", "symbol": "BTC", "timeInForce": "FAS", "timestamp": "yyyy-mm-ddTHH:MM:SS.FFFZ" } ], "pagination": { "count": 100, "currentPage": 1 } }, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
注文キャンセル
サンプル注文を注文キャンセルAPIでキャンセルします。
# 注文キャンセル method = 'POST' endPoint = 'https://api.coin.z.com/private' path = '/v1/cancelOrder' url = endPoint + path parameters = { "orderId": nnnnnnnnnn, # 注文ID。10桁の整数。 } 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 = { "API-KEY": apiKey, "API-TIMESTAMP": timestamp, "API-SIGN": sign } response = requests.post(url, headers=headers, data=json.dumps(parameters)) res = response.json() print(json.dumps(res, indent=4))
レスポンスはこのようになり、キャンセルできました。
{ "status": 0, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
最新の約定一覧
注文が約定したか確認するため、約定一覧APIを使ってみます。
# 最新の約定一覧の取得 method = 'GET' endPoint = 'https://api.coin.z.com/private' path = '/v1/latestExecutions' url = endPoint + path parameters = { "symbol": 'BTC', # ビットコイン現物 } 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 = { "API-KEY": apiKey, "API-TIMESTAMP": timestamp, "API-SIGN": sign } response = requests.get(url, headers=headers, params=parameters) res = response.json() print(json.dumps(res, indent=4))
約定があれば、レスポンスはこうなります。
nには数字が入ります。
{ "status": 0, "data": { "list": [ { "executionId": nnnnnnnnn, # 9桁の数値 "fee": "0", "lossGain": "0", "orderId": nnnnnnnnnn, # 10桁の数値 "price": "nnnnnnn", "settleType": "OPEN", "side": "BUY", "size": "0.001", "symbol": "BTC", "timestamp": "yyyy-mm-ddTHH:MM:SS.FFFZ" } ], "pagination": { "count": 100, "currentPage": 1 } }, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }
直近1日分の約定情報が無ければ、このレスポンスになります。
{ "status": 0, "data": {}, "responsetime": "yyyy-mm-ddTHH:MM:SS.FFFZ" }