収益化へのステップ

bitFlyerのAPIを使用して、Pythonにより自動取引システムを作る

bitFlyerのAPIを使用して、Pythonにより自動取引システムを作る
  • 「ビットコイン、イーサリアム等、仮想通貨の自動売買システムを作りたい!」
  • 「売買の凄いアイデアを持っているけど、会社員だし、ずっとチャートを見てるのは無理・・・」
  • 「人工知能による、自動売買システムを作りたい!(近未来的でかっこいい!)」

本記事は、そのような方を対象にしています。

本記事にて、ご紹介するのは、以下の2点となります。

  • bitFlyer APIを使用に当たって、事前準備するもの
  • bitFlyer APIの使い方(Pythonコードのご紹介)

本記事は、Python初心者 以上の方を、対象にしています。

(Python入門レベルの方でも、少し勉強すれば理解できるよう、わかりやいコードを心がけました。)

また本記事では、bitFlyerが公開しているAPIのみを使ったコードを、ご紹介します。

(第3者が作った、ラッパーライブラリ等は、使用しないようにしました。)

お金の処理なので、信頼性があるコードのみ、使いたいと思ったからです。(そのライブラリがNGとか、決してそういう訳では、ございません。)

bitFlyerでの、事前準備

「API」を使用するために、事前準備するもの2つ ご紹介します。

1、bitFlyerの口座開設

本取引所の主な特徴ですが、

  • 資本力が高い(三井住友銀行グループのSMBCベンチャーキャピタル、みずほキャピタル 等々の大手企業から出資されている)
  • 国内最大級の仮想通貨取引所(ビットコイン取引量 日本一)
    「※ Bitcoin 日本語情報サイト調べ。国内暗号資産交換業者における 2021 年の年間出来高(差金決済/先物取引を含む)」
  • セキュリティーが最高評価(※ Sqreen 社調べ。2018年1月発表、世界140の仮想通貨取引所を対象に調査。)
  • 初心者に優しい画面設計、「bitWire」というメールアドレスだけで、ビットコインが送れるサービス

になります。

口座開設したいと思った方は、以下より申し込みできます。(bitFlyerの公式サイトに遷移します。)

bitFlyer 公式サイトへのリンク

以降の章からは、口座開設した前提での記事となっていますが、開設されていない方でも、十分に理解できる内容となっています。

口座開設の判断は、本記事を読まれてからでも、遅くないと思います。

2、API通信に必要な、「認証キー」情報を取得する。

API通信をするためには、

  • 「API Key」
  • 「API Secret」

を取得する必要があります。

「API Key」、「API Secret」情報は、絶対に人に漏らさないようにして下さい。

万が一、人に漏れた場合は、「作り直し」て下さい。

「認証キー」の取得手順

次の4つの手順で、「認証キー」を取得する事ができます。

① TOPページから、「bitFlyer Lightning」を選択

② 「bitFlyer Lightning」のサイトで、下記をクリック

③ ウインドウが出てくるので、「API」をクリック

④ 出現したウインドウより「新しいAPIキーを追加」をクリック

「新しいAPIキーを追加」をクリックすると、新しいポップアップが出てきます。

「全てチェック」にして、「OK」ボタンをクリックして下さい。

「認証キー」が作られます。

この「認証キー」は、プログラムにて使用します。大切に保管して下さい。

「認証キー」は、「API Key」「API Secret」の2つがあります。

両方必要なので、大切に保管して下さい。

bitFlyer APIを使ったコードの紹介

下記の順番で、ご紹介いたします。

bitFlyer 公式APIの仕様は、こちら(公式サイトに遷移)になります。

「わかりやすさ優先」という事で、「オブジェクト」は使用せず、「関数」のみのコードでご紹介しています。

口座の残高取得

bitFlyerの口座に、残高がいくらあるか、取得するコードになります。

