てけとーぶろぐ。

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

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

前回でビットコインの現在の価格を取得してコンソールに出力することができました。

自動取引の判断材料に使ったり、自動取引のシミュレーションをしたりするためには
現在の価格だけでなく、ある程度の期間の価格が必要になります。
これは現在の価格を取得してそれを記録することを一定期間行えばいいわけです。

記録の方法としてはファイルに書き込んでファイルに記録するのが簡単かと思います。
ですがここでは記録した価格データへのアクセスのしやすさを考えてデータベースに記録してみましょう。

データベースにも色々種類がありますが扱いが簡単で記録するデータのフォーマットも柔軟に変えられるMongoDBを使うことにします。

MongoDBのインストール(Windows PC)

Download Center: Community Server | MongoDB
から

  • Version: 4.2.7 (current release)
  • OS: Windows x64
  • Package: ZIP

を選択してDownloadをクリック。
ダウンロードした「mongodb-win32-x86_64-2012plus-4.2.7.zip」を
適当なディレクトリーに展開します。
(例: C:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.6)

mongodの起動と終了

MongoDBデーモンであるmongodを起動してみます。
DBへデータを読み書きする場合は
あらかじめこのmongodを起動しておく必要があります。

コマンドプロンプトを起動して
カレントディレクトリーをMongoDBインストール先のbinディレクトリーにします。

> cd C:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.7\bin

binディレクトリー内のmongod.exeを実行します。
実行の際にはデータディレクトリーの指定ができます。
ここでは「mongodb-win32-x86_64-2012plus-4.2.7」内の「data」ディレクトリーをデータディレクトリーとします。
データディレクトリーとして指定するディレクトリーはあらかじめ作成しておく必要があるので作成してから実行します。

> mongod --dbpath ../data

これでmongodが起動しました。

終了する場合は起動したコマンドプロンプト上でCtrl+Cキーを押します。

pymongoのインストール

PythonからMongoDBにアクセスするために
pymongoパッケージをインストールします。

Raspbianで簡単にインストールできるMongoDBのバージョンが2.4で
MongoDB 2.4 に対応した一番新しいpymongoのバージョンは3.5.1のようです。

PCで動かしていたプログラムがそのままRaspberry Pi(Raspbian OS)でも使えるよう
pymongoのバージョンを合わせるようにします。
つまりpymongo 3.5.1をバージョン指定してインストールします。

> pip install pymongo==3.5.1
MongoDBへの記録

ビットコインの現在の価格を取得してMongoDBに書き込むプログラムを作成します。
前回作成したビットコインの価格をコンソールに出力するプログラムをベースに
コンソールに出力する部分をMongoDBへの書き込みに書き換えて作成します。

前回作成したプログラム「main_print.py」を「main_mongo.py」という名前でコピーします。
主にこれのupdate()関数を書き換えていきます。
「main_mongo.py」の全体は以下のコードになります。

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


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

client = MongoClient('mongodb://localhost:27017/')
db = client['coin']


def update():
    global is_exception_raised
    try:
        ticker = gmo_coin_api.get_ticker('BTC')
        print(ticker)
        post = {
            'ask': ticker.ask_price,
            'bid': ticker.bid_price,
            'high': ticker.high_price,
            'last': ticker.last_price,
            'low': ticker.low_price,
            'symbol': ticker.symbol,
            'timestamp': ticker.timestamp,
            'volume': ticker.volume,
        }
        db['ticker'].insert_one(post)
    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()

以下のコードでMongoDBにアクセスするためのMongoClientクラスのインスタンスを作成しています。

client = MongoClient('mongodb://localhost:27017/')

引数は接続先のホスト名です。
このプログラムを実行しているのと同じマシン上で
mongodを起動するので「localhost」になります。

続く以下のコードで指定の名前のデータベースを表す
Databaseクラスのインスタンスを取得します。

db = client['coin']

「coin」という名前のデータベースを使うことにします。
データベースはあらかじめ作成していなくても
存在しない場合は作成されるので問題ありません。

データベースへのデータの書き込みはDatabaseクラスのインスタンスを使って行います。
以下のコードで「post」を「ticker」というコレクションに書き込んでいます。

        db['ticker'].insert_one(post)

DB内のデータの構成を簡単に説明すると
coinデータベース内に、tickerコレクションがあり、tickerコレクション内に
「_id」「ask」「bid」「high」「last」「low」「symbol」「timestamp」「volume」
といったフィールドを持つ価格データのドキュメント(オブジェクト)が複数格納されているという構成になります。
「_id」フィールドは自動的に作られる、オブジェクトのIDを持つフィールドです。

