ビットコインの日足チャートをPythonとPlotlyでプロットしてみた

今回はPythonとPlotlyを使ってビットコインの日足チャートをプロットする方法についてまとめていきます。

## データ取得
ローソク足のデータはCryptowatのAPIを使って取得します。
取得の方法についての詳細は[APIドキュメント](https://docs.cryptowat.ch/rest-api/markets/ohlc)を参照してください。

```python
import requests
import json
import pandas as pd
# Bitflyerの円建てBTC価格を取得
res = requests.get('https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc')
data = json.loads(res.text)
# resultの下にある「86400」のキーが日足データ
daily_data = pd.DataFrame(data['result']['86400'], columns=['close_time', 'open_price', 'high_price', 'low_price', 'close_price', 'volume', 'quote_volume'])
daily_data.head()
```

```python:結果
   close_time  open_price  high_price  low_price  close_price  volume  quote_volume
0  1435276800       29020       32000      29020        32000   0.033           0.0
1  1435363200       32000       31700      31700        31700   0.001           0.0
2  1435449600       31700       31704      30550        31000   2.739           0.0
3  1435536000       31000       31220      30870        30870   1.280           0.0
4  1435622400       30870       31550      30900        31550   0.990           0.0
```
close_timeがタイムスタンプなので「YYYY-MM-DD」の形式に変換します。
ここでは新しくdateというカラムに変換後の日付を入れます。

```python
daily_data['date'] = pd.to_datetime(daily_data['close_time'], unit='s')
daily_data.head()
```

```python:結果
   close_time  open_price  high_price  low_price  close_price  volume  quote_volume       date
0  1435276800       29020       32000      29020        32000   0.033           0.0 2015-06-26
1  1435363200       32000       31700      31700        31700   0.001           0.0 2015-06-27
2  1435449600       31700       31704      30550        31000   2.739           0.0 2015-06-28
3  1435536000       31000       31220      30870        30870   1.280           0.0 2015-06-29
4  1435622400       30870       31550      30900        31550   0.990           0.0 2015-06-30
```

## ローソク足のプロット
ここからは先程のデータを使ってPlotlyでローソク足をプロットしていきます。

```python
from plotly.graph_objs import *
trace1 = {
    'type': 'candlestick',
    'x': daily_data['date'],
    'yaxis': 'y2',
    'low': daily_data['low_price'],
    'high': daily_data['high_price'],
    'open': daily_data['open_price'],
    'close': daily_data['close_price']
}
fig = Figure(data=[trace1])
fig.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/c5fff55b-94a9-db06-9102-8d3f2c980b22.png)
結構簡単にプロットできました。
上のやつはキャプチャですが、実際にプロットした場合はグリグリ動かせるかと思います。

## 移動平均線のプロット
ついでに移動平均線のプロットもやってみたいと思います。
まずは以下のように移動平均を計算しましょう。今回は直近20日の平均を算出します。(20MA）

```python
daily_data['20ma'] = daily_data['close_price'].rolling(10).mean()
daily_data.tail()
```

```python:結果
      close_time  open_price  high_price  low_price  close_price       volume  quote_volume       date       20ma
2410  1643587200     4405409     4427338    4314000      4372479  1861.188516  8.152451e+09 2022-01-31  4230787.9
2411  1643673600     4372033     4461762    4235851      4432335  2661.267119  1.153232e+10 2022-02-01  4259408.9
2412  1643760000     4433180     4505893    4365074      4445101  2940.564877  1.303647e+10 2022-02-02  4304918.5
2413  1643846400     4445119     4462325    4189000      4225388  2574.098126  1.117299e+10 2022-02-03  4314578.4
2414  1643932800     4226404     4258902    4167385      4220022  1329.148291  5.604551e+09 2022-02-04  4318259.4
```

```python
trace1 = {
    'type': 'candlestick', 
    'x': daily_data['date'], 
    'yaxis': "y2",
    'low': daily_data['low_price'], 
    'high': daily_data['high_price'], 
    'open': daily_data['open_price'], 
    'close': daily_data['close_price']
}
trace2 = {
    'line': {'width': 1}, 
    'mode': 'lines', 
    'name': '20MA', 
    'type': 'scatter', 
    'x': daily_data['date'], 
    'y': daily_data['20ma'], 
    'yaxis': 'y2', 
    'marker': {'color': '#E377C2'}
}
fig = Figure(data=[trace1, trace2])
fig.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/ec83012d-7f51-a4d2-994c-7b99911503a6.png)
上記の例では20MAを一本引いただけですが、traceを増やすことで50MAや100MAを同時にプロットすることも可能なので気になる方はやってみてください。

