Pythonを用いたGMOコインの仮想通貨APIの使い方

GMOコインのAPIを使って仮想通貨botを作りましょう。

この記事ではPythonでGMOコインのAPIを使う方法を動作するコードを使って紹介します。

前準備

GMOコインに口座を開設する

この記事を呼んだらすぐにAPIを使えるように、GMOコインで口座開設しておきましょう。

GMOコイン

GMOコインのAPI仕様書

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"
}