前回の記事で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 はしておきましょう。
[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にアクセスしてみてください。
アクセスした画面は以下。
だいたい同じ時間を 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だと綺麗に出ますがスマホだとグラフが小さくて見づらい、、笑
とりあえず今回はここまで。
スマホで綺麗に見たい場合は、とりあえず以下の単独画面で見てみてください。。
コメント