野良ジニアのスクラップブック

野良エンジニアによる雑記帳。技術、本、便利グッズなどを気の向くままに。

仮想通貨トレード Bot 制作に便利な CCXT ライブラリに関する知見まとめ【Python・随時更新】

こんにちは、野良エンジニアです。

ひさしぶりに Bot を作っています。複数取引所に対応している ccxt を使ってみたので、つまずいた事やその解決策について随時まとめていきたいと思います。

初心者向け・仮想通貨Lisk(LSK)を少しでも安く大量に買う方法
Lisk Vote 完全まとめ!やり方、確認方法、実績、効率、税金、etc... 最大効率の報酬で枚数を増やそう
仮想通貨ブログを書くなら、仮想通貨ウェブフォントを導入しよう

Amazon プライムは絶対入るべき!メリット・特典・会費・退会方法をまとめて簡単に紹介
内村さまぁ~ず 第1〜50回から選ぶオススメ神回10選【Amazonプライムビデオ】
キッチン作業が最高に捗る突っ張りキッチンラック【オススメグッズ・スペース倍増】

ccxt とは

ccxt について、簡単にまとめておきます。

複数の取引所に対応しているライブラリ
取引所ごとのライブラリを使って個別開発する必要がない
CoincheckbitFlyerbinanceBITMEX など、主要取引所にはほぼ対応
JavaScript, Python, PHP に対応
CryptoCurrency eXchange Trading library の略


主な対応取引所

Coincheck
bitFlyer
bitbank
QUOINEX
Zaif
binance
Bitfinex
BITMEX
Bittrex
Huobi
Kucoin

ccxt - GitHub
対応取引所



スポンサーリンク

ccxt の使い方メモ

ここでは、Python での ccxt の使い方についてメモしていきます。


インストール

# pip install ccxt

Install - ccxt - GitHub


基本的な使い方

import ccxt

exchange = ccxt.bitflyer()

# Private API を利用する場合に設定
exchange.apiKey = "Key"
exchange.secret = "Secret"

# API 実行(スネークケース、キャメルケース、どちらの書き方でも良い)
exchange.fetch_ticker("BTC/JPY")  # Ticker(相場情報)の取得
exchange.fetchBalance()  # 残高情報の取得
exchange.create_limit_sell_order ('BTC/JPY', 0.01, 200000)  # 指値売り注文
...


対応メソッドの確認

まだ開発中のため、取引所によっては使用できないメソッドがあります。

exchange.has で使用できるメソッドを確認しましょう。

# encoding: utf-8
import ccxt

bitbank = ccxt.bitbank()
print(bitbank.has)


bitbank 対応メソッド ※2018/04/03 現在

見やすいように改行してます。

>>> import ccxt
>>> ccxt.bitbank().has
{
  'publicAPI': True,
  'privateAPI': True,
  'CORS': False,
  'cancelOrder': True,
  'cancelOrders': False,
  'createDepositAddress': False,
  'createOrder': True,
  'createMarketOrder': True,
  'createLimitOrder': True,
  'deposit': False,
  'editOrder': 'emulated',
  'fetchBalance': True,
  'fetchClosedOrders': False,
  'fetchCurrencies': False,
  'fetchDepositAddress': False,
  'fetchFees': False,
  'fetchFundingFees': False,
  'fetchL2OrderBook': True,
  'fetchMarkets': True,
  'fetchMyTrades': True,
  'fetchOHLCV': True,
  'fetchOpenOrders': True,
  'fetchOrder': False,
  'fetchOrderBook': True,
  'fetchOrderBooks': False,
  'fetchOrders': False,
  'fetchTicker': True,
  'fetchTickers': False,
  'fetchTrades': True,
  'fetchTradingFees': False,
  'withdraw': False
}


未対応メソッドを API から操作する

ccxt ManualAPI Method Naming Conventions にやり方が記載されています。

f:id:ryota-17:20180403195009p:plain


