てけとーぶろぐ。

ソフトウェアの開発と、お絵かきと、雑記と。

Pythonでビットコインの価格を取得する(1)

Raspberry Pi + Pythonビットコイン自動取引」と銘打って書きはじめ
要素技術を身につけるための株価アラートの作成を終え
いよいよビットコインを扱うのですがそれにあたりまえがきを少し。

やりたいことは自動売買

Raspberry PiPythonビットコインも実は結果的にそれらを選ぶことになったもので
やりたいことは自作プログラムでの自動売買なんです。

プログラミングをしたことがあって、何らか投資をしたことがあるという人だったら
誰もが一度は夢見ることではないでしょうか?

自分は10年以上前からできたらいいなと思っていました。
それが最近になってようやく敷居をさげてくれるものが出てきていよいよ実現できるのではないかと思っています。

あたらめてコンセプト

Raspberry Pi + Pythonビットコイン自動取引」のコンセプトをあらためて載せておきます。

  • 高実現性

実現しなくては意味がありません。なんとかして実現します。実現させるために方法を選びます。

  • 低コスト

趣味で、あわよくば利益をというものなのに、コストがかかりすぎても仕方ありませんので…。

この2つをコンセプトとします。

なぜRaspberry Pi?なぜPython? なぜビットコイン

なぜRaspberry Piなのかについては前回まででお分かりいただけたかと思います。
なぜPythonなのかは実装のしやすさからです。
そしてなぜビットコインなのか。
ビットコインはその生まれからか、新興の投資対象であるからか、国内の取引所に自作プログラムから実行可能なAPIを用意しているところがいくつかあります。そこが理由です。
例えば国内株式についてはそのような仕組みを用意している証券会社は見当たりませんでした。
これがないと価格取得や発注のプログラムから用意しないといけないですし、その運用・保守もしなければいけなくなります。
そしてそれが今まで自分が自動取引を断念してきた主な理由でした。

要は自作プログラムでの自動売買を低コストで実現するためのRaspberry PiでありPythonでありビットコインです。

取引所を選ぶ

早速取引所を選びます。

  • 自作プログラムから実行可能なAPI
  • 国内の取引所
  • 安定性が期待できる有名所
  • 安い手数料

あたりからGMOコインを使うことにします。

coin.z.com

そうときまったら口座開設しましょう。

GMOコインのAPIを使う

早速GMOコインのAPIを使ってみましょう。
GMOコインには親切なAPIドキュメントがあり
Pythonでのサンプルコードも用意されています。

APIドキュメント| GMOコイン


GMOコインのAPIにはPublic APIとPrivate APIがあり
Public APIであれば口座開設せずとも実行することができます。
逆にPrivate APIは口座開設を行ってから得られるAPIキーとAPIシークレットがなければ実行することはできません。

幸いビットコインの価格を得るAPI「GET /public/v1/orderbooks」はPublic APIなので口座開設せずとも実行することができます。

API「GET /public/v1/orderbooks」のドキュメントは以下です。
APIドキュメント| GMOコイン

ドキュメントにあるサンプルの通りで十分ではありますが
今後を考えてAPIを実行するクラスを作っておきます。
結果もdataclassで返すようにします。
APIを実行し、APIが返してきたJSONに含まれる値をTickerクラスに詰め込んで返しているだけです。

from dataclasses import dataclass
from datetime import datetime
import requests
from datetime_util import DatetimeUtil

@dataclass
class Ticker:
    ask_price: int
    bid_price: int
    high_price: int
    last_price: int
    low_price: int
    symbol: str
    timestamp: datetime
    volume: float

