前回の記事でWordPress(Gutenberg)にChart.jsでcsvファイルから読み出したデータでグラフを表示するやり方はわかりました。
今回はbitcoinの価格データをDB(sqlite3)に入れて、DBから読み出したデータでグラフを表示しようと思います。
bitcoin の価格を取得して sqlite3 に入れる
bitcoin の取引所などから API で bitcoin の価格が取得できるようです。
今後、bitcoin 以外も取得したいので、さまざまな仮想通貨の情報を取得できる CoinGecko のAPIを使ってみようと思います。
まずはいつものように CoinGecko の API を使って情報を取得してるブログを探してみて、以下を参考にさせて頂きました。

上記のページでは「/coins/{id}/market_chart」のAPIを使ってますが、試してみると1日分を指定しても凄い大量に応答が返ってきます。
APIの説明ページを見てみると、1日は分毎のデータで、2日から90日までは時間毎のデータ、90日より前は日毎のデータみたいで変更できなさそう。。
---
Get historical market data include price, market cap, and 24h volume (granularity auto)
Minutely data will be used for duration within 1 day, Hourly data will be used for duration between 1 day and 90 days, Daily data will be used for duration above 90 days.
---
他にいいAPI無いかな?と見てたら「/coins/{id}/ohlc Get coin's OHLC (Beta)」が使えそう。
1~2日は30分毎、3~30日は4時間毎、31日以前は4日毎だそうです。
OHLCって何かな?と思ったら open、high、low、close の頭文字で、いわゆるローソク足のグラフ向けのデータみたい。
検索するとローソク足を表示できるものもありそうですが、とりあえずこのデータを使って1日分の30分毎のグラフを作ってみようと思います!
長くなりそうなので端折って行きます。笑
まず、python で上記の API でデータを取得するために、requests のライブラリが必要だったので、追加しました。
ちなみに以下の記事の後半でやってるように、pip の upgrade はしておきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [cuzuser@xxxx work]$ python3 -m pip install requests --user Collecting requests Downloading requests-2.25.1-py2.py3-none-any.whl (61 kB) |################################| 61 kB 6.7 MB/s Collecting certifi>=2017.4.17 Downloading certifi-2020.12.5-py2.py3-none-any.whl (147 kB) |################################| 147 kB 15.0 MB/s Collecting chardet<5,>=3.0.2 Downloading chardet-4.0.0-py2.py3-none-any.whl (178 kB) |################################| 178 kB 26.2 MB/s Collecting idna<3,>=2.5 Downloading idna-2.10-py2.py3-none-any.whl (58 kB) |################################| 58 kB 16.4 MB/s Collecting urllib3<1.27,>=1.21.1 Downloading urllib3-1.26.2-py2.py3-none-any.whl (136 kB) |################################| 136 kB 70.9 MB/s Installing collected packages: urllib3, idna, chardet, certifi, requests Successfully installed certifi-2020.12.5 chardet-4.0.0 idna-2.10 requests-2.25.1 urllib3-1.26.2 [cuzuser@xxxx work]$ |
先ほどのページを参考に、CoinGecko から API で情報収集して、とりあえず画面にテキストで出力する python プログラムを作ってみました。
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 | #!/usr/local/bin/python3 import requests import json from datetime import datetime import pandas as pd def get_btcprice(ticker, term): url = ('https://api.coingecko.com/api/v3/coins/') + ticker + ('/ohlc?vs_currency=jpy&days=') + term r = requests.get(url) r2 = json.loads(r.text) return r2 def get_price(r2): s = pd.DataFrame(r2) s.columns = ['date', 'price_open', 'price_high', 'price_low', 'price_close'] date = [] for i in s['date']: tsdate = int(i / 1000) loc = datetime.fromtimestamp(tsdate) date.append(loc) s.index = date del s['date'] return s r2 = get_btcprice('bitcoin', '1') btcprice = get_price(r2) print(btcprice) |
実行結果はこんな感じでちゃんと取れてそうです。
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 | [cuzuser@xxxx work]$ ./gecko.py price_open price_high price_low price_close 2021-01-22 22:00:00 3478907.27 3492097.88 3453620.74 3453620.74 2021-01-22 22:30:00 3459027.12 3486174.78 3459027.12 3479827.89 2021-01-22 23:00:00 3479383.54 3479383.54 3411854.71 3411854.71 2021-01-22 23:30:00 3407820.82 3427693.41 3407820.82 3427693.41 2021-01-23 00:00:00 3441108.35 3441108.35 3397854.29 3420536.19 2021-01-23 00:30:00 3411120.50 3411120.50 3363814.75 3363814.75 2021-01-23 01:00:00 3381304.81 3396146.55 3372626.85 3396146.55 2021-01-23 01:30:00 3398636.34 3398636.34 3358219.53 3370718.57 2021-01-23 02:00:00 3381817.55 3413416.91 3381817.55 3393976.54 2021-01-23 02:30:00 3396079.36 3404214.91 3360817.24 3360817.24 2021-01-23 03:00:00 3345125.13 3361533.55 3345125.13 3361533.55 2021-01-23 03:30:00 3357031.99 3376646.12 3357031.99 3372977.75 2021-01-23 04:00:00 3366063.48 3382121.72 3365678.60 3365678.60 2021-01-23 04:30:00 3360260.39 3410476.09 3360260.39 3410476.09 2021-01-23 05:00:00 3405873.12 3405873.12 3384990.54 3387011.94 2021-01-23 05:30:00 3380913.73 3385691.36 3362154.28 3362154.28 2021-01-23 06:00:00 3367143.22 3445430.49 3367143.22 3441991.63 2021-01-23 06:30:00 3453392.11 3458894.40 3443273.59 3443273.59 2021-01-23 07:00:00 3434881.98 3442235.99 3430887.58 3442235.99 2021-01-23 07:30:00 3417291.75 3425418.35 3411974.38 3425418.35 2021-01-23 08:00:00 3428328.42 3428328.42 3401333.08 3414232.60 2021-01-23 08:30:00 3415422.42 3416387.29 3390500.09 3416387.29 2021-01-23 09:00:00 3415637.98 3419667.20 3394640.85 3398302.69 2021-01-23 09:30:00 3432397.03 3432397.03 3403574.75 3403574.75 2021-01-23 10:00:00 3390670.90 3392741.54 3381762.34 3392741.54 2021-01-23 10:30:00 3385800.15 3385800.15 3356133.32 3356133.32 2021-01-23 11:00:00 3354489.54 3360204.44 3352518.53 3360204.44 2021-01-23 11:30:00 3357091.41 3370337.17 3294491.89 3304442.44 2021-01-23 12:00:00 3292916.05 3307309.61 3292916.05 3294086.51 2021-01-23 12:30:00 3285005.57 3318752.22 3285005.57 3300960.53 2021-01-23 13:00:00 3299347.04 3306680.51 3293106.64 3293106.64 2021-01-23 13:30:00 3276328.73 3317252.01 3267209.06 3317252.01 2021-01-23 14:00:00 3320924.74 3340155.41 3309355.90 3309355.90 2021-01-23 14:30:00 3303990.33 3306995.63 3299168.53 3306995.63 2021-01-23 15:00:00 3308598.79 3314262.72 3297509.70 3297509.70 2021-01-23 15:30:00 3299643.48 3333333.18 3299643.48 3333333.18 2021-01-23 16:00:00 3332277.77 3332277.77 3314959.51 3315480.34 2021-01-23 16:30:00 3307197.46 3329413.54 3306750.74 3329413.54 2021-01-23 17:00:00 3339897.72 3348581.95 3334516.87 3338368.51 2021-01-23 17:30:00 3339276.57 3339276.57 3331279.00 3331279.00 2021-01-23 18:00:00 3333987.91 3356930.26 3333987.91 3345663.54 2021-01-23 18:30:00 3348547.64 3348547.64 3335520.40 3337053.54 2021-01-23 19:00:00 3313184.87 3339111.12 3313184.87 3339111.12 2021-01-23 19:30:00 3341942.72 3356016.04 3341942.72 3356016.04 2021-01-23 20:00:00 3354772.32 3371301.31 3351062.60 3362692.04 2021-01-23 20:30:00 3358450.32 3358450.32 3339890.84 3342168.38 2021-01-23 21:00:00 3344790.37 3344790.37 3330416.14 3338902.22 2021-01-23 21:30:00 3340330.11 3347696.85 3333560.47 3347696.85 [cuzuser@xxxx work]$ |
さて、次は python からどうやって、sqlite3 に入れるか。
今度はこのページを参考にさせてもらいました。
python を1行づつ入力して動かすモードは使ったことが無かったですが、試すと簡単なので、先に動きを確認するのに便利ですね。
あと、びっくりしたのが、sqlite3 で先に DBのファイルは作成しないといけないのですが、python で pandas というモジュールを使うと、DBにテーブルが無くてもインサートできてしまうようです。
ただ、sqlite3 で テーブルを作らないとDBファイルができなかったので、以下ではまず sample.db というファイルを作って test というテーブルを作って保存してます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | [cuzuser@xxxx work]$ pwd /virtual/cuzuser/public_html/test2.teqnobreaker.com/work [cuzuser@xxxx work]$ sqlite3 sample.db SQLite version 3.7.17 2013-05-20 00:56:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> create table test( ...> id integer, ...> name varchar(50), ...> price integer ...> ); sqlite> .exit [cuzuser@xxxx work]$ |
以下は、python3 の対話モードで sqlite3 の sample.db に接続して testテーブルにデータをインサート。その後、読み出して確認してます。
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 | [cuzuser@xxxx work]$ python3 Python 3.6.8 (default, Jun 6 2019, 03:30:49) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sqlite3 >>> import pandas as pd >>> con = sqlite3.connect('sample.db') >>> pd.io.sql.read_sql_query('select * from {table}'.format(table='test'), con) Empty DataFrame Columns: [id, name, price] Index: [] >>> df = pd.DataFrame(data=[(1, 'jiro', 5000), (2, 'goro', 8000)], columns=['id', 'name', 'price']) >>> df id name price 0 1 jiro 5000 1 2 goro 8000 >>> df.to_sql('{table}'.format(table='test'), con, index=False, if_exists='replace') >>> pd.io.sql.read_sql_query('select * from {table}'.format(table='test'), con) id name price 0 1 jiro 5000 1 2 goro 8000 >>> df.to_sql('{table}'.format(table='test'), con, if_exists='replace') >>> pd.io.sql.read_sql_query('select * from {table}'.format(table='test'), con) index id name price 0 0 1 jiro 5000 1 1 2 goro 8000 >>> quit() [cuzuser@xxxx work]$ |
念のために sqlite3 で接続してデータが入ったことを確認してみます。
1 2 3 4 5 6 7 8 9 10 11 | [cuzuser@xxxx work]$ sqlite3 sample.db SQLite version 3.7.17 2013-05-20 00:56:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .tables test sqlite> select * from test; 0|1|jiro|5000 1|2|goro|8000 sqlite> .exit [cuzuser@xxxx work]$ |
それでは、CoinGecko から取ってきたデータを sqlite3 の sample.db の testテーブルに入れてみましょう。
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 | #!/usr/local/bin/python3 import sqlite3 import requests import json from datetime import datetime import pandas as pd def get_btcprice(ticker, term): url = ('https://api.coingecko.com/api/v3/coins/') + ticker + ('/ohlc?vs_currency=jpy&days=') + term r = requests.get(url) r2 = json.loads(r.text) return r2 def get_price(r2): s = pd.DataFrame(r2) s.columns = ['date', 'price_open', 'price_high', 'price_low', 'price_close'] date = [] for i in s['date']: tsdate = int(i / 1000) loc = datetime.fromtimestamp(tsdate) date.append(loc) s.index = date del s['date'] return s r2 = get_btcprice('bitcoin', '1') btcprice = get_price(r2) con = sqlite3.connect('sample.db') btcprice.to_sql('{table}'.format(table='test'), con, if_exists='replace') |
上記の python を起動してみた後で sqlite3 に繋いでデータがどうなったか見てみましょう。
出力は省略しましたが、ちゃんとテーブルにデータが設定されてました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [cuzuser@xxxx work]$ ./gecko2.py [cuzuser@xxxx work]$ sqlite3 sample.db SQLite version 3.7.17 2013-05-20 00:56:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .tables test sqlite> select * from test; 2021-01-23 16:00:00|3314959.51|3315480.34|3314959.51|3315480.34 2021-01-23 16:30:00|3307197.46|3329413.54|3306750.74|3329413.54 :(省略) 2021-01-24 15:30:00|3328383.25|3336944.28|3328383.25|3336944.28 2021-01-24 16:00:00|3331589.43|3344707.3|3331589.43|3341818.95 sqlite> .exit [cuzuser@xxxx work]$ |
sqlite3 からデータを読み出して Chart.js で表示
最初は javascript で sqlite3 から読み出して、Chart.js に設定して表示することを考えてましたが、javascript で sqlite3 からデータを読み出すやり方は無いのか、検索してもほとんど出て来ないし、出てきた記事見ても良くわかりませんでした。笑
どうしょうかと思ったら、php で最初に sqlite3 から情報を取得し変数に成形しておいて、HTMLの<script> の中で取得した情報を張り付けると良いようでした。
php は詳しく無いのでいろいろ上手くいかず紆余曲折しましたが、いろんなページのサンプルなどを参考になんとか出ました。
いろんなページを参考にしながら作ったのでコピー元の記事は特に無しです。
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 | <?php $db = new SQLite3('sample.db'); $data = $db->query('SELECT * FROM test'); $date = ''; $price = ''; while ($r = $data->fetchArray()) { $date = $date . '"'.$r[0].'",'; $price = $price . '"'.$r[1].'",'; } $date = trim($date,","); $price = trim($price,","); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name=”robots” content=”noindex”> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script> </head> <body> <div class="chart-container" style="position: relative; width: 100%; height: 95vh;"> <canvas id="myChart">ここにチャート表示</canvas> </div> <script> var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'line', data: { labels: [<?php echo $date ?>], datasets:[{ label: 'bitcoin(円)', data: [<?php echo $price ?>], borderColor: "rgba(50,205,50,0.8)", backgroundColor: "rgba(50,255,50,0.8)", fill: false, lineTension: 0, }] } }); </script> </body> </html> |
試しに上記を単体のページで確認する場合は以下のURLにアクセスしてみてください。

アクセスした画面は以下。

だいたい同じ時間を coincheck で見た画面は以下。

coincheck はローソク足なので雰囲気は違いますが、日時や値はあってそうです。
CoinGecko から情報収集してDBに入れるプログラムを cron で定期的に行えば最新のグラフが見れるようになりますね。
最後に前回のようにグラフ表示の php を iframe で記事に「カスタムHTML」で埋め込んでみます。
1 2 3 | <div class="iframe-wrap"> <iframe src="https://test2.teqnobreaker.com/work/graph7.php" frameborder="0"></iframe> </div> |
実際に埋め込んだのが以下です。
うーん、PCだと綺麗に出ますがスマホだとグラフが小さくて見づらい、、笑
とりあえず今回はここまで。
スマホで綺麗に見たい場合は、とりあえず以下の単独画面で見てみてください。。






コメント