簡単にまとめておきます、キャメルケース(PrivateApi みたいに大文字で区切るやつ)、スネークケース(private_api みたいに _ で区切るやつ)、どちらでも良いです。

1. API の種別(Public or Private)
2. HTTP の Method(GET, POST)
3. API の URL
4. パラメータは辞書(dict)型


もう少し詳しい例を、bitbank API を使って書いておきます。

ccxt Manual
bitbank API Doc
bitbank API エラーコード一覧



スポンサーリンク

GET /user/spot/orders

取引所 API を直接叩いている(はず)ので、パラメータは各取引所の指定に従ってください。この例だと BTC/JPY って書くとエラーになります。

bitbank.privateGetUserSpotOrders({"symbol": "btc_jpy", "id": 12345678})
bitbank.private_get_user_spot_orders({"symbol": "btc_jpy", "id": 12345678})


GET /user/spot/active_orders

URL に _ が含まれているケース。キャメルケースにしたい場合は _ を削って、次を大文字にすれば OK。

orders = bitbank.privateGetUserSpotActiveOrders({"pair": "btc_jpy"})
orders = bitbank.private_get_user_spot_active_orders({"pair": "btc_jpy"})


残高の確認

fetch_balance () で残高が取得できます。

balance = bitbank.fetchBalance()
print(json.dumps(balance, indent: 2))


レスポンスはこんな感じ。

{
  "info": {
    "success": 1,
    "data": {
      "assets": [
        {
          "asset": "jpy",
          "amount_precision": 4,
          "onhand_amount": "0.0000",
          "locked_amount": "0.0000",
          "free_amount": "0.0000",
          "stop_deposit": false,
          "stop_withdrawal": false,
          "withdrawal_fee": {
            "threshold": "30000.0000",
            "under": "540.0000",
            "over": "756.0000"
          }
        },
        ...
      ]
    }
  },
  "jpy": {
    "free": 0.0,
    "used": 0.0,
    "total": 0.0
  },
  "btc": {
    "free": 0.0,
    "used": 0.0,
    "total": 0.0
  },
  ...
  "free": {
    "jpy": 0.0,
    "btc": 0.0,
    "ltc": 0.0,
    "xrp": 0.0,
    "eth": 0.0,
    "mona": 0.0,
    "bcc": 0.0
  },
  "used": {
    "jpy": 0.0,
    ...
  },
  "total": {
    "jpy": 0.0,
    ...
  }
}

Querying Account Balance


相場情報(ticker) 取得

fetch_ticker (symbol) で相場情報(ticker)が取得できます。

ticker = bitbank.fetch_ticker("BTC/JPY")
print(json.dumps(ticker, indent: 2))


レスポンスはこんな感じ。

{
  "symbol": "BTC/JPY",
  "timestamp": 1522762518935,
  "datetime": "2018-04-03T13:35:19.935Z",
  "high": 796405.0,
  "low": 736132.0,
  "bid": 790605.0,
  "bidVolume": null,
  "ask": 790773.0,
  "askVolume": null,
  "vwap": null,
  "open": null,
  "close": 790947.0,
  "last": 790947.0,
  "previousClose": null,
  "change": null,
  "percentage": null,
  "average": null,
  "baseVolume": 2163.0537,
  "quoteVolume": null,
  "info": {
    "sell": "790773",
    "buy": "790605",
    "high": "796405",
    "low": "736132",
    "last": "790947",
    "vol": "2163.0537",
    "timestamp": 1522762518935
  }
}

Price Tickers


注文関連

指値注文

Limit Orders


指値買い

create_limit_buy_order(symbol, amount, price[, params]) で指値買い、params は取引所固有のパラメータがあれば設定可能です。

result = bitbank.create_limit_buy_order("MONA/JPY", 1, 2000) # 1MONA を 2000円で買い注文
print(json.dumps(result, indent: 2))