実行してみましょう。
実行にあたってはmongodを起動しておくことを忘れないでください。

mongo shellでデータの確認

プログラムの実行の結果DBにデータが書き込まれたか確認してみましょう。

Pythonプログラムからpymongoを使ってDBのデータを取得して確認してもいいのですが
簡単な確認であればmongo shellを使うのが楽です。

まずmongodを起動しておきます。

新しいコマンドプロンプトを起動しmongo shellを起動します。

> mongo

起動するとMongoDBに対するコマンドを受け付ける状態となります。
ここにデータ取得のコマンド等を入力してデータを確認したりします。

mongo shellを終了する場合はCtrl+Cキーを押します。

データの確認のために必要なコマンドを紹介します。

データベース一覧の表示

> show dbs

使用するデータベースの指定
データベースの削除や、データベース内のコレクションからドキュメントを検索したりするためにはあらかじめこのコマンドで使用するデータベースを指定しておく必要があります。

> use coin

※「coin」データベースの場合

データベースの削除

> use coin
> db.dropDatabase() 

※「coin」データベースの場合

データベース内のコレクション一覧の表示

> use coin
> show collections

※「coin」データベースの場合

データベース内のコレクションの削除

> use coin
> db.ticker.drop()

※「coin」データベース、「ticker」コレクションの場合

コレクション内のドキュメント一覧の表示

> use coin
> db.ticker.find()

※「coin」データベース、「ticker」コレクションの場合

コレクション内の最新X件のドキュメントの表示

> use coin
> db.ticker.find().sort({_id: -1}).limit(10);

※「coin」データベース、「ticker」コレクション、最新10件の場合

参照: https://docs.mongodb.com/manual/mongo/

さて、DBにデータが書き込まれたか確認できたでしょうか?

MongoDBのインストール(Raspberry Pi)

作成したプログラムをRaspberry Piでも動かしてみましょう。
そのためにはRaspberry PiにもMongoDBをインストールする必要があります。

Raspberry Piの場合はコマンド1つでMongoDBをインストールできます。

$ sudo apt-get install mongodb-server

またRaspberry Piの場合はデーモンとしてインストールされるので
インストールしたら以降Raspberry Piを起動すると自動的にWindowsでいうところの「mongod」が起動した状態となり「mongod」起動の操作は不要です。
その他はPCと特に変わりません。

無事Raspberry Piで実行できたらしばらく起動しっぱなしにして
価格データを収集してみましょう。

起動しっぱなしにする際は
Pythonで株価アラートをつくる(4) - てけとーぶろぐ。
で紹介したバックグラウンドでの実行を使ってください。

また長時間起動しっぱなしにしてみると
例えば取引所のシステムメンテナンスが入って
エラーが起きて停止してしまう
といったことも起こることが分かるかと思います。

エラーが起きて停止したことを知るために
Pythonで株価アラートをつくる(1) - てけとーぶろぐ。
でつくったメール通知も組み込むと簡単に停止を知ることができます。

CSVファイルへのエクスポート

価格データの書き込みや検索を行わず
単にある期間の価格データを読み込みたいだけといった用途には
価格データはDBに入っているよりもCSVファイルなどになっていたほうが扱いやすいということもありますね。
例えば価格の推移のグラフを描画するプログラムで価格データを使う場合などです。

MongoDBにはDB内のデータをCSVファイル等にエクスポートするツールが付属しています。

例としてcoinデータベースのtickerコレクションの各フィールドをticker.csvとしてMongoDBのインストール先のディレクトリー(binディレクトリーの親ディレクトリー)に出力してみましょう。

> cd C:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.7\bin
> mongoexport --db coin --collection ticker --type=csv --fields _id,ask,bid,high,last,low,symbol,timestamp,volume --out ../ticker.csv

Raspberry Piの場合はMongoDB 2.4でオプションが少し異なり「--type=csv」ではなく「--csv」になります。

$ mongoexport --db coin --collection ticker --csv --fields _id,ask,bid,high,last,low,symbol,timestamp,volume --out ticker.csv

サンプルとして何日間か分のビットコインの価格をエクスポートしたCSVを以下にアップロードしました。
ticker_20200514.zip

次回は収集した価格データをグラフ化して分析し、自動売買のアルゴリズムを考えてみたいと思います。