bitFlyerのticker情報をInfluxDBに入れてGrafanaで可視化する
概要
前回はビットコインのデータをバルクで配布しているサイトから直接ダウンロードして可視化しましたが、今回は自分でデータを取ってきて蓄積し、可視化までの流れをやってみたいと思います。
色々と方法はあると思いますが、せっかくなので自身の勉強のためにも、今回は時系列DBとして有名なInfluxDBをデータベースとして、可視化には相性の良いGrafanaを選択しました。取得するデータはbitFlyerのtickerの情報です。API経由でask/bidの価格や量などの情報を取得することができます(link)。
方法
環境
- macOS El capitan 10.11.6
- InfluxDB v1.0.0
- Grafana Version 3.1.1
InfluxDBを導入する
ここではインストールの具体的な手順は詳細は割愛します。MacならHomeBrewで入りますし、Linuxも公式ウェブサイトからパッケージをダウンロードして展開するだけでインストール自体は完了します。
さて、InfluxDBが使えるようになったところで、データを投入する前に一通り設定をしておきましょう。ウェブのQuery実行画面(http://localhost:8083/)で以下のSQLを実行し、root/rootのユーザと、bitcoinという名前のデータベースを作成しておきます。CLIから実行しても問題ありません。
CREATE USER "root" WITH PASSWORD 'root' CREATE DATABASE "bitcoin"
pythonからInfluxDBへデータを投入する
さて、データベースの準備が一通り整ったので、InfluxDBへデータを投入していきます。InfluxDBにはPythonのクライアントがあるので、今回はそれを利用します。
また、bitFlyerからのデータ取得は、拙作のpybitflyerを利用しています。本来ならばInfluxdbはRESTful APIによるデータ投入ができるので、bitFlyerのWebAPIから直接流すという選択肢もあるのですが、データの加工やカラム追加が容易という理由で、一度Pythonで処理するという形を取っています。
from influxdb import InfluxDBClient import pybitflyer api = pybitflyer.API(api_key="XXX...", api_secret="YYY...") ticker = api.ticker(product_code="BTC_JPY") user = 'root' password = 'root' dbname = 'bitcoin' json_body = [ { "measurement": "bf_ticker", "fields":ticker } ] client = InfluxDBClient("localhost", "8086", user, password, dbname) client.write_points(json_body)
bitFlyer Lightning APIから取得したデータをticker
変数に入れています。それをデータ投入用のjson_body
に含め、client.write_points()
にてデータベースへ書き込んでいます。measurement
はMySQLなどで言うところのテーブルに相当するもので、bitcoinというデータベース内に作成されます。他にも書き込む内容としてtagsやtimeなどの情報を加えることができますが、ここでは指定していません。
きちんとデータが格納されているか確認してみましょう。InfluxDBのウェブページでデータベースをbitcoinに設定したうえでselect * from bf_ticker
で問い合わせて、何かしらデータが表示されていれば問題ありません。レスポンスが{"results":[{}]}
でなかったらとりあえずは大丈夫でしょう。なお、この確認作業は以下のようにHTTP APIからでも実行可能です。
$ curl "http://localhost:8086/query?q=select+*+from+bf_ticker&db=bitcoin" | jq { "results": [ { "series": [ { "name": "bf_ticker", "columns": [ "time", "best_ask", "best_ask_size", "best_bid", "best_bid_size", "ltp", "pair", "product_code", "tick_id", "timestamp", "total_ask_depth", "total_bid_depth", "volume", "volume_by_product" ], [...]
これで上記スクリプトを実行したタイミングでのデータ投入が完了しました。あとは、このコードを定期的に動かすことで、ask/bidの価格を時系列で眺めたり、値を可視化することができます。
定期実行の方法としては、定番のcrontabや、最近出てきたジョブ管理ツールであるJenkins、Luigi、Azkabanなどがあります。試しに動かすだけならwhile True:
の中で上記スクリプトを動かしつつtime.sleep(30)
などで定期実行するのもアリですね。
Grafanaで可視化
それでは最後に、Grafanaを使ってInfluxDBからデータを取り出し可視化します。なお、InfluxDBと同じようにインストールの方法はここでは割愛します。
まずはDataSourcesでInfluxDBの接続設定をします。画面に表示されているTypeからInfluxDBを選択して、Http SettingsのURL、InfluxDB DetailsのDatabaseとUser、Passwordをそれぞれ入力します。これで、ダッシュボードからInfluxDBの対象データベースを選択して情報を取得することができます。
あとはDashboardで新規作成し、可視化したいパネルを作成していきます。今回はbitFlyerのtickerに含まれるbest_ask、best_bid、ltpの3種類の情報をグラフで表示させます。ADD ROWののちに左端に少し出ている緑色のハンバーガーメニューからAdd panel→Graphを選択し、Metricsを以下のように設定します。
- Metrics:SQL:
SELECT best_bid,ltp,best_ask FROM bf_ticker
- Metrics:Panel Data Source: InfluxDB(上記で接続設定をしたものです)
これでbitFlyerのask/bidなどの価格情報を可視化することができました!他にも生のデータを表示するTableを表示させて、一旦は以下のような形になりました。
まとめ
簡単にではありますが、InfluxDB/Grafanaを使ったデータ取得/蓄積/可視化を一通りやってみました。InfluxDB/GrafanaはSQLによる集計機能も充実しているので、あとは移動平均線を書いたり、取引量を一緒に可視化してみたり、まだまだ出来ることがいっぱいあります。単体の情報量であったり情報スピードなどは本家のトレード画面に劣るものの、複数のデータソースを一度に可視化できたりとカスタマイズできるのはかなり強力です。自分もこれから色々と試してみようと思います。
参考
- InfluxData | Documentation | InfluxDB Version 1.0 Documentation
- influxdata/influxdb-python: Python client for InfluxDB
- InfluxDBとGrafanaを使ってサーバーリソースの可視化をする - Qiita
- GrafanaとInfluxDBでネットワークリソースの視覚化 - Qiita
- InfluxDB の概要 - sonots #tokyoinfluxdb
補足ですが、InfluxDBは最近メジャーバージョンアップにより1.0.0となったことで、テーブル作成等のRESTful API部分の仕様がガラッと変わっています。qiitaや各種ブログ等の記事は0.9未満のものが多く、そのままでは動かないコード/クエリがありますので、実行する前にはバージョンの確認をしたほうが良いでしょう。
Bitcoinchartsでbitcoinの過去の取引履歴を取得し可視化する
今回はbitcoinの取引所での取引履歴のデータを取得してみます。
前回bitFlyer LightningのAPIを使えるパッケージを作った時のように、各取引所が公開しているデータや提供しているAPI等がありますが、今回はBitcoinchartsから取得してみます。Bitcoinchartsは各取引所の各通貨のデータを収集、可視化しているウェブサイトで、そこで利用しているデータも公開しています。
データ取得
WebAPIから取得する
1つ目の方法として、URLを叩いてWebAPIから取得する方法があります。データを取得するには、以下のURLにアクセスするだけです。SYMBOL
の所には取得したい取引所&通貨の情報を指定します。取得対象とするデータの開始日をあわらすstart=UNIXTIME
は必須ではありません。
- http://api.bitcoincharts.com/v1/trades.csv?symbol=SYMBOL[&start=UNIXTIME]
例えば、coinckeckのBTC/JPYの場合はcoincheckJPY
なので、http://api.bitcoincharts.com/v1/trades.csv?symbol=coincheckJPY にアクセスすればいいわけです。すると、以下のように生のcsv形式でデータが表示されるので、ブラウザのダウンロード等を利用して保存することができます。
もちろん、次のようにcURLやwgetのようにコマンドラインからURLを指定してダウンロードすることもできます。
$ wget "http://api.bitcoincharts.com/v1/trades.csv?symbol=coincheckJPY"
最新の情報のみを取得したい時などは、WebAPI形式での取得が簡単です。
csv形式で直にデータを取得する
2つ目の方法として、Bitcoinchartsが所有するすべてのデータを一度に取得する方法もあります。以下のURLにアクセスすると、様々な取引所と通貨の取引履歴がリストアップされており、データを選択して保存、ローカルで解凍することで簡単にデータを手に入れることができます。なかにはそもそもデータの無いものやMt.Goxのように取引所が閉鎖され更新が止まっているものなどもありますので、データの最終更新日やファイルサイズを確認した上で、データを利用したほうが良さそうです。
btc/jpyに関しては以下の5つがあります。
- anxhkJPY.csv.gz
- ANX INTERNATIONAL
- 最終取引履歴日:2015/10/10
- btcexJPY.csv.gz
- BTCex - Bitcoin Wiki
- 最終取引履歴日:2011/03/06
- coincheckJPY.csv.gz
- Coincheck(コインチェック)
- 最終取引履歴日:2016/09/04(データ取得日)
- mtgoxJPY.csv.gz
- マウントゴックス - Wikipedia
- 最終取引履歴日:2014/02/25
- ruxumJPY.csv.gz
- Ruxum - Bitcoin Wiki
- 最終取引履歴日:2011/10/19
- thJPY.csv.gz
- ?
- データ無し
これを見ると、正常にデータ取得ができていて継続的に利用できるのはcoincheckのみのようですね。
データ形式
さて、実際に中身を見てみましょう。
1472948762,62163.000000000000,0.251085070000
データはcsv形式で保存されており、各カラムは以下の情報を表しています。
- 1カラム目:時刻 (unixtime)
- 2カラム目:価格 (price)
- 3カラム目:取引量 (amount)
なので、この取引は2016/09/04 09:26:02に0.251085070000 btcを62163 btc/jpyで取引されたということを表しています。
取引値を可視化
さて、最後に取得したデータを可視化してみましょう。今回は、WebAPI形式で取得したデータを可視化してみます。可視化にはPythonのpandas&matplotlibを使用し、データはWebAPI経由での過去5日分のデータを使用しています。
import pandas as pd from datetime import datetime df = pd.read_csv("http://api.bitcoincharts.com/v1/trades.csv?symbol=coincheckJPY", header=None, parse_dates=True, date_parser=lambda x: datetime.fromtimestamp(float(x)), index_col='datetime', names=['datetime', 'price', 'amount']) df["price"].plot()
すると、以下のような取引値の変動を可視化することができます。2016/9/4午前に起きた価格高騰の様子がよく分かりますね……。
なお、上記コードをJupyter notebookで動かしたものをgistでも公開していますので、参考下さい。
参考
bitFlyer LightningのAPIをPythonから使えるパッケージ「pybitflyer」を作りました
最近ようやく重い腰をあげてBitcoinに入門しました。最初はBlockchainの仕組みなどを"Mastering Bitcoin"で学んでいたのですが、実際に取引してみないとピンと来ないということで、bitFlyerという取引所に口座を開設し、日本円をBitcoinに換金して遊ぶことに。
素人が売り買いをして価値がだんだん下がっていく数字を見ながら悲しんでいたのですが、そうなるとエンジニアとしてはシステムトレードがしたくなるのが世の常です(?)。幸いにもbitFlyerには、HTTP APIというURLを叩くことで情報を得たり取引をしたりできるシステムがあるではありませんか。しかしながらその仕組みは複雑で、セキュリティのための暗号化が必要だったり、HTTP APIで返ってくるものを処理したりと、そのまま扱うには何かと大変です。
そこで、bitFlyerのREST APIをPythonから気軽に利用することができるラッパーを作成しました。
まだまだ作りかけでテストすらきちんとできていない状態ですが、一通り動くことが確認できたので公開してみました。
インストール
パッケージはPyPIに登録しているので、pipでインストールすることができます。現在のバージョンは0.1.0です。
$ pip install pybitflyer
使い方
使いはじめる前に
まずま何よりbitFlyerのアカウントが必要ですので、作成します。
PythonのようなプログラムからbitFlyer Lightningを操作する際には、ログイン時に使用するようなメールアドレスとパスワードでははく、専用のAPI KeyとAPI Secretという2つの情報が必要です。これらは、bitFlyer Lightningの設定ページから作成することができるので、利用する前に作っておきましょう。
詳しくはAPI Documentationを参照ください。
これで準備は万全です!
基本的な使い方
まずはpybitflyerをインポートして、HTTP APIのインスタンスを作成します。この際に上で取得したAPI KyeとAPI Secretを指定します(以下のコード例では...
で埋めているので適宜置き換えて下さい)。
import pybitflyer api = pybitflyer.API(api_key="...", api_secret="...")
なお、板情報や取引所の状態などはAPI KEYを必要としないため、pybitflyer.API()
だけで取得することができます。
板情報を取得する
まずは下記のように、BTC_JPYを指定して情報を取得します。
board = api.board(product_code="BTC_JPY")
すると、以下のように辞書形式でasks(買値), bids(売値), mid_price(中間価格)という3つの情報を取得することができます(asksとbidsの途中を省略しています)。こういった取得できる情報はすべてAPI Documentationの「レスポンス」という箇所に記載されているので、利用する際はそちらと照らしあわせてみてください。
{'asks': [{'price': 58372.0, 'size': 1.0}, {'price': 58373.0, 'size': 0.5}, {'price': 58382.0, 'size': 2.0}, ... {'price': 717600.0, 'size': 0.001}], 'bids': [{'price': 58357.0, 'size': 6.3}, {'price': 58356.0, 'size': 6.475}, ... {'price': 5754.0, 'size': 0.001}], 'mid_price': 58364.0}
試しに少しデータをいじってみましょう。例えば買値の最小値と最大値を出したいときには、以下のようにasksの中のすべてのpriceを取り出してminとmaxで値を取り出せばよいというわけですね。
In [13]: min([p["price"] for p in board["asks"]]) Out[13]: 58372.0 In [14]: max([p["price"] for p in board["asks"]]) Out[14]: 717600.0
他にも幾つか機能を見てみましょう。
Tickerを取得する
次に、Tickerの情報も取得してみましょう。先ほどの板情報と同じように、今度は.ticker()
というメソッドを使用します。
ticker = api.ticker(product_code="BTC_JPY")
すると、以下のようなデータがレスポンスとして返ってきます。
{'best_ask': 58372.0, 'best_ask_size': 1.0, 'best_bid': 58357.0, 'best_bid_size': 5.0, 'ltp': 58357.0, 'product_code': 'BTC_JPY', 'tick_id': 1215580, 'timestamp': '2016-08-28T12:01:32.367', 'total_ask_depth': 2238.88215243, 'total_bid_depth': 2414.34489585, 'volume': 42780.14047168, 'volume_by_product': 17621.67437353}
新規注文を出す
それでは肝心の売買の注文を出してみましょう。なお、このHTTP APIはPrivateと呼ばれ、API KeyとAPI Secretを取得してインスタンス時に作成しておくことが必要ですのでご注意ください。
buy_btc = api.sendchildorder(product_code="BTC_JPY", child_order_type="MARKET", side="BUY", size=0.001, minute_to_expire=10000, time_in_force="GTC" )
product_code
は注文するプロダクトを指定します。BTC_JPYやFX_BTC_JPY、またはETH_BTCを選択します。
child_order_type
は注文のタイプで、指値注文なら"LIMIT"、成行注文なら"MARKET"を指定します。
side
には売り買いを"SELL"か"BUY"で、sizeに取引額を指定します。
なお、minute_to_expireやtime_in_forceは必須ではありません。
新規注文の確認
さて、先ほどの注文は無事に完了したでしょうか?buy_btcに以下のような情報が入って入れば取引成功です。
{'child_order_acceptance_id': 'JRF20160828-121631-076088'}
実際にbitFlyer Lightningでも以下のように確かめることができます。
他にできること
このpybitflyerパッケージはbitFlyerが提供しているHTTP APIを使いやすくしたWrapperですので、できることはすべてHTTP APIに準拠します。bitFlyerでは以下のHTTP APIの機能が提供されています。
- 基本情報
- 板情報
- Ticker
- 約定履歴
- 取引所の状態
- チャット
- API
- API キーの権限を取得
- 資産
- 資産残高を取得
- 証拠金の状態を取得
- 入出金
- トレード
- 新規注文を出す
- 注文をキャンセルする
- 新規の親注文を出す(特殊注文)
- 親注文をキャンセルする
- すべての注文をキャンセルする
- 注文の一覧を取得
- 親注文の一覧を取得
- 親注文の詳細を取得
- 約定の一覧を取得
- 建玉の一覧を取得
(https://lightning.bitflyer.jp/docsより)
ウェブページからできることは大抵できるようになっているのではないでしょうか?中には「銀行口座一覧取得」なんてものもあります。このpybitflyerを作っている最中に試してみたのですが、本当に私が登録している銀行の名前や口座番号がレスポンスで返ってきて、少しびっくりしました……。
この記事でご紹介できた機能はほんの一部ですので、ぜひともbitFlyer Lightningの色々な機能を使ってみてください。