Python pandas_datareaderとbokehで株価のキャンドルチャート


##ぶっちゃけネットを見れば転がってる株価チャートを自分で作ってみる。

参考元：
https://www.udemy.com/the-python-mega-course/learn/v4/
yahho_financeモジュール
https://pypi.org/project/fix-yahoo-finance/
YAHOOファイナンス情報
https://finance.yahoo.co.jp/

Candlestick Chartとは:

* グラフ上でデータをロウソクのような部品(四角形と線分)で表現
* 上がった時、下がったときが一目瞭然でわかる

* 水色四角:buttom→open, top→close。価格は上がった
* 赤色四角:buttom→close, top→open。価格は下がった
* 中心を通る線分: 線の一番下:low, 線の一番上:high
こんな感じで作る。

使うライブラリー

```py

from pandas_datareader import data
import fix_yahoo_finance as yf
```

##Googleの株価データを取得する。
インターネット接続がいります。

```python
from pandas_datareader import data
from datetime import datetime

#datetimeオブジェクトの作成
start=datetime(2016,3,1)
end=datetitme(2016,3,10)

#ticker, google or yahoo, start_datetime, end_datetime
#gooleの株価データ
df=data.DatarReader(name="GOOG", data_source="yahoo", start=start, end=end)

#が、2017年の下半期あたりでサポート終わってるっぽい。
>>>UnstableAPIWarning: 
The Google Finance API has not been stable since late 2017. Requests seem
to fail at random. Failure is especially common when bulk downloading.
warnings.warn(UNSTABLE_WARNING, UnstableAPIWarning)
```
1. ticker(stocksymbol)と呼ばれる会社ごとの固有の識別名。googleとデータベースかyahooのデータベース。`datetime`型で取得したい開始日時と終了日時。これらを`data.DatarReader()`に渡せば、`DataFrame`を取得できる。...できたのだ。昔は。
2. `pandas_datareader`の`data.DataReader()`を使うはずだったが、2017年後期あたりでサポートが終わってるぽい。
3. tickerはgoogleならGOOG, appleならAAPL, FacebookならFBなど。それぞれ固有。

```py
#代わりに
$ pip install fix_yahoo_finance

from datetime import datetime as dt
import fix_yahoo_finance as yf
from pandas_datareader import data as pdr

start = dt(2018,4,1)
end = dt(2018,7,31)
yf.pdr_override()
#これFacebook株価データ,FB
df=pdr.get_data_yahoo(tickers="FB", start=start, end=end)
```
1. 参考元：https://pypi.org/project/fix-yahoo-finance/ これのQuickStartってとこ。
2. 現状`pandas_datareader`でエラーができるのを解決してくれる。yahooファイナンスから情報を取ってきてくれる。
3. `pdr.get_data_yahoo`にデータのほしい会社のticker、ほしい範囲の開始日、終了日を渡せば今度こそ`DataFrame`の表を取得できる。日付ごとにrowになる。土日は市場が空いてないためデータはない。
4. 取得できるデータのコラムについて。Open：始値。Close：終値。High：最高値。Low：最低値。Volume:出来高(成立した株の売買数)


##BokehでCandleStick Chartを作る
Googleのが株価の値変動が大きくて面白いけど、Facebookのデータを取得してるのはこの先日2018/07/26にどーんと株価が下がってたから。

```py
from datetime import datetime as dt
from bokeh.plotting import figure, show, output_file
from pandas_datareader import data as pdr
import fix_yahoo_finance as yf

start = dt(2018,4,1)
end = dt(2018,7,31)

yf.pdr_override()
df=pdr.get_data_yahoo(tickers="FB", start=start, end=end)

def inc_dec(close, open_):
    if close>open_:
        value="Increase"
    elif close<open_:
        value="Decrease"
    else:
        value="Equal"
    return value

#価格が増加日か減少日のコラム
df["Status"]=[inc_dec(c,o) for c,o in zip(df.Close, df.Open)]

#平均値
df["Middle"]=(df.Close+df.Open)/2

#四角形の縦の長さ。始値と終値の差の絶対値。
df["Height"]=abs(df.Open-df.Close)



#グラフ作成
p=figure(x_axis_type="datetime", width=1000, height=300, title="Candlestick Chart", sizing_mode="scale_width")
p.grid.grid_line_alpha=0.3

#中心線レイヤー。:vertival_line:HighとLow
#highのx座標、y、lowのx座標,y座標
p.segment(df.index, df.High, df.index, df.Low, color="black")

#12hour
millisecond_of_12hour=12*60*60*1000

#四角形:rectangle:OpenとClose　: 色分けあり
#四角形の中心のx,y座標。横,縦の長さを渡す。それぞれの渡すリストの長さは同じである必要がある。
p.rect(df.index[df.Status=="Increase"], df.Middle[df.Status=="Increase"], millisecond_of_12hour, df.Height[df.Status=="Increase"],
       fill_color="#CCFFFF", line_color="black")
p.rect(df.index[df.Status=="Decrease"], df.Middle[df.Status=="Decrease"], millisecond_of_12hour, df.Height[df.Status=="Decrease"],
       fill_color="#FF3333", line_color="black")

output_file("Chandlestick Chart.html")
show(p)
```

