jupyter notebook上で金融データの描画・取得・操作

この記事はplotlyとpandasを結びつけるライブラリ"cufflinks"の紹介、およびそれを利用した金融関連のデータ描画、pandas_datareaderや自作モジュールによる金融データの取得、自作モジュールによる金融データの操作を行います。

# データの描画
## cufflinks 使い方

公式: [GitHub - santosjorge/cufflinks](https://github.com/santosjorge/cufflinks)
> This library binds the power of plotly with the flexibility of pandas for easy plotting.

> このライブラリーは簡単なプロットのために「plotlyの力」と「pandasの柔軟性」を結びつけます。

2017年12月現在、condaではインストールできません。
> [anaconda cloudで探す](https://anaconda.org/bioconda/cufflinks)と(またはぐぐると) biocondaでRNAがなんとかとか言っている生物学系の別のcufflinksが見つかるけれども、全く関係ないものなので注意。

正しくインストールするにはpipを使って下さい。

```shell-session
$ pip install cufflinks
```

### インポートと初期設定

cufflinksをインポートし、オフライン設定を有効化します。


```python
import cufflinks as cf
cf.set_config_file(offline=True)
```



`get_config_file()`で`'offline': True,`設定を確認します。


```python
cf.get_config_file()
```




    {'colorscale': 'dflt',
     'datagen_mode': 'stocks',
     'dimensions': None,
     'offline': True,
     'offline_link_text': 'Export to plot.ly',
     'offline_show_link': True,
     'offline_url': '',
     'sharing': 'public',
     'theme': 'pearl'}



### 動作確認


```python
cf.datagen.box(20).iplot(kind='box')
```

![Peek 2017-12-24 10-44.gif](https://qiita-image-store.s3.amazonaws.com/0/113494/fe38fa6b-9f8b-946d-6d58-0431d525c0f1.gif)

> ここ以降の画像は静止画像になっていますが~~gifをキャプチャするのが面倒だったので~~jupyter notebook上ではマウスオーバー・ドラッグ可能です。



```python
fig = cf.datagen.histogram(3).figure(kind='histogram')
cf.iplot(fig)
```



![Screenshot-2017-12-17 cufflinks_practice.png](https://qiita-image-store.s3.amazonaws.com/0/113494/c124d1a5-7c95-d094-74e3-8864a110b20b.png)




## cufflinksによるローソク足のプロット

### サンプルOHLCデータをプロット


```python
np.random.seed(0)  # ランダム状態固定
df = cf.datagen.ohlcv()  # ランダムなデータを作成
qf = cf.QuantFig(df)
qf.add_bollinger_bands()  # ボリンジャーバンド追加
qf.iplot()  # ローソク足プロット
```


![Screenshot-2017-12-23 cufflinks_practice.png](https://qiita-image-store.s3.amazonaws.com/0/113494/27a2c66a-2fba-fe52-dad9-2354d0f2a132.png)



```python
qf.add_macd()  # MACD追加
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice1.png](https://qiita-image-store.s3.amazonaws.com/0/113494/b330cbfe-7675-1be2-8446-4abaca00d039.png)


```python
qf.add_sma([10,50],width=2, color=['red', 'green'])  # 移動平均線追加
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice2.png](https://qiita-image-store.s3.amazonaws.com/0/113494/2572c5eb-1461-586b-b534-3ca07259536f.png)







### 出来高も表示


```python
qf = cf.QuantFig(df, legend='top')
qf.add_volume()  # 出来高追加
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice3.png](https://qiita-image-store.s3.amazonaws.com/0/113494/c54dd4cc-9513-4072-a98e-48eb6a63e040.png)


```python
qf.add_shapes(hline=[80, -142], vline=[pd.Timestamp('20150317'), pd.Timestamp('20150218')])  # 価格80, -142に水平線
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice4.png](https://qiita-image-store.s3.amazonaws.com/0/113494/d007c199-946d-2d63-db78-cc6c680b450f.png)




```python
qf.add_trendline('01Jan15', '13Feb15')  # トレンドラインの挿入
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice5.png](https://qiita-image-store.s3.amazonaws.com/0/113494/1dca847d-4e18-74db-c32a-f75ef7f577b7.png)



日本人にはあまり馴染みのない'%d%b%y'形式しか受け付けないようです。
自分好みの形式で入力したいときはpandas.Timestampクラスとstrftimeメソッドを混ぜて下のようにしてやると打ち込みやすいと思います。


```python
qf = cf.QuantFig(df, legend='top')
# 上と同様に2015年1月1日から2015年2月13日
start, end = (pd.Timestamp(x).strftime('%d%b%y') for x in ('2015/1/1', '2015-2-13'))
# mapを使うならこう
# `start, end = map(lambda x: pd.Timestamp(x).strftime('%d%b%y'), ('2015/1/1', '2015-2-13'))`
qf.add_trendline(start, end)
qf.iplot()
```


![Screenshot-2017-12-23 cufflinks_practice6.png](https://qiita-image-store.s3.amazonaws.com/0/113494/8079a719-d889-e7fe-9523-47e22f858c40.png)





# データの取得

## 海外株

pandas_datareaderモジュールから米国株式のデータはダウンロードできます。

**[pandas-datareader](https://pandas-datareader.readthedocs.io/en/latest/remote_data.html)**

>Functions from pandas_datareader.data and pandas_datareader.wb extract data from various Internet sources into a pandas DataFrame. Currently the following sources are supported:

>pandas_datareader.dataとpandas_datareader.wbの関数はインターネット上の様々なデータをpandas DataFrameに抽出します。現在、以下のソースがサポートされています。

> * Yahoo! Finance
* Google Finance
* Enigma
* Quandl
* St.Louis FED (FRED)
* Kenneth French’s data library
* World Bank
* OECD
* Eurostat
* Thrift Savings Plan
* Nasdaq Trader symbol definitions

インストールは

```shell-session
$ conda install pandas-datareader
# または
$ pip install pandas-datareader
```


```python
from pandas_datareader import data
```


```python
end = pd.datetime.today()  # 今日の日付
start = (pd.Period(end, 'D')-300).start_time  # 300日前日付
df = data.get_data_yahoo('AMZN', end=end, start=start)  # 300日前からのAmazon株価取得
```


```python
df.tail()
```




<div>

</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-12-11</th>
      <td>1164.599976</td>
      <td>1169.900024</td>
      <td>1157.000000</td>
      <td>1168.920044</td>
      <td>1168.920044</td>
      <td>2363500</td>
    </tr>
    <tr>
      <th>2017-12-12</th>
      <td>1166.510010</td>
      <td>1173.599976</td>
      <td>1161.609985</td>
      <td>1165.079956</td>
      <td>1165.079956</td>
      <td>2235900</td>
    </tr>
    <tr>
      <th>2017-12-13</th>
      <td>1170.000000</td>
      <td>1170.869995</td>
      <td>1160.270020</td>
      <td>1164.130005</td>
      <td>1164.130005</td>
      <td>2616800</td>
    </tr>
    <tr>
      <th>2017-12-14</th>
      <td>1163.709961</td>
      <td>1177.930054</td>
      <td>1162.449951</td>
      <td>1174.260010</td>
      <td>1174.260010</td>
      <td>3156600</td>
    </tr>
    <tr>
      <th>2017-12-14</th>
      <td>1163.709961</td>
      <td>1177.930054</td>
      <td>1162.449951</td>
      <td>1176.089966</td>
      <td>1176.089966</td>
      <td>1873348</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(df, legend='top', name='AMZN')
qf.add_volume()
qf.iplot()
```


![Screenshot-2017-12-23 cufflinks_practice7.png](https://qiita-image-store.s3.amazonaws.com/0/113494/1d9576ad-9ffe-6f01-4b75-cede2b64dd89.png)




## 日本株
jsmモジュール利用して、日本株を取得してpandas DataFrameで返してくれるモジュールを組み立てました。

[Qiita - 日本株の株価を取得してpandasデータフレームに格納する](https://qiita.com/u1and0/items/f6dad2cc2ee730be321c)

> 参考
> [【Python/jsm】日本企業の株価データを銘柄ごとに取得](https://algorithm.joho.info/programming/python/jsm-get-japan-stock/)

**[jsm 0.19](https://pypi.python.org/pypi/jsm/0.19)**

> 日本の株式市場の株価・財務データを取得するツールです。

> 各種データは、 Yahoo!ファイナンス からスクレイピングしています。

インストールは

```shell-session
$ pip install jsm
```


```python
from read_nikkei import get_jstock  # 日本企業の株価取得モジュール
```

pandas_datareaderと異なる点

* 銘柄はsymbol(Amazonなら'AMZN'とする)ではなく株価コード(数字4桁)で取得
* 週足、月足での取得も可能(freq='W', freq='M'オプション)
    * デフォルトは日足(freq='D')
* 期間の指定(periods=<数字>)で「endまたはstartから数えて<数字>本足の取得」
    * periodsを指定するとendまたはstartオプションが必ず必要です。
* デフォルトでは、今日から数えて30日前からの日足データの取得(`freq='D', end=pd.datetime.today(), periods=30`と同様)
    * pandas_datereaderではデフォルトで2010年1月1日から今日までの株価取得(`start=20100101, end=pd.datetime.today()`)


```python
from read_nikkei import get_jstock
# 今日から100日前からの任天堂株価を取得
df = get_jstock(7974, end=pd.datetime.today(), periods=100)
df.tail()
```

```
    Get data from 2017-09-08 to 2017-12-17


    /home/u1and0/.pyenv/versions/anaconda3-5.0.0/envs/snow/lib/python3.6/site-packages/bs4/__init__.py:181: UserWarning:
    
    No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.
    
    The code that caused this warning is on line 193 of the file /home/u1and0/.pyenv/versions/anaconda3-5.0.0/envs/snow/lib/python3.6/runpy.py. To get rid of this warning, change code that looks like this:
    
     BeautifulSoup(YOUR_MARKUP})
    
    to this:
    
     BeautifulSoup(YOUR_MARKUP, "lxml")
```    
    


> なんかBeautifulSoup関連のワーニング出ますが、jsm作者に何とかしてもらうしかないんですかねー






<div>

</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-12-11</th>
      <td>43800</td>
      <td>44380</td>
      <td>43400</td>
      <td>44380</td>
      <td>44380</td>
      <td>1822300</td>
    </tr>
    <tr>
      <th>2017-12-12</th>
      <td>44380</td>
      <td>44380</td>
      <td>43710</td>
      <td>43900</td>
      <td>43900</td>
      <td>1536600</td>
    </tr>
    <tr>
      <th>2017-12-13</th>
      <td>43430</td>
      <td>44140</td>
      <td>43100</td>
      <td>43930</td>
      <td>43930</td>
      <td>2045600</td>
    </tr>
    <tr>
      <th>2017-12-14</th>
      <td>43700</td>
      <td>43800</td>
      <td>42800</td>
      <td>43010</td>
      <td>43010</td>
      <td>2012200</td>
    </tr>
    <tr>
      <th>2017-12-15</th>
      <td>42500</td>
      <td>43380</td>
      <td>42320</td>
      <td>43030</td>
      <td>43030</td>
      <td>2283300</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(df, legend='top', name='任天堂')
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice8.png](https://qiita-image-store.s3.amazonaws.com/0/113494/784a9b5a-08ca-fa0f-57f8-ffa4959fed62.png)




## 為替
為替のデータはpandas_datereaderからでもある程度は取得可能です。
遡って1996年からの日足データを手に入れることができるようです。

### 日足


```python
df = data.get_data_yahoo('JPY=X', start='1990')
df.head()
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1996-10-30</th>
      <td>114.370003</td>
      <td>114.480003</td>
      <td>113.610001</td>
      <td>114.180000</td>
      <td>114.180000</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>1996-10-31</th>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1996-11-01</th>
      <td>113.500000</td>
      <td>113.500000</td>
      <td>113.500000</td>
      <td>113.500000</td>
      <td>113.500000</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>1996-11-04</th>
      <td>113.349998</td>
      <td>113.980003</td>
      <td>112.949997</td>
      <td>113.879997</td>
      <td>113.879997</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>1996-11-05</th>
      <td>113.709999</td>
      <td>114.330002</td>
      <td>113.449997</td>
      <td>114.250000</td>
      <td>114.250000</td>
      <td>0.0</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(df[-1000:], legend='top', name='USDJPY日足')  # 最後から1000本足をプロット
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice9.png](https://qiita-image-store.s3.amazonaws.com/0/113494/94784ce8-6b9d-b8ac-32bf-985cd2b682c4.png)



### 1分足

1分足を扱うには[MetaTrader](https://ja.wikipedia.org/wiki/MetaTrader)などで扱われるヒストリカルファイル(.hst)をダウンロードしてくると利用できます。

MT4,5を使っている人はPCの中のどこかに.hst拡張子のファイルがあると思うので探して下さい。
> 参考: [MT4でデモ口座・ライブ口座のヒストリカルデータを取得する方法](http://www.autotrading-fx.com/mt4-tips/3507.html)

MT4,5を利用していない人は[FXDD TRADING](http://www.fxdd.com/bm/jp/forex-resources/forex-trading-tools/metatrader-1-minute-data/)などからダウンロードして下さい。

> wgetやaria2を使える環境にある人は
```shell-session
$ wget http://tools.fxdd.com/tools/M1Data/USDJPY.zip
$ aria2c -x10 -s10 -k1M http://tools.fxdd.com/tools/M1Data/USDJPY.zip
```

2005年からの主要通貨1分足をhstファイルを圧縮したzip形式でダウンロードできます。容量の目安は50MB程度、zip解凍すると200MB程度です。

### hstファイルをpandas DataFrameに変換

hst形式のままでは使えませんので、hstファイルをpandas DataFrame形式に変換するコードを書きました。

[Qiita - u1and0/MT4ヒストリカルデータをpython上で扱えるようにしたりcsvに保存する](https://qiita.com/u1and0/items/6a690f6b0080b8efc2c7)

zip解凍から行ってくれますので、ダウンロードしたファイルはzip解凍しておく必要はありません。


```python
from read_hst import read_hst
```


```python
df = read_hst('/home/u1and0/Data/USDJPY.zip')
df = df[-1000:]
df.head()
```

    Extracting USDJPY.hst...





<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>open</th>
      <th>high</th>
      <th>low</th>
      <th>close</th>
      <th>volume</th>
    </tr>
    <tr>
      <th>time</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-11-16 15:57:00</th>
      <td>113.027</td>
      <td>113.030</td>
      <td>113.001</td>
      <td>113.001</td>
      <td>77.0</td>
    </tr>
    <tr>
      <th>2017-11-16 15:58:00</th>
      <td>113.003</td>
      <td>113.008</td>
      <td>113.002</td>
      <td>113.003</td>
      <td>70.0</td>
    </tr>
    <tr>
      <th>2017-11-16 15:59:00</th>
      <td>113.003</td>
      <td>113.010</td>
      <td>113.000</td>
      <td>113.001</td>
      <td>72.0</td>
    </tr>
    <tr>
      <th>2017-11-16 16:00:00</th>
      <td>113.001</td>
      <td>113.015</td>
      <td>112.996</td>
      <td>113.015</td>
      <td>78.0</td>
    </tr>
    <tr>
      <th>2017-11-16 16:01:00</th>
      <td>113.015</td>
      <td>113.027</td>
      <td>113.010</td>
      <td>113.025</td>
      <td>89.0</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(df, name='USDJPY分足')
qf.add_volume()
qf .iplot()
```



![Screenshot-2017-12-23 cufflinks_practice10.png](https://qiita-image-store.s3.amazonaws.com/0/113494/feb40507-d9b9-eeb3-f22d-81824941964d.png)



# データ操作

## ローソク足OHLCの時間足変換
参考: [qiita - u1and0/ローソク足OHLCの時間足を変える](https://qiita.com/u1and0/items/8e7bcaaf3668ed2afee1)
ohlcデータの時間軸を変えます。


```python
def _ohlcv(columns, open=None, high=None, low=None, close=None, volume=None):
    """Make a dictionary of {open:'***', low:'***', high:'***', close:'***', volume:'***'}"""
    auto_dict = {str(v).lower(): v for v in columns}  # Lower case of columns dictionary
    my_dict = {'open': open, 'high': high, 'low': low,
               'close': close, 'volume': volume}  # User defined OHLCV
    updater = {k: v for k, v in my_dict.items() if v}  # Remove `None` values in `my_dict`
    auto_dict.update(updater)  # Swap `auto_dict` with `my_dict` except `None` value
    return auto_dict


def ohlc2(self, open=None, high=None, low=None, close=None, volume=None):
    """`pd.DataFrame.resample(<TimeFrame>).ohlc2()`
    Resample method converting OHLC to OHLC
    """
    auto_dict = _ohlcv(self.asfreq().columns, open, high, low, close, volume)
    # Make dict as `agdict` for `df.resample(<Time>).agg(<dict>)`
    try:
        agdict = {auto_dict['open']: 'first',
                  auto_dict['high']: 'max',
                  auto_dict['low']: 'min',
                  auto_dict['close']: 'last'}
    except KeyError as e:
        raise KeyError('Columns not enough {}'.format(*e.args))
    # Add `volume` columns
    if 'volume' in auto_dict:
        agdict[auto_dict['volume']] = 'sum'
    return self.agg(agdict)


# Add instance as `pd.DataFrame.resample('<TimeFrame>').ohlc2()`
resample.DatetimeIndexResampler.ohlc2 = ohlc2
```


```python
df.resample('H').ohlc2().head()
```




<div>

</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>open</th>
      <th>high</th>
      <th>low</th>
      <th>close</th>
      <th>volume</th>
    </tr>
    <tr>
      <th>time</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-11-16 15:00:00</th>
      <td>113.027</td>
      <td>113.030</td>
      <td>113.000</td>
      <td>113.001</td>
      <td>219.0</td>
    </tr>
    <tr>
      <th>2017-11-16 16:00:00</th>
      <td>113.001</td>
      <td>113.059</td>
      <td>112.800</td>
      <td>112.840</td>
      <td>6319.0</td>
    </tr>
    <tr>
      <th>2017-11-16 17:00:00</th>
      <td>112.840</td>
      <td>112.951</td>
      <td>112.725</td>
      <td>112.783</td>
      <td>6509.0</td>
    </tr>
    <tr>
      <th>2017-11-16 18:00:00</th>
      <td>112.785</td>
      <td>112.888</td>
      <td>112.766</td>
      <td>112.884</td>
      <td>5264.0</td>
    </tr>
    <tr>
      <th>2017-11-16 19:00:00</th>
      <td>112.884</td>
      <td>112.905</td>
      <td>112.794</td>
      <td>112.857</td>
      <td>4129.0</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(df.resample('H').ohlc2(), name='USDJPY時間足')
qf.add_volume()
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice11.png](https://qiita-image-store.s3.amazonaws.com/0/113494/a9b45862-084c-b612-2328-e1d279c3c14c.png)

日経平均のデータを取得して、調整後終値(Adjusted Closing Price, Adj Close)を終値として扱いたいときは、ohlc2の引数に与えてあげます。


```python
df = data.get_data_yahoo('^N225')  # 日経平均日足の取得
df.head()
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2010-01-04</th>
      <td>10609.339844</td>
      <td>10694.490234</td>
      <td>10608.139648</td>
      <td>10654.790039</td>
      <td>10654.790039</td>
      <td>104400.0</td>
    </tr>
    <tr>
      <th>2010-01-05</th>
      <td>10719.440430</td>
      <td>10791.040039</td>
      <td>10655.570313</td>
      <td>10681.830078</td>
      <td>10681.830078</td>
      <td>166200.0</td>
    </tr>
    <tr>
      <th>2010-01-06</th>
      <td>10709.549805</td>
      <td>10768.610352</td>
      <td>10661.169922</td>
      <td>10731.450195</td>
      <td>10731.450195</td>
      <td>181800.0</td>
    </tr>
    <tr>
      <th>2010-01-07</th>
      <td>10742.750000</td>
      <td>10774.000000</td>
      <td>10636.669922</td>
      <td>10681.660156</td>
      <td>10681.660156</td>
      <td>182600.0</td>
    </tr>
    <tr>
      <th>2010-01-08</th>
      <td>10743.299805</td>
      <td>10816.450195</td>
      <td>10677.559570</td>
      <td>10798.320313</td>
      <td>10798.320313</td>
      <td>211800.0</td>
    </tr>
  </tbody>
</table>
</div>




```python
df.resample('W').ohlc2().head()  # 普通に週足に変換
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2010-01-10</th>
      <td>10609.339844</td>
      <td>10816.450195</td>
      <td>10608.139648</td>
      <td>10798.320313</td>
      <td>846800.0</td>
    </tr>
    <tr>
      <th>2010-01-17</th>
      <td>10770.349609</td>
      <td>10982.099609</td>
      <td>10729.860352</td>
      <td>10982.099609</td>
      <td>963000.0</td>
    </tr>
    <tr>
      <th>2010-01-24</th>
      <td>10887.610352</td>
      <td>10895.099609</td>
      <td>10528.330078</td>
      <td>10590.549805</td>
      <td>872000.0</td>
    </tr>
    <tr>
      <th>2010-01-31</th>
      <td>10478.309570</td>
      <td>10566.490234</td>
      <td>10198.040039</td>
      <td>10198.040039</td>
      <td>779500.0</td>
    </tr>
    <tr>
      <th>2010-02-07</th>
      <td>10212.360352</td>
      <td>10438.410156</td>
      <td>10036.330078</td>
      <td>10057.089844</td>
      <td>794700.0</td>
    </tr>
  </tbody>
</table>
</div>




```python
df.resample('W').ohlc2(close='Adj Close').head()  # 終値をAdj Closeに指定
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2010-01-10</th>
      <td>10609.339844</td>
      <td>10816.450195</td>
      <td>10608.139648</td>
      <td>10798.320313</td>
      <td>846800.0</td>
    </tr>
    <tr>
      <th>2010-01-17</th>
      <td>10770.349609</td>
      <td>10982.099609</td>
      <td>10729.860352</td>
      <td>10982.099609</td>
      <td>963000.0</td>
    </tr>
    <tr>
      <th>2010-01-24</th>
      <td>10887.610352</td>
      <td>10895.099609</td>
      <td>10528.330078</td>
      <td>10590.549805</td>
      <td>872000.0</td>
    </tr>
    <tr>
      <th>2010-01-31</th>
      <td>10478.309570</td>
      <td>10566.490234</td>
      <td>10198.040039</td>
      <td>10198.040039</td>
      <td>779500.0</td>
    </tr>
    <tr>
      <th>2010-02-07</th>
      <td>10212.360352</td>
      <td>10438.410156</td>
      <td>10036.330078</td>
      <td>10057.089844</td>
      <td>794700.0</td>
    </tr>
  </tbody>
</table>
</div>



`ohlc2()`の引数には`open, high, low, close, volume`を与えることができます。
例えば次のようにカラム名が4本値と関係ないデータを渡しても、きちんと引数を指定してやればOHLCVで変換してくれます。


```python
np.random.seed(19)
df = cf.datagen.ohlcv()  # データ生成
df.columns = range(1,6)  # カラム名を数字に変える
df.head()
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2015-01-01</th>
      <td>100.000000</td>
      <td>106.526092</td>
      <td>77.530418</td>
      <td>81.491630</td>
      <td>8015</td>
    </tr>
    <tr>
      <th>2015-01-02</th>
      <td>83.748302</td>
      <td>85.962681</td>
      <td>63.060215</td>
      <td>65.605544</td>
      <td>5769</td>
    </tr>
    <tr>
      <th>2015-01-03</th>
      <td>65.592938</td>
      <td>76.415738</td>
      <td>47.096441</td>
      <td>56.526309</td>
      <td>9328</td>
    </tr>
    <tr>
      <th>2015-01-04</th>
      <td>58.160297</td>
      <td>64.929405</td>
      <td>52.899053</td>
      <td>57.952424</td>
      <td>4412</td>
    </tr>
    <tr>
      <th>2015-01-05</th>
      <td>58.498021</td>
      <td>69.737244</td>
      <td>34.999141</td>
      <td>41.165273</td>
      <td>6892</td>
    </tr>
  </tbody>
</table>
</div>



週足に変更するため、open, high, low, close, volumeをそれぞれ1,2,3,4,5と指定します。


```python
df.resample('W').ohlc2(open=1, high=2, low=3, close=4, volume=5)  # 引数にohlcvのカラム名を指定
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2015-01-04</th>
      <td>100.000000</td>
      <td>106.526092</td>
      <td>47.096441</td>
      <td>57.952424</td>
      <td>27524</td>
    </tr>
    <tr>
      <th>2015-01-11</th>
      <td>58.498021</td>
      <td>98.722285</td>
      <td>25.081057</td>
      <td>85.380938</td>
      <td>34592</td>
    </tr>
    <tr>
      <th>2015-01-18</th>
      <td>85.227185</td>
      <td>116.629094</td>
      <td>56.120302</td>
      <td>104.003280</td>
      <td>35803</td>
    </tr>
    <tr>
      <th>2015-01-25</th>
      <td>103.913949</td>
      <td>139.336095</td>
      <td>82.181452</td>
      <td>109.151731</td>
      <td>38910</td>
    </tr>
    <tr>
      <th>2015-02-01</th>
      <td>108.334060</td>
      <td>126.237090</td>
      <td>75.235135</td>
      <td>101.461833</td>
      <td>39578</td>
    </tr>
    <tr>
      <th>2015-02-08</th>
      <td>101.868035</td>
      <td>131.537039</td>
      <td>27.324298</td>
      <td>57.099236</td>
      <td>33278</td>
    </tr>
    <tr>
      <th>2015-02-15</th>
      <td>55.782685</td>
      <td>98.734416</td>
      <td>49.267611</td>
      <td>61.573598</td>
      <td>34527</td>
    </tr>
    <tr>
      <th>2015-02-22</th>
      <td>62.830502</td>
      <td>104.472611</td>
      <td>48.834591</td>
      <td>85.477329</td>
      <td>30116</td>
    </tr>
    <tr>
      <th>2015-03-01</th>
      <td>84.665842</td>
      <td>123.096526</td>
      <td>44.282473</td>
      <td>121.435018</td>
      <td>40203</td>
    </tr>
    <tr>
      <th>2015-03-08</th>
      <td>120.073562</td>
      <td>154.933346</td>
      <td>120.073562</td>
      <td>123.635981</td>
      <td>55421</td>
    </tr>
    <tr>
      <th>2015-03-15</th>
      <td>123.368637</td>
      <td>130.713508</td>
      <td>54.363323</td>
      <td>74.063469</td>
      <td>50965</td>
    </tr>
    <tr>
      <th>2015-03-22</th>
      <td>72.393416</td>
      <td>130.067377</td>
      <td>61.799581</td>
      <td>119.121722</td>
      <td>35717</td>
    </tr>
    <tr>
      <th>2015-03-29</th>
      <td>120.383713</td>
      <td>213.487056</td>
      <td>111.342313</td>
      <td>202.147684</td>
      <td>36784</td>
    </tr>
    <tr>
      <th>2015-04-05</th>
      <td>202.951959</td>
      <td>211.550772</td>
      <td>102.660010</td>
      <td>106.082669</td>
      <td>42398</td>
    </tr>
    <tr>
      <th>2015-04-12</th>
      <td>106.244248</td>
      <td>115.505312</td>
      <td>76.272411</td>
      <td>106.781127</td>
      <td>23787</td>
    </tr>
  </tbody>
</table>
</div>



ただし、カラム名がFalseになるもの(0, None, False, np.NaNなど)を指定すると失敗します。

## 平均足


```python
def heikin_ashi(self, open=None, high=None, low=None, close=None):
    """Return HEIKIN ASHI columns"""
    df = self.copy()
    auto_dict = _ohlcv(df.columns, open, high, low, close)
    df['hopen'] = (df[auto_dict['open']].shift() + df[auto_dict['close']].shift()) / 2
    df['hclose'] = df[[auto_dict['open'],
                      auto_dict['high'],
                      auto_dict['low'],
                      auto_dict['close']]].mean(1)
    df['hhigh'] = df[[auto_dict['high'], 'hopen', 'hclose']].max(1)
    df['hlow'] = df[[auto_dict['low'], 'hopen', 'hclose']].min(1)
    return df[['hopen', 'hhigh', 'hlow', 'hclose']]


pd.DataFrame.heikin_ashi = heikin_ashi
```


```python
df = data.get_data_yahoo('^GSPC')  # S&P500指数の取得
df.tail()
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Open</th>
      <th>High</th>
      <th>Low</th>
      <th>Close</th>
      <th>Adj Close</th>
      <th>Volume</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-12-18</th>
      <td>2685.919922</td>
      <td>2694.969971</td>
      <td>2685.919922</td>
      <td>2690.159912</td>
      <td>2690.159912</td>
      <td>3724660000</td>
    </tr>
    <tr>
      <th>2017-12-19</th>
      <td>2692.709961</td>
      <td>2694.439941</td>
      <td>2680.739990</td>
      <td>2681.469971</td>
      <td>2681.469971</td>
      <td>3368590000</td>
    </tr>
    <tr>
      <th>2017-12-20</th>
      <td>2688.179932</td>
      <td>2691.010010</td>
      <td>2676.110107</td>
      <td>2679.250000</td>
      <td>2679.250000</td>
      <td>3241030000</td>
    </tr>
    <tr>
      <th>2017-12-21</th>
      <td>2683.020020</td>
      <td>2692.639893</td>
      <td>2682.399902</td>
      <td>2684.570068</td>
      <td>2684.570068</td>
      <td>3273390000</td>
    </tr>
    <tr>
      <th>2017-12-22</th>
      <td>2684.219971</td>
      <td>2685.350098</td>
      <td>2678.129883</td>
      <td>2683.340088</td>
      <td>2683.340088</td>
      <td>2399830000</td>
    </tr>
  </tbody>
</table>
</div>



普通にローソク足の表示


```python
qf = cf.QuantFig(df, name='S&P500ローソク足', legend='top',
                 slice=(pd.Timestamp('20170901'), pd.Timestamp('20171220')))
qf.iplot()
```



![Screenshot-2017-12-23 cufflinks_practice12.png](https://qiita-image-store.s3.amazonaws.com/0/113494/0a820c8e-2cdd-5761-4e8b-ef19d8d66365.png)

平均足の表示は平均足メソッドを使用します。


```python
he = df.heikin_ashi()
he.tail()
```




<div>
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>hopen</th>
      <th>hhigh</th>
      <th>hlow</th>
      <th>hclose</th>
    </tr>
    <tr>
      <th>Date</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>2017-12-18</th>
      <td>2668.219971</td>
      <td>2694.969971</td>
      <td>2668.219971</td>
      <td>2689.242432</td>
    </tr>
    <tr>
      <th>2017-12-19</th>
      <td>2688.039917</td>
      <td>2694.439941</td>
      <td>2680.739990</td>
      <td>2687.339966</td>
    </tr>
    <tr>
      <th>2017-12-20</th>
      <td>2687.089966</td>
      <td>2691.010010</td>
      <td>2676.110107</td>
      <td>2683.637512</td>
    </tr>
    <tr>
      <th>2017-12-21</th>
      <td>2683.714966</td>
      <td>2692.639893</td>
      <td>2682.399902</td>
      <td>2685.657471</td>
    </tr>
    <tr>
      <th>2017-12-22</th>
      <td>2683.795044</td>
      <td>2685.350098</td>
      <td>2678.129883</td>
      <td>2682.760010</td>
    </tr>
  </tbody>
</table>
</div>




```python
qf = cf.QuantFig(he, name='S&P500平均足', legend='top',
                 slice=(pd.Timestamp('20170901'), pd.Timestamp('20171220')))
qf.iplot()
```


![Screenshot-2017-12-23 cufflinks_practice13.png](https://qiita-image-store.s3.amazonaws.com/0/113494/fb6c514f-0d66-45bd-a4f0-42a177f487d3.png)


ローソク足と比べて陽線、陰線が続きやすくなっています。



# まとめ
* グラフの描画
    * `plotly`と`pandas`をの合わせ技をやりやすくしてくれる`cufflinks`
* データの取得
    * 海外株、主要通貨、主要指数 → `pandas-datareader`
    * 日本株 → `jsm` + 自作モジュールでpandas DataFrame化
    * 為替の1分足 → FXDDからhstファイルをダウンロード + 自作モジュールでpandas DataFrame化
* データ操作
    * OHLCをOHLCに変換 → 自作ohlc2()メソッド
    * 平均足 → 自作heikinashi()メソッド