下記コード中で出現する、それぞれの変数を

  • settings.api_key → bitFlyerサイトより取得した、「API key」
  • settings.api_secret → bitFlyerサイトより取得した、「API Secret」

で、置き換えて下さい。

setting.pyを別途作成し、機密情報はそこに入れておくのが、いいと思います。

下記コードになります。

api_key = **********
api_secret = *******************

本記事で紹介するコードでも、この方式を採用しています。

——-更に参考———–

更に優れているのは、「setting.ini」 ファイルを作って、configparserを使って、settings.pyに読込む方式です。

そしてファイルアクセス権限を設定すれば、セキュリティーの点でも、優れています。

その他にも、環境変数を使ったりする方法等があります。

ご検討頂ければと思います。

コード(口座の残高取得)

HTTP通信ライブラリとして、「requests」を使用しています。

事前にインストールをお願いします。

pip install requests

下記コードの get_balance()を呼ぶと、残高が取得できます。

(def header( )部分は、後ほど、ご紹介しています。)

import hashlib
import hmac
import requests
import time


def header(method: str, endpoint: str, body: str) -> dict:
    timestamp = str(time.time())
    if body == '':
        message = timestamp + method + endpoint
    else:
        message = timestamp + method + endpoint + body
    signature = hmac.new(settings.api_secret.encode('utf-8'), message.encode('utf-8'),
                         digestmod=hashlib.sha256).hexdigest()
    headers = {
        'Content-Type': 'application/json',
        'ACCESS-KEY': settings.api_key,
        'ACCESS-TIMESTAMP': timestamp,
        'ACCESS-SIGN': signature
    }
    return headers


def get_balance():
    base_url = 'https://api.bitflyer.com'
    endpoint = '/v1/me/getbalance'

    headers = header('GET', endpoint=endpoint, body='')
    response = requests.get(base_url + endpoint, headers=headers)
    return response.json()

 

requestsコマンドを使う際は、try〜except を使って、例外処理をするようにして下さい。

ここでは、分かりやすさ優先で、あえて記載せずに、ご紹介しています。

実行結果

上記コードの、get_balance()を実行した結果です。

JSONで返ってきたものを、辞書型に変換しています。(response.json()の部分です。)

bitFlyerが扱っている、アルトコイン全体の残高が返ってきます。

# **** → 実際には、数字が入っています。

[{'currency_code': 'JPY', 'amount': ******, 'available': ******}, 
{'currency_code': 'BTC', 'amount': ******, 'available': ******}, 
{'currency_code': 'BCH', 'amount': 0.0, 'available': 0.0}, 
{'currency_code': 'ETH', 'amount': ******, 'available': ******}, 
{'currency_code': 'ETC', 'amount': 0.0, 'available': 0.0}, 
{'currency_code': 'LTC', 'amount': ******, 'available': ******}, 
{'currency_code': 'MONA', 'amount': 0.0, 'available': 0.0}, 
{'currency_code': 'LSK', 'amount': ******, 'available': ******}, 
{'currency_code': 'XRP', 'amount': ******, 'available': ******}, 
{'currency_code': 'BAT', 'amount': ******, 'available': ******}, 
{'currency_code': 'XLM', 'amount': ******, 'available': ******}, 
{'currency_code': 'XEM', 'amount': ******, 'available': ******}, 
{'currency_code': 'XTZ', 'amount': ******, 'available': ******}, 
{'currency_code': 'DOT', 'amount': 0.0, 'available': 0.0}]

amountは「資産残高」、availableは「使用可能残高」になります。

(指値発注時など、一部の資産が拘束されるため、「amount」 と 「available」は異なる場合があります。)

上記JSON中の、****は実際は数字が返ってきます。(筆者の残高情報が入っているため、*に置き換えました・・・)

コード中の認証部分の説明