1. yahooフィナンスからデータを取得して、DataFrame型にするところまで同じ
2. その日の株価の終値が始値より増加してるかどうか調べて、"Status"コラムへ。
3. 作った"Middle"コラムは、始値と終値の平均値。グラフ上の四角形の中心点のy座標になる。DataFrameの`df.Cloumn_name`で取得できる`pandas.core.series.Series`オブジェクトは、list型のように扱える。が、より便利。2つの`pandas.core.series.Series`オブジェクトを結合ではなく、同じindex位置の要素をそれぞれ足して新しい`pandas.core.series.Series`を得られる(`df.Close+df.Open`の部分)。また、`pandas.core.series.Series`を2で割ると、for文のように、要素1つ1つに対して÷2を適用した新しい`pandas.core.series.Series`が生成される。
4. "Height"コラムは始値と終値の価格差の絶対値。四角形の縦の長さに使う。
5. グラフ作成。`figure()`でグラフの基礎部分を作る。x軸のデータ型を`datetime`型に指定。正確にはミリセコンド(millisecond)でx軸のパラメータを渡せるようになった。引数の`sizing_mode=`には"scale_width"と"fixed"のどちらかを渡せる。"scale_width"ならばグラフを開いているwindowのサイズによってグラフも可変する。
6. キャンドルスティックチャートには、部品が2つある。1つは四角形。もう1つは四角形の中心を垂直方向に横切る線分。bokehのグラフでは、部品同士にグラフ上で重なりがある場合、コードの後に記述された部品が上に表示される。今回の場合、線分と四角形で重なった部分の線分は見えなくなる(線分を先に記述してるから)
7. `segement()`メソッドには、始点のx座標,y座標,終点のx座標,y座標を渡す。リストの形式(正確には`pandas.core.series.Series`)で渡す場合には、それぞれのリストの長さは同じである必要がある。
8. `millisecond_of_12hour`は12時間をミリセコンドで表現したもの。`figure`でグラフを作ったときに、x軸のデータ型を`datetime`型にした。そのため、x軸方向のパラメータにはミリセコンドを渡す。12時間なのは、グラフの四角形の範囲を12時間。次の日までの空白を12時間で表現したいから。
9. `rect()`メソッドはrectangleの意味から。四角形を作れる。中心点のx座標、y座標、縦の長さ、横の長さを引数に渡し四角形を形成する。"Status"コラムの値によって、色の違う四角形を作っている。`df.index[df.Status=="Increase"]`このように、`pandas.core.series.Series`オブジェクトは、特定の条件を付加し、別の`pandas.core.series.Series`オブジェクトを生成することができる。この場合"Status"コラムに"Increase"が入ってるrowのindexのみを集めた`pandas.core.series.Series`オブジェクトを得る。
10. 色の指定にはCSSstyleで指定することも可能。`#`を色コードの先頭につければいい。
11. `output_file`でhtml名を指定
12. `show()`でhtmlで表示。`output_file`でhtml名を指定しない場合、"graph.html"って名前になる。

結果：
2018/7/26までは右肩上がりなのに、2018/07/26でガクッとおちてるFacebookの株価グラフができる。

##おまけ。htmlの表をcsvへ。
urlはゲームボーイ版ドラゴンクエストモンスターズ2イルとルカの不思議な鍵のモンスターのステータス成長率。

ドラクエのモンスターズの成長率の範囲は0-31なんだよね。ポケモンの個体値も0-31。それぞれ意味合いは全然異なるけど、偶然の一致なの？あるいは2の5乗の範囲？
ドラクエの成長率は、ポケモンの種族値と似た意味だしなー。

```py
import pandas

url="http://www.geocities.jp/shdqm/syuttyo/kaiseki4.htm"

#htmlのテーブルごとにリストの要素になる。
df = pandas.read_html(url)
print(df[0])
>>>表が表示

df[0].to_csv

```

1. `read_html`メソッドでhtml内部の表を読み込んでくれる。リストの長さは表の数。
2. つまりhtml上のテーブルタグで作られた表は簡単にcsvに変換可能

グラフのソートしたかっただけ。

##あとがき
そろそろmacのバッテリーが死ぬ。
というかメモリーが圧迫されてやばい。Coinhive?
ストレージもやばい。