日経平均株価のテクニカル分析用データ作成

# Todo
**株価の分析をより高度なものにする為、テクニカル指標を追加しグラフで表示する**

- `移動平均`
- `MACD`
- `RSI`
- `ボリンジャーバンド`
- `ローソク足`

:::note
これらのテクニカル指標の追加は、Pythonだと**pandas_datareader**や**TA-Lib**というライブラリを使用することで簡単に出来る。
:::
:::note warn
**TA-Lib**のインストールは環境によって上手くいかないケースがあるためDockerを使い環境構築を行う。
:::


# 用語

`テクニカル指標`

- ***<font color="LightSeaGreen">移動平均</font>***
    - **過去〇〇日分の平均**
    - ゴールデンクロス
        - 「短期の移動平均線」が「中期以上の移動平均線」を下から上に抜けること
        - 価格が上昇しているサイン
    - デッドクロス
        - 「短期の移動平均線」が「中期以上の移動平均線」を上から下に抜けること
        - 価格が下降しているサイン
- ***<font color="LightSeaGreen">MACD</font>***
    - **トレンドを見る指標**
        - 0以上なら上昇トレンド
        - 0以下なら下降トレンド
- ***<font color="LightSeaGreen">RSI</font>***
    - **売られ過ぎ・買われ過ぎを判断する指標**
        - 20〜30%を下回る・・・売られ過ぎ
        - 70〜80%を上回る・・・買われ過ぎ
- ***<font color="LightSeaGreen">ボリンジャーバンド</font>***
    - **売られ過ぎ・買われ過ぎを判断する指標**
    - 移動平均などの一定期間の平均に対して、一定期間の標準偏差を足したものと引いたものの2本のラインを引く
        - 一般的にプラスマイナス「標準偏差の2倍」を使うことが多い
        - 統計学の考え方から終値はこの2本の間に収まると考えられる
        - 収まらなかった場合は、売られ過ぎ・買われ過ぎだと判断する
- ***<font color="LightSeaGreen">ローソク足</font>***
    - **取引時間中の株価の値動き（始値、終値、高値、安値など）を1本のローソクの形で表現したもの**
        - 数字の羅列で変化し続ける為替レートを視覚的に、かつ過去のデータも含めて一目で値動きの推移を把握できるのがローソク足の特徴


:::note
これらの指標を用いて分析をし、**株の売買の意思決定**が行われている。
**株**の他、**Bitcoin**や**為替**、**FX**にも活用可能。
:::

# 前提

Dockerのインストールを済ませておく（目安：5分）

https://qiita.com/rexid/items/dd3db91b612f0c70097c

# 環境構築

先にも述べたように、<font color="Crimson">TA-Libのインストールは環境によって上手くいかない</font> or <font color="Crimson">インストール出来るとしても手順として複雑になるケースがある</font>為、Dockerを使い環境構築を行う


## 1. 任意のフォルダを作成
今回はDesktop上に`data_analysis`フォルダを新規作成

## 2. Dockerfileを作成し、フォルダに格納

```Dockerfile:Dockerfile
FROM --platform=linux/amd64 ubuntu:20.04

RUN apt-get update && apt-get install -y sudo wget vim curl gawk make gcc

RUN wget https://repo.continuum.io/archive/Anaconda3-2019.03-Linux-x86_64.sh && \
    sh Anaconda3-2019.03-Linux-x86_64.sh -b  && \
    rm -f Anaconda3-2019.03-Linux-x86_64.sh && \
    sudo curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -  && \
    sudo apt-get install -y nodejs

ENV PATH $PATH:/root/anaconda3/bin

RUN pip install --upgrade pip
RUN pip install pandas_datareader
RUN pip install mplfinance

RUN wget --quiet http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz -O ta-lib-0.4.0-src.tar.gz && \
    tar xvf ta-lib-0.4.0-src.tar.gz && \
    cd ta-lib/ && \
    ./configure --prefix=/usr && \
    make && \
    sudo make install && \
    cd .. && \
    pip install TA-Lib && \
    rm -R ta-lib ta-lib-0.4.0-src.tar.gz

RUN mkdir /workspace

CMD ["jupyter-lab", "--ip=0.0.0.0","--port=8888" ,"--no-browser", "--allow-root", "--LabApp.token=''"]
```

