ビットコインの価格情報を取得するシェルを実装してみた
ビットコインのTicker情報を取得する
プログラムって前に作ってなかったっけ?
というツッコミを頂いた方、
本当にありがとうございます。
実は以前Pythonで同じようなものを実装しました。
↓以前の記事
ビットコインTicker情報を取得するプログラムをPythonで作ったよ
今回はCakePHP3を使って同じようなものを作ってみました。
なぜ今回わざわざCakePHP3を使って
実装したのかといいますと、
取得したTicker情報を表示させる
システムを作りたい
(価格情報をグラフで表示させたい)
ためです。
現在使用しているWEBサーバーは、
レンタルサーバーなのです。
Apache+MySQLという環境なのですが、
通常のよくあるレンタルサーバーなので
SSHでガリガリ環境構築とかができません。
レンタルサーバーでWEBシステム構築というと
やはりPHPがお手軽で便利なので
今回これに合わせて取得する方も
実装し直してみました。
CakePHPですが、以前は非常によく利用していました。
CakePHP 1.2とかの頃です。
CakePHP 2でも二つ、三つほどシステムを
実装したことがあります。
しかしそこからしばらく離れていて
気がつけばバージョン3が
リリースされているではありませんか。
これは試してみるしかない!
という単純な理由でCakePHP3での実装となりました。
早速CakePHP3のソースをダウンロードしてと、
ダウンロードを開いたところから面喰いました。
ダウンロードボタンをクリックしても
ダウンロードされないではありませんか。
で、そのページに記載されている内容を
読んでみるとcomposerを使えと書かれています。
ん?composer?
何それ?
という状態でした。
初めてさわるcomposerでしたが、
手順通りに進めると意外に
あっさりとインストールが完了しました。
データベースを作成して
config/app.php を作成して
tmpやlogsフォルダの権限を変更すれば
設定は完了です。
さすがはCakePHPです。
この辺の手軽さは相変わらずでした。
テーブルを作成する
最初に、取得したTicker情報を
保存するテーブルを作成します。
各ビットコイン取引所ごとに
1テーブルずつ用意します。
各ビットコイン取引所のAPIから
返ってきた値をそのまま
DBに突っ込む形なので
テーブル構成はAPIの返り値に合わせています。
以下のSQLでテーブルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
CREATE TABLE bitflyers ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, product_code VARCHAR(10), timestamp datetime DEFAULT NULL, tick_id INT, best_bid DECIMAL(10.3), best_ask DECIMAL(10.3), best_bid_size DECIMAL(5.1), best_ask_size DECIMAL(5.1), total_bid_depth DECIMAL(15.8), total_ask_depth DECIMAL(15.8), ltp DECIMAL(10.1), volume DECIMAL(15.8), volume_by_product DECIMAL(15.8), created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE coinchecks ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, last DECIMAL(10.3), bid DECIMAL(10.3), ask DECIMAL(10.3), high DECIMAL(10.3), low DECIMAL(10.3), volume DECIMAL(13.8), timestamp datetime, created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE quoines ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, product_type VARCHAR(20), code VARCHAR(8), name VARCHAR(20), market_ask DECIMAL(10.3), market_bid DECIMAL(10.3), indicator smallint, currency VARCHAR(4), currency_pair_code VARCHAR(8), symbol VARCHAR(2), fiat_minimum_withdraw DECIMAL(10.3), pusher_channel VARCHAR(32), taker_fee DECIMAL(5.2), maker_fee DECIMAL(5.2), low_market_bid DECIMAL(10.3), high_market_ask DECIMAL(10.3), volume_24h DECIMAL(15.8), last_price_24h DECIMAL(10.3), last_traded_price DECIMAL(10.3), last_traded_quantity DECIMAL(12.8), quoted_currency VARCHAR(4), base_currency VARCHAR(4), exchange_rate DECIMAL(22.20), created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE zaifs ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, last DECIMAL(10.3), high DECIMAL(10.3), low DECIMAL(10.3), vwap DECIMAL(10.3), volume DECIMAL(15.8), bid DECIMAL(10.3), ask DECIMAL(10.3), created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE btcboxs ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, high DECIMAL(10.3), low DECIMAL(10.3), buy DECIMAL(10.3), sell DECIMAL(10.3), last DECIMAL(10.3), vol DECIMAL(15.8), created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE krakens ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, buy DECIMAL(10.3), buy_size DECIMAL(8.3), sell DECIMAL(10.3), sell_size DECIMAL(8.3), last DECIMAL(10.3), last_size DECIMAL(8.3), vol DECIMAL(15.8), vol_24 DECIMAL(15.8), vwap DECIMAL(10.3), vwap_24 DECIMAL(10.3), low DECIMAL(10.3), low_24 DECIMAL(10.3), high DECIMAL(10.3), high_24 DECIMAL(10.3), open DECIMAL(10.3), created DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE bitbanks ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, sell DECIMAL(10.3), buy DECIMAL(10.3), high DECIMAL(10.3), low DECIMAL(10.3), last DECIMAL(10.3), vol DECIMAL(15.8), timestamp INT, created DATETIME DEFAULT CURRENT_TIMESTAMP ); |
Modelを焼く
テーブルを作成できたので
bakeでModelを焼けないか調べてみます。
するとやっぱりありました。
「bin/cake bake」で焼けるようです。
とりあえず「bin/cake bake」と打つと
以下のように表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
$ bin/cake bake Welcome to CakePHP v3.1.14 Console --------------------------------------------------------------- App : src Path: /home/hoge/src/ PHP : 5.4.16 --------------------------------------------------------------- The following commands can be used to generate skeleton code for your application. Available bake commands: - all - behavior - cell - component - controller - fixture - form - helper - mailer - migration - migration_diff - migration_snapshot - model - plugin - seed - shell - shell_helper - template - test By using `cake bake [name]` you can invoke a specific bake task. |
今回はモデルを作りたいので、
bin/cake bake model と打ちます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ bin/cake bake model Welcome to CakePHP v3.1.14 Console --------------------------------------------------------------- App : src Path: /home/hoge/src/ PHP : 5.4.16 --------------------------------------------------------------- Choose a model to bake from the following: - Bitbanks - Bitflyers - Btcboxs - Coinchecks - Krakens - Quoines - Zaifs |
bin/cake bake model [モデル名]
と打てばよいようです。
1 2 |
bin/cake bake model Bitbanks bin/cake bake model Bitflyers |
など、作成したテーブル分だけ実行します。
シェルの作成
モデルができたので、
次はシェルを作ります。
最初のひな型もbakeで作ります。
1 2 3 4 5 6 7 8 9 |
$ bin/cake bake shell Welcome to CakePHP v3.1.14 Console --------------------------------------------------------------- App : src Path: /home/hoge/src/ PHP : 5.4.16 --------------------------------------------------------------- Error: You must provide a name to bake a shell |
シェルを焼くときには、
シェルの名前を指定するようです。
1 |
$ bin/cake bake shell bitflyer |
とすれば、シェルファイルが自動で作成されます。
ソースを編集
bakeで焼いたソースは
srcフォルダ以下にあります。
bakeで焼いたシェルファイルを
落としてローカルで開きます。
で、以下のように各ビットコイン
取引所ごとに作成していきます。
bitFlyerの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Bitflyer shell command. */ class BitflyerShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Bitflyers'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://api.bitflyer.jp/v1/ticker?product_code=BTC_JPY"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $bitflyer = $this->Bitflyers->newEntity(); if (!empty($ticker)) { $bitflyer->product_code = $ticker->product_code; $bitflyer->timestamp = $ticker->timestamp; $bitflyer->tick_id = $ticker->tick_id; $bitflyer->best_bid = $ticker->best_bid; $bitflyer->best_ask = $ticker->best_ask; $bitflyer->best_bid_size = $ticker->best_bid_size; $bitflyer->best_ask_size = $ticker->best_ask_size; $bitflyer->total_bid_depth = $ticker->total_bid_depth; $bitflyer->total_ask_depth = $ticker->total_ask_depth; $bitflyer->ltp = $ticker->ltp; $bitflyer->volume = $ticker->volume; $bitflyer->volume_by_product = $ticker->volume_by_product; $bitflyer->created = date('Y-m-d H:i:s'); if ($this->Bitflyers->save($bitflyer)) { } else { $this->out("Error!"); } } } } |
coincheckの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Coincheck shell command. */ class CoincheckShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Coinchecks'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://coincheck.com/api/ticker"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $coincheck = $this->Coinchecks->newEntity(); if (!empty($ticker)) { $coincheck->last = $ticker->last; $coincheck->bid = $ticker->bid; $coincheck->ask = $ticker->ask; $coincheck->high = $ticker->high; $coincheck->low = $ticker->low; $coincheck->volume = $ticker->volume; $coincheck->timestamp = $ticker->timestamp; $coincheck->created = date('Y-m-d H:i:s'); if ($this->Coinchecks->save($coincheck)) { } else { $this->out("Error!"); } } } } |
QUOINEの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Quoine shell command. */ class QuoineShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Quoines'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://api.quoine.com/products/5"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $quoine = $this->Quoines->newEntity(); if (!empty($ticker)) { $quoine->product_type = $ticker->product_type; $quoine->code = $ticker->code; $quoine->name = $ticker->name; $quoine->market_ask = $ticker->market_ask; $quoine->market_bid = $ticker->market_bid; $quoine->indicator = $ticker->indicator; $quoine->currency = $ticker->currency; $quoine->currency_pair_code = $ticker->currency_pair_code; $quoine->symbol = $ticker->symbol; $quoine->fiat_minimum_withdraw = $ticker->fiat_minimum_withdraw; $quoine->pusher_channel = $ticker->pusher_channel; $quoine->taker_fee = $ticker->taker_fee; $quoine->maker_fee = $ticker->maker_fee; $quoine->low_market_bid = $ticker->low_market_bid; $quoine->high_market_ask = $ticker->high_market_ask; $quoine->volume_24h = $ticker->volume_24h; $quoine->last_price_24h = $ticker->last_price_24h; $quoine->last_traded_price = $ticker->last_traded_price; $quoine->last_traded_quantity = $ticker->last_traded_quantity; $quoine->quoted_currency = $ticker->quoted_currency; $quoine->base_currency = $ticker->base_currency; $quoine->exchange_rate = $ticker->exchange_rate; $quoine->created = date('Y-m-d H:i:s'); if ($this->Quoines->save($quoine)) { } else { $this->out("Error!"); } } } } |
Zaifの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Zaif shell command. */ class ZaifShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Zaifs'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://api.zaif.jp/api/1/ticker/btc_jpy"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $zaif = $this->Zaifs->newEntity(); if (!empty($ticker)) { $zaif->last = $ticker->last; $zaif->high = $ticker->high; $zaif->low = $ticker->low; $zaif->vwap = $ticker->vwap; $zaif->volume = $ticker->volume; $zaif->bid = $ticker->bid; $zaif->ask = $ticker->ask; $zaif->created = date('Y-m-d H:i:s'); if ($this->Zaifs->save($zaif)) { } else { $this->out("Error!"); } } } } |
BtcBoxの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Btcbox shell command. */ class BtcboxShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Btcboxs'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://www.btcbox.co.jp/api/v1/ticker/"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $btcbox = $this->Btcboxs->newEntity(); if (!empty($ticker)) { $btcbox->high = $ticker->high; $btcbox->low = $ticker->low; $btcbox->buy = $ticker->buy; $btcbox->sell = $ticker->sell; $btcbox->last = $ticker->last; $btcbox->vol = $ticker->vol; $btcbox->created = date('Y-m-d H:i:s'); if ($this->Btcboxs->save($btcbox)) { } else { $this->out("Error!"); } } } } |
Krakenの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Kraken shell command. */ class KrakenShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Krakens'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://api.kraken.com/0/public/Ticker?pair=XXBTZJPY"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); var_dump($ticker->result->XXBTZJPY); $kraken = $this->Krakens->newEntity(); if (!empty($ticker)) { $kraken->buy = $ticker->result->XXBTZJPY->a[0]; $kraken->buy_size = $ticker->result->XXBTZJPY->a[2]; $kraken->sell = $ticker->result->XXBTZJPY->b[0]; $kraken->sell_size = $ticker->result->XXBTZJPY->b[2]; $kraken->last = $ticker->result->XXBTZJPY->c[0]; $kraken->last_size = $ticker->result->XXBTZJPY->c[1]; $kraken->vol = $ticker->result->XXBTZJPY->v[0]; $kraken->vol_24 = $ticker->result->XXBTZJPY->v[1]; $kraken->vwap = $ticker->result->XXBTZJPY->p[0]; $kraken->vwap_24 = $ticker->result->XXBTZJPY->p[1]; $kraken->low = $ticker->result->XXBTZJPY->l[0]; $kraken->low_24 = $ticker->result->XXBTZJPY->l[1]; $kraken->high = $ticker->result->XXBTZJPY->h[0]; $kraken->high_24 = $ticker->result->XXBTZJPY->h[1]; $kraken->open = $ticker->result->XXBTZJPY->o; $kraken->created = date('Y-m-d H:i:s'); if ($this->Krakens->save($kraken)) { } else { $this->out("Error!"); } } } } |
Bitbankの情報取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php namespace App\Shell; use Cake\Console\Shell; /** * Bitbank shell command. */ class BitbankShell extends Shell { public function initialize() { parent::initialize(); $this->loadModel('Bitbanks'); } /** * main() method. * * @return bool|int Success or error code. */ public function main() { $url = "https://public.bitbank.cc/btc_jpy/ticker"; $conn = curl_init(); curl_setopt($conn, CURLOPT_RETURNTRANSFER, true); curl_setopt($conn, CURLOPT_URL, $url); $result = curl_exec($conn); curl_close($conn); $ticker = json_decode($result); $bitbank = $this->Bitbanks->newEntity(); if (!empty($ticker)) { $bitbank->sell = $ticker->data->sell; $bitbank->buy = $ticker->data->buy; $bitbank->high = $ticker->data->high; $bitbank->low = $ticker->data->low; $bitbank->last = $ticker->data->last; $bitbank->vol = $ticker->data->vol; $bitbank->timestamp = $ticker->data->timestamp; $bitbank->created = date('Y-m-d H:i:s'); if ($this->Bitbanks->save($bitbank)) { } else { $this->out("Error!"); } } } } |
以上で各ビットコイン取引所のTicker情報を
取得するシェルが完成しました。
シェルの実行
シェルを実行するには、以下のコマンドを実行します。
1 |
bin/cake kraken |
これで各シェルを定期的に実行すれば
各ビットコイン取引所のTicker情報を
DBに保存できます。