レスポンスはこんな感じ。

{
  "id": "7378568",
  "datetime": "2018-04-03T12:55:37.805Z",
  "timestamp": 1522760136805,
  "status": "open",
  "symbol": "MONA/JPY",
  "type": "limit",
  "side": "buy",
  "price": 2000.0,
  "cost": 0.0,
  "amount": 1.0,
  "filled": 0.0,
  "remaining": 1.0,
  "trades": null,
  "fee": null,
  "info": {
    "order_id": 7378568,
    "pair": "mona_jpy",
    "side": "buy",
    "type": "limit",
    "start_amount": "1.00000000",
    "remaining_amount": "1.00000000",
    "executed_amount": "0.00000000",
    "price": "2000.0000",
    "average_price": "0.0000",
    "ordered_at": 1522760136805,
    "status": "UNFILLED"
  }
}


指値売り

create_limit_sell_order (symbol, amount, price[, params]) で指値売り、params は取引所固有のパラメータがあれば設定可能です。

result = bitbank.create_limit_sell_order("MONA/JPY", 1, 2000) # 1MONA を 2000円で売り注文
print(json.dumps(result, indent: 2))


レスポンスはこんな感じ。

{
  "id": "7378568",
  "datetime": "2018-04-03T12:55:37.805Z",
  "timestamp": 1522760136805,
  "status": "open",
  "symbol": "MONA/JPY",
  "type": "limit",
  "side": "sell",
  "price": 2000.0,
  "cost": 0.0,
  "amount": 1.0,
  "filled": 0.0,
  "remaining": 1.0,
  "trades": null,
  "fee": null,
  "info": {
    "order_id": 7378568,
    "pair": "mona_jpy",
    "side": "sell",
    "type": "limit",
    "start_amount": "1.00000000",
    "remaining_amount": "1.00000000",
    "executed_amount": "0.00000000",
    "price": "2000.0000",
    "average_price": "0.0000",
    "ordered_at": 1522760136805,
    "status": "UNFILLED"
  }
}


成行注文

create_market_buy_order (symbol, amount[, params])create_market_sell_order (symbol, amount[, params]) で成行注文。

成行注文といえど、メソッド実行した瞬間(= API 発行した瞬間)はまだ約定していないので注意。

{
  "id": "379751834",
  "datetime": "2018-04-03T17:02:40.871Z",
  "timestamp": 1522774959871,
  "status": "open",
  "symbol": "BTC/JPY",
  "type": "market",
  "side": "buy",
  "price": 0.0,
  "cost": 0.0,
  "amount": 0.0001,
  "filled": 0.0,
  "remaining": 0.0001,
  "trades": null,
  "fee": null,
  "info": {
    "order_id": 379751834,
    "pair": "btc_jpy",
    "side": "buy",
    "type": "market",
    "start_amount": "0.00010000",
    "remaining_amount": "0.00010000",
    "executed_amount": "0.00000000",
    "average_price": "0.0000",
    "ordered_at": 1522774959871,
    "status": "UNFILLED"
  }
}

Market Orders


注文の確認

fetch_order(id, symbol) で注文の最新状況を取得

order = bitbank.fetch_order(7378542, "MONA/JPY")
print(json.dumps(order, indent: 2))

レスポンスはこんな感じ。

{
  "id": "7378542",
  "datetime": "2018-04-03T12:54:55.633Z",
  "timestamp": 1522760094633,
  "status": "open",
  "symbol": "MONA/JPY",
  "type": "limit",
  "side": "sell",
  "price": 2000.0,
  "cost": 0.0,
  "amount": 1.0,
  "filled": 0.0,
  "remaining": 1.0,
  "trades": null,
  "fee": null,
  "info": {
    "order_id": 7378542,
    "pair": "mona_jpy",
    "side": "sell",
    "type": "limit",
    "start_amount": "1.00000000",
    "remaining_amount": "1.00000000",
    "executed_amount": "0.00000000",
    "price": "2000.0000",
    "average_price": "0.0000",
    "ordered_at": 1522760094633,
    "status": "UNFILLED"
  }
}