## 3. ビルド
```terminal
$ docker build -t 任意のタグ名:latest フォルダまでのパス
```
:::note
パスはファイルを直接ドラックアンドドロップすれば入力される
:::


```terminal:例
(base) sample@SampleMBP ~ % cd Desktop/data_analysis/
(base) sample@SampleMBP data_analysis % ls
Dockerfile
(base) sample@SampleMBP data_analysis % docker build -t da:latest /Users/sample/Desktop/data_analysis
```
コマンド実行後、完了まで20分以上要する

## 4. イメージIDを確認
```terminal
$ docker images
```

```terminal:実行結果例
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
da           latest    cdf22f203d75   a minute ago   3.86GB
```


## 5. JupyterLabを起動
```terminal
$ docker run -p ローカルの任意のポート番号:8888 -v フォルダまでのパス:/workspace –-name ビルド時のタグ名 イメージID
```

```terminal:例
(base) sample@SampleMBP data_analysis % docker run -p 8888:8888 -v /Users/sample/Desktop/data_analysis:/workspace --name da cdf22f203d75
```

***コマンド実行後にブラウザで下記URLにアクセスし、JupyterLabが起動したら環境構築完了🎉***
（例）http://127.0.0.1:8888/

![スクリーンショット 2022-10-15 16.49.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/5359b68d-10ce-616f-8815-defa04f751e4.png)

---

:::note
ローカルと同期されている為、workspaceディレクトリに移動すればDockerfileが存在することを確認できる
:::

![スクリーンショット 2022-10-15 16.53.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/6075ad7d-6a32-8535-e5a1-ee90b512724b.png)

:::note
workspaceディレクトリ配下に任意の実行ファイルを作成し作業を行う
:::

# 単純移動平均をグラフで可視化する

## 1. ライブラリをimport
```py
import pandas as pd
import talib as ta
# 日経平均やNASDAQ、個別銘柄の株価データを取得できるライブラリ
from pandas_datareader import data
# matplotlibのpyplotモジュールを使用
import matplotlib.pyplot as plt
# JupyterLab上で作成したグラフを表示
%matplotlib inline
import warnings
# すべての警告を表示させない
warnings.simplefilter('ignore')
```

## 2. 移動平均と出来高をグラフで可視化