## ボリンジャーバンドのプロット
最後にボリンジャーバンドのプロットもやってみましょう。
以下のようにボリンジャーバンドの線を計算します。（※ここではボリンジャーバンドの詳細は省きます）

```python
daily_data['bb_mean'] = daily_data['close_price'].rolling(window=20).mean()
daily_data['bb_std'] = daily_data['close_price'].rolling(window=20).std()
daily_data['bb_upper'] = daily_data['bb_mean'] + (daily_data['bb_std'] * 2)
daily_data['bb_lower'] = daily_data['bb_mean'] - (daily_data['bb_std'] * 2)
daily_data.tail()
```

```python:結果
      close_time  open_price  high_price  low_price  close_price       volume  quote_volume       date       20ma     bb_mean         bb_std      bb_upper      bb_lower
2410  1643587200     4405409     4427338    4314000      4372479  1861.188516  8.152451e+09 2022-01-31  4230787.9  4551391.80  348662.869050  5.248718e+06  3.854066e+06
2411  1643673600     4372033     4461762    4235851      4432335  2661.267119  1.153232e+10 2022-02-01  4259408.9  4526324.25  337577.137683  5.201479e+06  3.851170e+06
2412  1643760000     4433180     4505893    4365074      4445101  2940.564877  1.303647e+10 2022-02-02  4304918.5  4496377.15  315046.871209  5.126471e+06  3.866283e+06
2413  1643846400     4445119     4462325    4189000      4225388  2574.098126  1.117299e+10 2022-02-03  4314578.4  4464542.65  308243.358236  5.081029e+06  3.848056e+06
2414  1643932800     4226404     4258902    4167385      4220022  1329.148291  5.604551e+09 2022-02-04  4318259.4  4429406.85  292936.338577  5.015280e+06  3.843534e+06
```
算出できたら以下のようにプロットします。（冗長なコードですが一旦気にしない・・・）
基本的にプロットのやり方は移動平均線と同じです。

```python
trace1 = {
    'type': 'candlestick', 
    'x': daily_data['date'], 
    'yaxis': "y2",
    'low': daily_data['low_price'], 
    'high': daily_data['high_price'], 
    'open': daily_data['open_price'], 
    'close': daily_data['close_price']
}
trace2 = {
    'line': {'width': 1}, 
    'mode': 'lines', 
    'name': 'BB MEAN', 
    'type': 'scatter', 
    'x': daily_data['date'], 
    'y': daily_data['bb_mean'], 
    'yaxis': 'y2', 
    'marker': {'color': '#E377C2'}
}
trace3 = {
    'line': {'width': 1}, 
    'mode': 'lines', 
    'name': 'B Bands', 
    'type': 'scatter', 
    'x': daily_data['date'], 
    'y': daily_data['bb_upper'], 
    'yaxis': 'y2', 
    'marker': {'color': '#CCC'},
    'legendgroup': 'BB', 
}
trace4 = {
    'line': {'width': 1}, 
    'mode': 'lines', 
    'name': 'B Bands', 
    'type': 'scatter', 
    'x': daily_data['date'], 
    'y': daily_data['bb_lower'], 
    'yaxis': 'y2', 
    'marker': {'color': '#CCC'},
    'legendgroup': 'BB', 
}
fig = Figure(data=[trace1, trace2, trace3, trace4])
fig.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/b0d6d3c9-7ac2-3bdf-a195-3200c2f361e3.png)

他にもいろいろなテクニカル指標プロットしてみると面白いと思います。