class GmoCoinApi:
    def __init__(self, end_point) :
        self.end_point = end_point
    
    def get_ticker(self, symbol) -> Ticker:
        path = '/public/v1/ticker?symbol=' + symbol
        response = self._send_get_request(self.end_point + path)
        response_json = response.json()

        if response_json['status'] != 0:
            raise RuntimeError('API error.')

        ask_price = int(response_json['data'][0]['ask'])
        bid_price = int(response_json['data'][0]['bid'])

        # highにnullが入ってくることがあったのでその場合はNoneにする        
        response_json_high = response_json['data'][0]['high']
        if response_json_high is None:
            high_price = None
        else:
            high_price = int(response_json_high)

        last_price = int(response_json['data'][0]['last'])

        # lowにnullが入ってくることがあったのでその場合はNoneにする        
        response_json_low = response_json['data'][0]['low']
        if response_json_low is None:
            low_price = None
        else:
            low_price = int(response_json_low)

        symbol = response_json['data'][0]['symbol']
        timestamp = DatetimeUtil.iso_to_datetime(response_json['data'][0]['timestamp'])
        volume = float(response_json['data'][0]['volume'])

        ticker = Ticker(ask_price, bid_price, high_price, last_price, low_price, symbol, timestamp, volume)
        return ticker


    def _send_get_request(self, url, params=None, **kwargs):
        response = requests.get(url, params=params, **kwargs)
        return response


if __name__ == '__main__':

    gmo_coin_api = GmoCoinApi('https://api.coin.z.com')
    ticker = gmo_coin_api.get_ticker('BTC')
    print(ticker)


この中で使っている DatetimeUtil.iso_to_datetime() は
APIが返してくるISO 8601形式の時刻をdatetimeに変換するユーティリティメソッドで以下がソースコードです。

import datetime

class DatetimeUtil(object):

    @staticmethod
    def iso_to_datetime(iso: str) -> datetime:
        if iso is None:
            return None
            
        dt = datetime.datetime.fromisoformat(iso.replace('Z', '+00:00'))
        if (dt.tzinfo is not None) and (dt.tzinfo.utcoffset(dt) is not None):
            return dt
        else:
            return (dt.astimezone())

    @staticmethod
    def datetime_to_iso(dt: datetime) -> str:
        if dt is None:
            return None

        if (dt.tzinfo is not None) and (dt.tzinfo.utcoffset(dt) is not None):
            if dt.tzinfo == datetime.timezone.utc:
                return dt.isoformat().replace('+00:00', 'Z')
            else:
                return (dt.astimezone(datetime.timezone.utc)).isoformat().replace('+00:00', 'Z')
        else:
            return (dt.astimezone(datetime.timezone.utc)).isoformat().replace('+00:00', 'Z')

実行してみましょう。
実行にあたっては「requests」のパッケージが必要なので
未インストールの場合はインストールします。

> pip install requests

価格が取得できましたね。

時々刻々と変化する価格を取得するためには定期実行することになります。
株価アラートと同様にapschedulerを使って3秒おきに取得してみます。

from api import GmoCoinApi
from apscheduler.schedulers.background import BackgroundScheduler
from time import sleep
import json


gmo_coin_api = GmoCoinApi('https://api.coin.z.com')


def update():
    global is_exception_raised
    try:
        ticker = gmo_coin_api.get_ticker('BTC')
        print(ticker)
    except Exception as exception:
        print(exception)
        is_exception_raised = True


if __name__ == '__main__':
    
    scheduler = BackgroundScheduler()
    scheduler.add_job(update, trigger='interval', seconds=3, max_instances=10)
    scheduler.start()

    is_exception_raised = False

    try:
        while True:          
            if is_exception_raised:
                break

            sleep(0.001)

    except KeyboardInterrupt:
        pass

    scheduler.shutdown()

実行してみます。
実行にあたっては「apscheduler」のパッケージが必要なので
未インストールの場合はインストールします。

> pip install apscheduler

こんなふうにしてビットコインの価格を取得して、あとは、蓄積して、分析して、売買アルゴリズムを作っていこうと思います。

次回は取得した価格データを分析のためにデータベースに保存してみましょう。