WordPress(Gutenberg)にChart.jsでbitcoinのグラフ表示(php,sqlite3,python3)

WordPress
記事内に自動で広告が表示されます

前回の記事でWordPress(Gutenberg)にChart.jsでcsvファイルから読み出したデータでグラフを表示するやり方はわかりました。
今回はbitcoinの価格データをDB(sqlite3)に入れて、DBから読み出したデータでグラフを表示しようと思います。

bitcoin の価格を取得して sqlite3 に入れる


bitcoin の取引所などから API で bitcoin の価格が取得できるようです。
今後、bitcoin 以外も取得したいので、さまざまな仮想通貨の情報を取得できる CoinGecko のAPIを使ってみようと思います。

まずはいつものように CoinGecko の API を使って情報を取得してるブログを探してみて、以下を参考にさせて頂きました。

【Python】CoinGeckoのAPIでビットコイン・アルトコインの価格データを取得する
こんにちは、ミナピピン(@python_mllover)です。最近仮想通貨BOTの作成にハマっており...続きを読む

上記のページでは「/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.
---

Most Comprehensive Cryptocurrency API | CoinGecko
Use our free cryptocurrency API to get data such a...続きを読む

他にいい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 はしておきましょう。

[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 プログラムを作ってみました。

#!/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)

実行結果はこんな感じでちゃんと取れてそうです。

[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 というテーブルを作って保存してます。

[cuzuser@xxxx work]$ pwd
/virtual/cuzuser/public_html/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テーブルにデータをインサート。その後、読み出して確認してます。

[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 で接続してデータが入ったことを確認してみます。

[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テーブルに入れてみましょう。

#!/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 に繋いでデータがどうなったか見てみましょう。
出力は省略しましたが、ちゃんとテーブルにデータが設定されてました。

[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 は詳しく無いのでいろいろ上手くいかず紆余曲折しましたが、いろんなページのサンプルなどを参考になんとか出ました。
いろんなページを参考にしながら作ったのでコピー元の記事は特に無しです。

<?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にアクセスしてみてください。

https://teqnobreaker.com/work/graph7.php
...続きを読む

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

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

coincheck はローソク足なので雰囲気は違いますが、日時や値はあってそうです。

CoinGecko から情報収集してDBに入れるプログラムを cron で定期的に行えば最新のグラフが見れるようになりますね。

最後に前回のようにグラフ表示の php を iframe で記事に「カスタムHTML」で埋め込んでみます。

<div class="iframe-wrap">
  <iframe src="https://teqnobreaker.com/work/graph7.php" frameborder="0"></iframe>
</div>

実際に埋め込んだのが以下です。
うーん、PCだと綺麗に出ますがスマホだとグラフが小さくて見づらい、、笑
とりあえず今回はここまで。

スマホで綺麗に見たい場合は、とりあえず以下の単独画面で見てみてください。。

https://teqnobreaker.com/work/graph7.php
...続きを読む

コメント

タイトルとURLをコピーしました