***[詳細](https://qiita.com/rexid/items/4148e29300f47966066e)***

- 下記実行
```py
start_date = '2021-10-01'
end_date = '2022-10-01'

# data.DataReader('取得したいティッカーシンボル', 'データソースの名前', '取得したい期間の開始日付', '終了日付')
df = data.DataReader('^N225', 'yahoo', start_date, end_date)

date = df.index
close = df['Adj Close']

# 過去5日、25日、50日の移動平均を算出する為に定義
span01 = 5
span02 = 25
span03 = 50

# 移動平均を算出
# smaは単純移動平均の略称
df['sma01'] = close.rolling(window=span01).mean()
df['sma02'] = close.rolling(window=span02).mean()
df['sma03'] = close.rolling(window=span03).mean()

plt.figure(figsize=(30, 15))

# グラフ領域を二分割する
# plt.subplot(縦方向を分割する数, 横方向に分割する数, グラフを配置する位置を示すindex)
plt.subplot(2,1,1)

# 線グラフ(単純移動平均)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.plot(date, df['sma01'], label='sma01', color='#e84a5f')
plt.plot(date, df['sma02'], label='sma02', color='#ff847c')
plt.plot(date, df['sma03'], label='sma03', color='#feceab')
plt.legend()

# 棒グラフ(出来高)
plt.subplot(2,1,2)
plt.bar(date, df['Volume'], label='Volume', color='gray')
plt.legend()
```

![スクリーンショット 2022-10-15 18.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/d0a64cb5-5613-f184-dd3f-a8a39424fe14.png)

# MACDの指標を追加

`MACD`：トレンドを見る指標
 - 0以上なら上昇トレンド
 - 0以下なら下降トレンド


## 1. MACDの計算

```py
# ta.MACD(終値, 短期移動平均, 長期移動平均, MACDシグナル)
df['macd'], df['macdsignal'], df['macdhist'] = ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
``` 

:::note
一般的に**短期移動平均**は`12`、**長期移動平均**は`26`、 **MACDシグナル**は`9`を設定することが多い
:::

## 2. データが出来ていることを確認

```py
df.tail()
```

![スクリーンショット 2022-10-15 19.06.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/f02d1aec-55d8-da2e-107c-841216ccf673.png)

## 3. MACDをグラフ化

- **塗りつぶし折れ線グラフ**を用いる
    - ヒストグラムよりも分かりやすい

```py
plt.figure(figsize=(30, 15))

# グラフ領域を二分割する
# plt.subplot(縦方向を分割する数, 横方向に分割する数, グラフを配置する位置を示すindex)
plt.subplot(2,1,1)

# 線グラフ(調整後の終値)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.legend()

plt.subplot(2,1,2)

# 塗りつぶし折れ線グラフ(MACD)
# plt.fill_between(x軸, y軸, 色, 塗りつぶしの透過, ラベル)
plt.fill_between(date, df['macdhist'], color='gray', alpha=0.5, label='MACD_hist')

# y = 0に水平線を描画
# plt.hlines(y軸, 開始するx軸, 終了するx軸, 色, 線の種類)
plt.hlines(0, start_date, end_date, 'gray', linestyles='dashed')
plt.legend()
```

![スクリーンショット 2022-10-15 19.26.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/c4c77026-e522-7740-2892-2b4da6cedd4a.png)

:::note
0を基準にトレンドが簡単にわかる
:::


# RSI

`RSI`：売られ過ぎ・買われ過ぎを判断する指標
- 20〜30%を下回る・・・売られ過ぎ
    - 逆張りの「買い」と判断する
- 70〜80%を上回る・・・買われ過ぎ
    - 逆張りの「売り」と判断する

## 1. `25日`のRSIを計算

```py
# df['RSI'] = ta.RSI(終値, RSIを作成する期間)
df['RSI'] = ta.RSI(close, timeperiod=span02)
```

## 2. データが出来ていることを確認
```py
df.tail()
```

![スクリーンショット 2022-10-15 19.42.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/a20633be-95ae-8efb-fd00-11022d1f4b1a.png)

## 3. RSIをグラフ化

```py
plt.figure(figsize=(30, 15))
# グラフ領域を二分割する
# plt.subplot(縦方向を分割する数, 横方向に分割する数, グラフを配置する位置を示すindex)
plt.subplot(2,1,1)

# 単純移動平均
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.plot(date, df['sma01'], label='sma01', color='#e84a5f')
plt.plot(date, df['sma02'], label='sma02', color='#ff847c')
plt.plot(date, df['sma03'], label='sma03', color='#feceab')
plt.legend()

# RSI
plt.subplot(2,1,2)
plt.plot(date, df['RSI'], label='RSI', color='gray')
# y軸の範囲を設定
plt.ylim(0, 100)
# 30%、50%、70%の場所に転線を引く
plt.hlines([30, 50, 70], start_date, end_date, 'gray', linestyles='dashed')
plt.legend()
```

![スクリーンショット 2022-10-15 19.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/92407771-3583-0cb5-40da-b5648e07e92d.png)

:::note
RSIの可視化に成功
:::


# ボリンジャーバンド
`ボリンジャーバンド`：売られ過ぎ・買われ過ぎを判断する指標
- 移動平均などの一定期間の平均に対して、一定期間の標準偏差を足したものと引いたものの2本のラインを引く
    - 一般的にプラスマイナス「標準偏差の2倍」を使うことが多い
    - 統計学の考え方から終値はこの2本の間に収まると考えられる
    - 収まらなかった場合は、売られ過ぎ・買われ過ぎだと判断する

## 1. ボリンジャーバンドの計算

```py
# matype: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (デフォルト=SMA)

# 上のボリンジャーバンド, 移動平均, 下のボリンジャーバンド = ta.BBANDS(調整済み終値, 日経平均日数, 上のラインの標準偏差, 下のラインの標準偏差, 移動平均の計算方法)インの標準偏差, ○○移動平均)
df['upper'], df['middle'], df['lower'] = ta.BBANDS(close, timeperiod=span02, nbdevup=2, nbdevdn=2, matype=0)
```

- ***matype***
    - `0`・・・単純移動平均
    - `1`・・・指数移動平均
    - `2`・・・加重移動平均

## 2. データが出来ていることを確認
```py
df.tail()
```

![スクリーンショット 2022-10-15 21.39.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/5f4197fc-81cb-73b7-a4be-2116caf1b701.png)


## 3. ボリンジャーバンドをグラフ化

```py
plt.figure(figsize=(30, 15))

plt.plot(date, close, label='Adj Close', color='#99b898')
# plt.fill_between(x軸, 塗りつぶし上側, 塗りつぶし下側, 色, 透過)
plt.fill_between(date, df['upper'], df['lower'], color='gray', alpha=0.3)
plt.legend()
```

![スクリーンショット 2022-10-15 21.57.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/c4fdaf46-ae34-3cae-dd49-030dfef7ee4f.png)

:::note
ボリンジャーバンドの可視化に成功
:::


# 5つのグラフを同時に表示

```py
plt.figure(figsize=(30, 15))

# 移動平均
plt.subplot(5,1,1)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.plot(date, df['sma01'], label='sma01', color='#e84a5f')
plt.plot(date, df['sma02'], label='sma02', color='#ff847c')
plt.plot(date, df['sma03'], label='sma03', color='#feceab')

# 出来高
plt.subplot(5,1,2)
plt.bar(date, df['Volume'], label='Volume', color='gray')
plt.legend()

# MACD
plt.subplot(5,1,3)
plt.fill_between(date, df['macdhist'], color='gray', alpha=0.5, label='MACD_hist')
plt.hlines(0, start_date, end_date, 'gray', linestyles='dashed')
plt.legend()

# RSI
plt.subplot(5,1,4)
plt.plot(date, df['RSI'], label='RSI', color='gray')
plt.ylim(0, 100)
plt.hlines([30, 50, 70], start_date, end_date, 'gray', linestyles='dashed')
plt.legend()

# ボリンジャーバンド
plt.subplot(5,1,5)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.fill_between(date, df['upper'], df['lower'], color='gray', alpha=0.3)
plt.legend()
```

![スクリーンショット 2022-10-15 22.10.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/878c13f6-26ed-42f7-f031-baadca5a7aec.png)

:::note
同時に5つのグラフ表示成功
:::



# ここまでのコードまとめ

```py
import pandas as pd
import talib as ta
import mplfinance as mpf
from pandas_datareader import data
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.simplefilter('ignore')
```

```py
start_date = '2021-10-01'
end_date = '2022-10-01'

df = data.DataReader('^N225', 'yahoo', start_date, end_date)

date = df.index
close = df['Adj Close']

span01 = 5
span02 = 25
span03 = 50

# 移動平均を算出。smaは単純移動平均の略称
df['sma01'] = close.rolling(window=span01).mean()
df['sma02'] = close.rolling(window=span02).mean()
df['sma03'] = close.rolling(window=span03).mean()

plt.figure(figsize=(30, 60))

# 移動平均
plt.subplot(5,1,1)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.plot(date, df['sma01'], label='sma01', color='#e84a5f')
plt.plot(date, df['sma02'], label='sma02', color='#ff847c')
plt.plot(date, df['sma03'], label='sma03', color='#feceab')

# 出来高
plt.subplot(5,1,2)
plt.bar(date, df['Volume'], label='Volume', color='gray')
plt.legend()

# MACD
plt.subplot(5,1,3)
df['macd'], df['macdsignal'], df['macdhist'] = ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
plt.fill_between(date, df['macdhist'], color='gray', alpha=0.5, label='MACD_hist')
plt.hlines(0, start_date, end_date, 'gray', linestyles='dashed')
plt.legend()

# RSI
plt.subplot(5,1,4)
df['RSI'] = ta.RSI(close, timeperiod=span02)
plt.plot(date, df['RSI'], label='RSI', color='gray')
plt.ylim(0, 100)
plt.hlines([30, 50, 70], start_date, end_date, 'gray', linestyles='dashed')
plt.legend()

# ボリンジャーバンド
plt.subplot(5,1,5)
df['upper'], df['middle'], df['lower'] = ta.BBANDS(close, timeperiod=span02, nbdevup=2, nbdevdn=2, matype=0)
plt.plot(date, close, label='Adj Close', color='#99b898')
plt.fill_between(date, df['upper'], df['lower'], color='gray', alpha=0.3)
plt.legend()
```







# ローソク足

`ローソク足`：取引時間中の株価の値動き（始値、終値、高値、安値など）を1本のローソクの形で表現したもの
- **mplfinance**
    - ファイナンスに特化した可視化ライブラリ

## 1. ローソク足を表示

```py
# mplfinanceをインポート
import mplfinance as mpf

start_date = '2021-10-01'
end_date = '2022-10-01'

# 日経平均株価を取得
df = data.DataReader('^N225', 'yahoo', start_date, end_date)

date = df.index
close = df['Adj Close']

span02 = 25

# ボリンジャーバンド
df['upper'], df['middle'], df['lower'] = ta.BBANDS(close, timeperiod=span02, nbdevup=2, nbdevdn=2, matype=0)

# ローソク足用のデータフレームを作成
df_candle = df[['High', 'Low', 'Open', 'Close', 'Volume']]

# ローソク足のグラフを作成
# df_candle[100:200]のように記述し、データを絞ることも可能
mpf.plot(df_candle, type='candle', style='yahoo', figsize=(30, 15))
```

![スクリーンショット 2022-10-15 22.41.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/5a2fd4bf-6723-786c-0190-2d7d818f4056.png)


# すべてのテクニカル指標をまとめて表示する場合

```py
start_date = '2022-04-01'
end_date = '2022-10-15'

# 日経平均株価を取得
df = data.DataReader('^N225', 'yahoo', start_date, end_date)

# MACD
# ta.MACD(終値, 短期移動平均, 長期移動平均, MACDシグナル)
df['macd'], df['macdsignal'], df['macdhist'] = ta.MACD(df['Adj Close'], fastperiod=12, slowperiod=26, signalperiod=9)

# ボリンジャーバンド
# matype: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (デフォルト=SMA)
# 上のボリンジャーバンド, 移動平均, 下のボリンジャーバンド = ta.BBANDS(調整済み終値, 日経平均日数, 上のラインの標準偏差, 下のラインの標準偏差, 移動平均の計算方法)
df['upper'], df['middle'], df['lower'] = ta.BBANDS(df['Adj Close'], timeperiod=25, nbdevup=2, nbdevdn=2, matype=0)

# RSI
df['RSI'] = ta.RSI(df['Adj Close'], timeperiod=25)

# グラフに追加したい項目を代入
apds = [
    mpf.make_addplot(df['upper'], color='g'),
    mpf.make_addplot(df['middle'], color='b'),
    mpf.make_addplot(df['lower'], color='r'),
    mpf.make_addplot(df['macdhist'], type='bar', color='gray', width=1.0, panel=1, alpha=0.5, ylabel='MACD'),
    mpf.make_addplot(df['RSI'], type='line', panel=2, alpha=0.5, ylabel='RSI')
]

mpf.plot(df, type='candle', figsize=(30, 10), style='yahoo', volume=True, addplot=apds, volume_panel=3, panel_ratios=(5,2,2,1))

# 画像として保存する場合は以下に変更
# mpf.plot(df, type='candle', figsize=(30, 10), style='yahoo', volume=True, addplot=apds, volume_panel=3, panel_ratios=(5,2,2,1), savefig='株価テクニカル分析.png')
```

![スクリーンショット 2022-10-16 18.21.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/4fc345a8-275f-0517-d0f2-a8288c3eb315.png)


関連
---
- [日経平均株価/個別銘柄の移動平均と出来高を可視化](https://qiita.com/rexid/items/4148e29300f47966066e)
- [日経平均株価のチャート分析用グラフ作成](https://qiita.com/rexid/items/63d74b8e9d2bc9eeeb44)