コード中の、def header(・・・ の部分になります。

bitFlyerの公式APIサイトに以下の説明が書かれています。

以下の情報を HTTP リクエストヘッダに含めます。

  • ACCESS-KEY開発者ページで発行した API key
  • ACCESS-TIMESTAMP: リクエスト時の Unix Timestamp
  • ACCESS-SIGN: 以下の方法でリクエストごとに生成した署名

ACCESS-SIGN は、ACCESS-TIMESTAMPHTTP メソッドリクエストのパスリクエストボディ を文字列として連結したものを、 API secret で HMAC-SHA256 署名を行った結果です。

公式のページでは、Node.jsで書かれたコードが紹介されていましたが、それをPythonに直しました。

この部分、よく分からなくても、このままコピペで大丈夫です。

(今回のAPI使用に関しては、これで事足ります。)

ビットコイン価格の取得(1回のみ)

コード(ビットコイン価格の取得)

ビットコインの事例で、価格取得方法をご紹介します。

イーサリアムの場合は、コード中の変数を「product_code = ‘eth_jpy’」に変更して下さい。

def get_ticker():
    base_url = 'https://api.bitflyer.com'
    endpoint = '/v1/ticker'
    product_code = 'btc_jpy'  # ビットコインの場合
    # product_code = 'eth_jpy' # イーサリアムの場合

    response = requests.get(base_url + endpoint, params={"product_code": product_code})
    return response.json()

実行結果

上記コードの、get_ticker()を実行した結果です。

同じく、JSONで返ってきたものを、辞書型に変換しています。

返ってくる値の各意味を、注釈にて記述しておきました。

{'product_code': 'BTC_JPY', 
'state': 'RUNNING', 
'timestamp': '2021-08-14T03:10:19.72',  # UTCで表示
'tick_id': 16261706,  
'best_bid': 5211026.0,   # 最高買価格
'best_ask': 5213834.0,   # 最低売価格
'best_bid_size': 0.02,  # 最高買価格数
'best_ask_size': 0.1235,  # 最低売価格数
'total_bid_depth': 840.49197604, # 売り注文総数
'total_ask_depth': 469.6806732,  # 買い注文総数
'market_bid_size': 0.0,  # 板寄せ時の売りの成行注文量
'market_ask_size': 0.0,  # 板寄せ時の買いの成行注文量
'ltp': 5213834.0,         # 最終取引価格
'volume': 11186.61364203,  # 24hの取引量
'volume_by_product': 3620.19260028  # 価格ごとの出来高
}

発注する

単純な指値注文 (LIMIT)、成り行き注文 (MARKET)のみを対象としたコードをご紹介します。

それ以外は、bitFlyerさんのAPIでは、「親注文」という特殊注文扱いになります。下記記事にて、ご紹介しています。

仮想通貨の自動取引、bitFlyerでの特殊注文 - IFD、OCO、IFDOCO、ストップ、ストップリミット、トレール注文 等 -
仮想通貨の自動取引、bitFlyerでの特殊注文 - IFD、OCO、IFDOCO、ストップ、ストップリミット、トレール注文 等 -bitFlyerのAPIを使用して、Pythonにより自動取引システムで、特注注文(ストップ、ストップリミット、トレール注文 等)の作り方を、解説した記事です。...

コード(発注)

ビットコインの事例です。

イーサリアムの場合は、コード中の6行目を「product_code = ‘eth_jpy’」に変更して下さい。

また、口座の残高で紹介した、header関数「header()」を、使用しています。

def order():
    base_url = 'https://api.bitflyer.com'
    endpoint = "/v1/me/sendchildorder"

    body = {
        "product_code": 'btc_jpy',  # ビットコイン(日本円)
        "child_order_type": 'LIMIT',  # 指値。成行きの場合は、MARKET
        "side": 'BUY',  # 「買い」注文
        "price": 3000000,  # 価格指定
        "size": 0.001,  # 注文数量
        "minute_to_expire": 1000,  # 期限切れまでの時間(分)
        "time_in_force": 'GTC'  # GTC発注
    }

    body = json.dumps(body)
    headers = header('POST', endpoint=endpoint, body=body)

    response = requests.post(base_url + endpoint, data=body, headers=headers)
    return response.json()

実行結果

上記の order()を呼んだ結果です。

同じく、JSONで返ってきたものを、辞書型に変換しています。

下記の「API受付ID」は、キャンセル処理する際に、使用します。

{
'child_order_acceptance_id': 'JRF20210323-115602-225510'  # 発注時の「API受付ID」
}

注文の一覧を確認する

コード(注文の一覧を確認する)

ビットコインを事例にして、注文した一覧を取得するコードをご紹介します。

イーサリアムの場合は、「product_code = ‘eth_jpy’」に変更して下さい。

また、口座の残高で紹介した、header関数「header()」を、使用しています。

def list_child_order():
    base_url = 'https://api.bitflyer.com'
    endpoint = '/v1/me/getchildorders'
    product_code = 'btc_jpy'  # ビットコイン価格(日本円)

    params = {
        "product_code": product_code
    }
    endpoint_for_header = endpoint + '?'
    for k, v in params.items():
        endpoint_for_header += k + '=' + v
        endpoint_for_header += '&'
    endpoint_for_header = endpoint_for_header[:-1]

    headers = header('GET', endpoint=endpoint_for_header, body='')
    response = requests.get(base_url + endpoint, headers=headers, params=params)
    return response.json()

実行結果

上記の list_child_order()を実行した結果です。

同じく、JSONで返ってきたものを、辞書型に変換しています。

返ってくる値の意味を、注釈で記述しておきました。

[{'id': 2456291909, 
'child_order_id': 'JOR20210323-115602-043106',  # 注文する時に発行される一意なID 
'product_code': 'BTC_JPY', 
'side': 'SELL',   # 「売り」で発注
'child_order_type': 'MARKET',  # 「成り行き」発注
'price': 0.0, 
'average_price': 5895493.0,  # 「約定時」の平均価格
'size': 0.023,  # 約定した量
'child_order_state': 'COMPLETED',  # 取引完了の案件 オープンの注文があれば active になる。
'expire_date': '2021-04-22T11:56:02', 
'child_order_date': '2021-03-23T11:56:02', 
'child_order_acceptance_id': 'JRF20210323-115602-225510', # 発注時の 「API受付ID」 
'outstanding_size': 0.0, 
'cancel_size': 0.0, 
'executed_size': 0.023, 
'total_commission': 3.45e-05}, 

# 以下、2個目の発注内容が続く・・・
]

注文をキャンセル処理をする

注文をキャンセル処理をする(未約定の場合のみ)

特定のオーターをキャンセルする場合

コード中の「child_order_acceptance_id」は、発注時に発行された「API受付ID」に置き換えて下さい。

(このコード中の、「JRF20150707-033333-099999″」という番号で表示されている箇所を変更して下さい。)

また、口座の残高で紹介した、header関数「header()」を、使用しています。

キャンセルに成功すれば、ステータスコードとして、200 が返ってきます。

import json

def order_cancel(self):
    base_url = 'https://api.bitflyer.com'
    endpoint = "/v1/me/cancelchildorder"

    body = {
        "product_code": 'btc_jpy',
        "child_order_acceptance_id": "JRF20150707-033333-099999"
    }

    body = json.dumps(body)
    headers = self.header('POST', endpoint=endpoint, body=body)

    response = requests.post(base_url + endpoint, data=body, headers=headers)
    return response.status_code

全オーダーのキャンセルする場合
import json

def all_order_cancel():
    base_url = 'https://api.bitflyer.com'
    endpoint = "/v1/me/cancelallchildorders"

    body = {
        "product_code": 'btc_jpy'
    }

    body = json.dumps(body)
    headers = self.header('POST', endpoint=endpoint, body=body)

    response = requests.post(base_url + endpoint, data=body, headers=headers)
    return response.status_code

実行結果

正しく処理された場合は、ステータスコードの「200」が返ってきます。

リアルタイムでの、ビットコイン価格を取得

価格変動があった場合、リアルタイムに価格情報を取得するコードをご紹介します。

「WebSocket」を使用しています。

事前にインストールが必要です。

pip install websocket-client

コード(リアルタイムでの、ビットコイン価格を取得)

データが送られてくると、下記コード中の、「on_message」変数に代入した「get_real_ticker_on_message」関数が呼ばれます。

import websocket


def get_realtime_ticker():
    product_code = 'BTC_JPY'  # 小文字NG

    web_socket_url = 'wss://ws.lightstream.bitflyer.com/json-rpc'
    channel = f'lightning_ticker_{product_code}'
    ws = websocket.WebSocketApp(web_socket_url,
                                on_message=get_real_ticker_on_message,
                                on_open=lambda wss: wss.send(json.dumps({'method': 'subscribe',
                                                                         'params': {'channel': channel}}))
                                )
    try:
        ws.run_forever()
    except Exception as e:
        # ロギング処理するとか
        raise


def get_real_ticker_on_message(ws, message):
    # WebsocketでJSON-RPCから情報が来た時の処理
    message = json.loads(message)['params']
    message = message.get('message')
    print(message)
  • 「on_open」変数 → websocket 実行前に実施
  • その他、エラー発生時、websocket 終了時に、実行する関数登録も可能です。

実行結果

上記コードの「get_real_ticker_on_message」関数中の、message変数の中身です。

下記の情報がリアルタイムで送られてきます。

{'product_code': 'BTC_JPY', 
'state': 'RUNNING', 
'timestamp': '2021-08-15T02:52:02.6888776Z',  # UTCで表示
'tick_id': 17356610,  
'best_bid': 5179796.0,  # 最高買価格
'best_ask': 5182499.0,  # 最低売価格
'best_bid_size': 0.2568,  # 最高買価格数
'best_ask_size': 0.47,  # 最低売価格数
'total_bid_depth': 852.46014501,  # 売り注文総数
'total_ask_depth': 593.72290046,  # 買い注文総数
'market_bid_size': 0.0,  # 板寄せ時の売りの成行注文量
'market_ask_size': 0.0,  # 板寄せ時の買いの成行注文量
'ltp': 5179792.0,  # 最終取引価格
'volume': 3364.02532087,  # 24hの取引量
'volume_by_product': 3364.02532087 # 価格ごとの出来高
}

実際の売買システムとしては、

  • この取得した情報を分析し、売買戦略に基づき、売買処理をする

というコードになります。

素晴らしい売買戦略を見つけられれば、お金という観点では、「人生の勝ち」が決まったようなものです(笑)

分析手法として、

  • テクニカル分析

が候補として挙がると思います。

下記記事が参考になるかと思います。併せてどうぞ。

【 Python 】Ta-Libを用いた、テクニカル分析 6選
【 Python 】Ta-Libを用いた、テクニカル分析 6選Pythonにて、金融取引のテクニカル分析 実装コードを紹介した記事です。...

最後に

本記事を読んで、「私でも作れそう」と思って頂けたら、幸いです。

「よく分からなかった・・・」と思われた方でも、

最初のうちは、本記事のコードを「コピペ」して使っていく中で、段々と理解できていくと思います。

冒頭でもお話しましたが、「bitFlyer」は他社にない強みがあってお薦めです。

口座作成費用、口座維持費用は無料ですし、自動売買取引のAPIデビューにはオススメです。

(金額を思いっきり少なくして取引すれば、数千円位から取引可能です。

申し込みは下記リンクより可能です。(bitFlyerの公式サイトに遷移します。)

bitflyer 公式サイトへのリンク

それではまた、お会いしましょう!