Bitcoinのリアルタイムチャート画像を返すAPIを作ってSlackでHubotに吐かせる

この記事は CAMPHOR- Advent Calendar 2015 20日目の記事です。
(CAMPHOR- についてはこちら https://camph.net/ )

こんにちは @morishin127 です。
近頃 CAMPHOR- メンバー間での割勘や立て替え時に Bitcoin を利用するのが流行っています。LINE Pay 的な使い方でしょうか。
自分でいくらかの Bitcoin を持つようになると日々変化するレートが気になるので時々ググってチャートを見たりしていたのですが、bot に話しかけてチャートが得られたら便利そうと思いチャート画像を返すAPIを作成しました。

bot

http://ticker.morishin.me/ https://ticker.arukascloud.io/ を叩けばリアルタイムのチャート画像が返ってきます。
?scale=15mで15分足、?scale=1dで1日足になったりします。(デフォルトは5分足)

リポジトリはこちらです。 github.com

Dockerリポジトリがあるので

docker pull morishin127/bitchart-api
docker run -itd -p 80:8080 morishin127/bitchart-api

で動かせると思います。

実装

使ったもの

  • Python 3
    • Bottle
    • pandas
    • matplotlib
  • Docker

レート情報の取得

Bitcoin のレートの取得にはcoincheckのAPIを使わせてもらってます。
https://coincheck.jp/api/ticker を叩くと下記の形式で現在時刻の価格情報が得られます。

{
  "last": 55621,
  "bid": 55694,
  "ask": 55715,
  "high": 56552,
  "low": 54927,
  "volume": "1835.34189941",
  "timestamp": 1450547505
}

この API を毎分叩いて DB に last の値を INSERT していきます。

pandas + matplotlib でチャートを描画

DB に INSERT するとともにその時点までのチャート画像を生成してファイルに保存しておきます。DB から SELECT したデータを pandas の DataFrame にし、 matplotlib の機能でロウソク足チャートを描画します。matplotlib.finance.candlestick_ohlc を利用しました。

ここまでの処理を一つのスクリプトにして crontab で毎分実行します。

チャート画像の配信

Bottle で Web サーバーを立ち上げてリクエストが来たらファイルに保存されている画像を返します。

Docker

これを適当なサーバーにDockerでドーンしてそこにticker.morishin.meドメインを振りました。
自分のサーバーに置いていたのは閉じて、さくらの Arukas に移行しました → https://ticker.arukascloud.io/
Arukas の設定はこんな感じで PORT=80 を指定したら起動できます。

Dockerfileはこんな感じです。

依存ライブラリとかよくわからなかったのでこちらを参考にさせていただきました🙏 fits.hatenablog.com

Docker を採用したのは手動での環境構築で挫折したからです... 自分で借りていた VPS (Debian) でサクッと動かそうとしたのですが virtualenv 上に matplotlib 等のライブラリをインストールするのに詰まって挫折してしまい、既に誰かが構築に成功している Dockerfile を使うのが楽なのではと思い Docker にしました。
ちなみにその Debian マシンに docker-engine をインストールするのにも詰まってしまい(ょゎぃ)、結局 DigitalOcean で Docker 環境がプリインストールされたインスタンスをポチって立ち上げました。
DigitalOcean の One-Click Apps めっちゃ便利やんけ...

Hubot

これで下記のような hubot script を書いておくとチャットで Hubot にチャートを返してもらうことができます。

module.exports = (robot) ->
  robot.hear /bitchart\s*(\d+[mhd])?/, (res) ->
    query = res.match[1] ? "5m"
    res.send "https://ticker.arukascloud.io/?scale=" + query

より詳しくはリポジトリをご覧ください。

明日はkeishakeの記事です。お楽しみに!