キャンセル

cancel_order(id, symbol) でキャンセル、id は文字列でも数値でも OK っぽい(bitbank はどっちでもいけました)

result = bitbank.cancel_order("7365919", "MONA/JPY")
print(json.dumps(result, indent: 2))

レスポンスはこんな感じ。

{
  "order_id": 7365912,
  "pair": "mona_jpy",
  "side": "sell",
  "type": "limit",
  "start_amount": "1.00000000",
  "remaining_amount": "1.00000000",
  "executed_amount": "0.00000000",
  "price": "1000.0000",
  "average_price": "0.0000",
  "ordered_at": 1522744451311,
  "canceled_at": 1522758207410,
  "status": "CANCELED_UNFILLED"
}

Canceling Orders


注文を全部キャンセル

例外処理とか未考慮ですが一案です。

orders = exchange.fetch_open_orders("MONA/JPY")
for order in orders:
  exchange.cancel_order(order["id"], order["symbol"])


JSON の整形

ccxt の戻り値は基本的に JSON 形式(のはず)。

json モジュールを import して json.dump メソッドで整形できます。

import json
print(json.dumps(json_data, indent=2))


例:fetch_ticker の整形

fetch_ticker はこうなります。

{
  "symbol": "BTC/JPY",
  "timestamp": 1522756790945,
  "datetime": "2018-04-03T11:59:51.945Z",
  "high": 796405.0,
  "low": 736132.0,
  "bid": 781570.0,
  "bidVolume": null,
  "ask": 782190.0,
  "askVolume": null,
  "vwap": null,
  "open": null,
  "close": 781554.0,
  "last": 781554.0,
  "previousClose": null,
  "change": null,
  "percentage": null,
  "average": null,
  "baseVolume": 2153.4508,
  "quoteVolume": null,
  "info": {
    "sell": "782190",
    "buy": "781570",
    "high": "796405",
    "low": "736132",
    "last": "781554",
    "vol": "2153.4508",
    "timestamp": 1522756790945
  }
}


例:GET /user/spot/orders の整形

GET /user/spot/orders はこうなります。

{
  "success": 1,
  "data": {
    "order_id": 12345678,
    "pair": "btc_jpy",
    "side": "sell",
    "type": "limit",
    "start_amount": "1.00000000",
    "remaining_amount": "1.00000000",
    "executed_amount": "0.00000000",
    "price": "1200000.0000",
    "average_price": "0.0000",
    "ordered_at": 1522744456362,
    "status": "UNFILLED"
  }
}


参考

他に ccxt について書かれているページをまとめておきます。

Python3とCCXTを使用して仮想通貨の自動売買プログラムを作る - エンジニアの頭の中
ccxtを使って裁定取引botを作ってみたらなぜか虚しくなった件 - Qiita
Python3とCCXTライブラリを用いたBitMEX自動売買bot作成Tips|AKAGAMI|note
[Python]CCXTを使ったBitMEXのオープンポジション取得方法(API) – Aoiue's memorandum


まとめ

少しずつ開発と記事更新を行っていきます。



スポンサーリンク

初心者向け・仮想通貨Lisk(LSK)を少しでも安く大量に買う方法
Lisk Vote 完全まとめ!やり方、確認方法、実績、効率、税金、etc... 最大効率の報酬で枚数を増やそう
仮想通貨ブログを書くなら、仮想通貨ウェブフォントを導入しよう

Amazon プライムは絶対入るべき!メリット・特典・会費・退会方法をまとめて簡単に紹介
内村さまぁ~ず 第1〜50回から選ぶオススメ神回10選【Amazonプライムビデオ】
キッチン作業が最高に捗る突っ張りキッチンラック【オススメグッズ・スペース倍増】