Zaif取引所のAPIで仮想通貨の売買価格を取得しチャートを作成する

# 環境

```
- MacOS Sierra 10.12.6
- Python 3.5.3 :: Anaconda 4.4.0 (x86_64)
- Jupyter 4.3.0
```

# 背景
- Zaif取引所は、ビットコインだけでなく、NEM、Monacoinなど、ここでしか日本円とペアで売買できない仮想通貨のある貴重な仮想通貨取引所である。
- Zaif取引所は、ビットコイン関連の（主にネガティブな）ニュースが報じられた際などに取引量が急増すると、Webサイトが非常に重くなり、取引どころかログインすることすらできなくなることがある。

# 問題
- Zaif取引所にログインできない状態になると、（特に）Zaif取引所以外では日本円とペアで取引されていなかったり、ZaifトークンのようにZaif取引所でしか取引されていない暗号通貨について、正確な値動きを知ることができなくなる。

# 解決
- Zaif取引所は、売買価格情報の取得や取引を行うことができるAPIを公開しており、Webサイトが重くなっていてもAPIは生き残っていることが多い。そのため、APIで定期的に売買値を取得してチャートを表示させればWebサイトにログインできなくても値動きを確認することができる。
- **作成したものはこちら（チャートは5分おきに更新）：**https://zaifcharts.hateblo.jp/
- チャートを確認した上でAPIで売買をする方法はこちら：[ZaifAPIを使って仮想通貨の売買をする](https://qiita.com/occha/items/27a2cf12e4e7dbb260d9)

# 仕様
Zaif取引所より売買価格情報を取得してcsvファイルに書き出すスクリプトと、書き出したcsvファイルからチャートを作成するスクリプトを作成し、それぞれcronで定期的に実行する。
## Zaif取引所より売買価格情報を取得
- pandas、numpy、jsonなど必要となるモジュールをインポート

```py3
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
from datetime import datetime
import time
import json
import requests
import csv
import sys, codecs
```

- 現在の時刻を取得（チャートの横軸にするため）

```py3
date = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
```

- Zaif取引所のAPIを利用して最新の売買価格を取得（下記はBTCのみ記述、他の仮想通貨も同様）


```py3
response = requests.get('https://api.zaif.jp/api/1/last_price/btc_jpy')
if response.status_code != 200:
    raise Exception('return status code is {}'.format(response.status_code))
res_dict = json.loads(response.text)
btc_price = res_dict['last_price']
#[現在時刻、売買価格]のリストを作成
btc_list = [date, btc_price]
```

- 取得した売買価格をcsvファイルに書き出す（下記はBTCのみ記述、他の仮想通貨も同様）

```py3
f = open("/var/www/html/zaif/btc.csv", "a")
writer = csv.writer(f, lineterminator='\n')
writer.writerow(btc_list)
f.close()
```

なお、ファイルに書き出す操作を含むスクリプトをcronで実行させると下記のようなエラーが出力され、実行できない場合がある。

>UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 720: ordinal not in range(128)

今回は、下記のようにcrontabに`export LANG=ja_JP.UTF-8;`と記述することでエラーを回避した。

```bash
0,5,10,15,20,25,30,35,40,45,50,55 * * * * export LANG=ja_JP.UTF-8; runipy /home/user/Get_Zaif_data.ipynb
```

## 取得した売買価格情報からチャートを作成
- matplotlibなど必要となるモジュールをインポート

```py3
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
from datetime import datetime
import time
import json
import requests
import csv
import matplotlib.pyplot as plt
from matplotlib.pylab import rcParams
%matplotlib inline
import seaborn as sns
sns.set_style('whitegrid')
rcParams['figure.figsize'] = 20, 10
from matplotlib.dates import DateFormatter
```

- csvファイルを読み込みDataframeを作成（下記はBTCのみ記述、他の仮想通貨も同様）

```py3
btc_df = pd.read_csv("/var/www/html/zaif/btc.csv", names = ("date", "BTC price"))
```

- チャートを作成する期間のみ取り出す（下記の例は3日間）

```py3
btc_df = btc_df[-864:-1]
```

- btc_dfのdate列をhh:mm形式に成形

```py3
date_df = btc_df["date"].str[10:16]
btc_df = pd.concat([date_df, btc_df["BTC price"]], axis=1)
```

- BTCのbollinger bandを算出（下記はBTCのみ記述、他の仮想通貨も同様）

```py3
rm = btc_df.set_index("date").rolling(window=24).mean()
rstd = btc_df.set_index("date").rolling(window=24).std()
upper_band = rm + rstd * 2
lower_band = rm - rstd * 2
```

*詳しくはこちらのページを参照：http://www.madopro.net/entry/MachineLearningForTrading*

- Dataframeからチャートを作成（下記はBTCのみ記述、他の仮想通貨も同様）

```py3
ax = btc_df.set_index("date").plot()
rm.columns = ["Rolling mean"]
rm.plot(ax=ax, color="#8FBC8F")
upper_band.columns = ["Upper band"]
upper_band.plot(ax=ax, color="#F4A460")
lower_band.columns = ["Lower band"]
lower_band.plot(ax=ax, color="#F4A460")
plt.legend(loc='best',
           fontsize=14,
           borderaxespad=0.,)
plt.tick_params(labelsize=14)
plt.savefig("/var/www/html/zaif/btc.png")
```

- 作成したチャート
![btc_chart.png](https://qiita-image-store.s3.amazonaws.com/0/201508/ed6853aa-a9a2-cc9d-2da4-d424134075b8.png)

# まとめ
- APIから取得した売買価格情報よりチャートを作成することで、Zaif取引所のWebサイトにログインできない状況でもZaif取引所で取引されている仮想通貨の値動きを確認できるようになった。
- Zaif取引所のWebサイトにログインできる状況であっても、各仮想通貨のチャートを一覧できるページがあると便利である（Zaif取引所のWebサイトでは、複数の仮想通貨のチャートを一度に見ることができない）。