【5年分データ分析】ボリンジャーバンドを利用した逆張り戦略は効率的に稼げない？

株式相場を予測・分析するテクニカル分析の様々な手法を検証しています．
過去には，TOPIX500銘柄の過去5年分のデータを使って，移動平均線のゴールデンクロス，MACD，RSIを検証しました．

・[【5年分データ分析】ゴールデンクロスの数日後に株価は上がっているのか](https://qiita.com/MandT500/items/1f2ed62922de3037fe3c)
・[【5年分データ分析】MACDの買いサインから上がる確率を検証しました](https://qiita.com/MandT500/items/52f253bffb14306611c6)
・[投資タイミングを判断するときに必ず見てほしい指標RSIをデータ分析](https://qiita.com/MandT500/items/37c2d357e89ca6354d13)

今後も様々な手法を検証していきます．

今回はTOPIX500銘柄の過去5年分のデータを使って，
**ボリンジャーバンドの買いサインの数日後に，株価が上がっているのか**
**売りサインの数日後に，株価が下がっているのか**
を検証します．

この記事はYoutubeにもアップロードしました．是非ご覧ください！SofTalkで記事を読み上げています．
チャンネル登録していただけますと励みになります！

https://youtu.be/eHEB4ZsvZWE



# ボリンジャーバンド
有名なテクニカル分析の手法の１つです．

ボリンジャーバンドは株価の移動平均に加えて，ばらつき具合（標準偏差）を取り入れた分析手法です．

ミドルバンド，アッパーバンド，ローバンドがあり，ミドルバンドは20日の移動平均，アッパーバンドは20日の移動平均に20日の標準偏差の2倍を加えたもの，ローバンドは20日の移動平均から20日の標準偏差の2倍を引いたものです．

アッパーバンド，ローバンドが示す範囲と実際の価格の関係を見て分析を行います．

![図6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/f9615a3e-a8c9-4331-3f26-59d5b135606c.png)

武田薬品工業（TYO: 4502）を例に見ていきましょう．

2020年8月から2021年2月の株価時系列データです．

![図7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/2854878f-2ac7-c612-0cf5-561543344124.png)



基本的な使い方として，アッパーバンド，ローバンドで囲まれた領域から株価が外れた時が売りや買いのタイミングです．

上に抜けたときには高値になっていると考えられるため**売り**，下に抜けたときには安値になっていると考えられるため**買い**の判断をします．

この平均値への回帰を前提とした逆張り戦略は，価格が2σ内で変動する確率が約95％となることから，理論的に価格はそのほとんどが2σの範囲に収まるはずという考え方に基づいた投資戦略です（正規分布において，1σ（標準偏差）内に事象が存在する確率は約68％，2σ内に事象が存在する確率は約95％となる）．

武田薬品工業の例では，緑点で示したように買いタイミングが8回あります．その後の株価に注目すると，8回のうち6回は数日中に株価上昇しています．また赤点で示したように売りタイミングは2回あります．その後の株価に注目すると，2回のうち1回は数日中に株価下落しています．

この例だけを見ると，ボリンジャーバンドが短期トレードにおいて，投資タイミングを判断するときに有効だろうと推測されます．特に，この例では買いタイミングがうまく捉えることができています．

# 検証内容
武田薬品工業の例ではボリンジャーバンドを使って売りタイミングや買タイミングを判断する際の指標として有効でした．

今回の検証では，TOPIX500銘柄を対象に5年分のデータからボリンジャーバンドの有効性を検証します．大まかな流れとして，5年分のすべてのデータに対してボリンジャーバンドから外れたタイミングを見つけ，その数日後の株価上昇率を調査します．

また，検証プログラムは記事の最後に記載します．

【ボリンジャーバンドの設定期間】
20日（最も使われる）

【基準値】
・ローバンド（$2\sigma$）を下回るとき
・アッパーバンド（$-2\sigma$）を上回るとき

【検証期間】
2015年1月～2020年2月の約5年間

【対象銘柄】
TOPIX500銘柄

【株価の上昇を確認する日】
1. 1日後
2. 3日後
3. 5日後
4. 10日後

※ その他のパラメータでの検証結果は記事の一番下に載せてあるので興味ある方はご覧ください．

▼ 買いサイン
ローバンドから外れたとき，数日後に株価が上昇しているかを確認します．

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/dd6f3968-484b-761f-6241-59fe5b60d2d2.png)

▼ 売りサイン
アッパーバンドから外れたとき，数日後に株価が下落しているかを確認します．

![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/2d21ed53-e9bb-f215-932a-84543d2f3327.png)

# 検証結果
ここでは1，3，5，10日後に上昇している確率と，分布図を記載します．
その他のパラメータで検証した結果は記事の最後にまとめて記載します．
使用するデータは前述の通りTOPIX500銘柄の5年間です．

▼ 買いサイン
ローバンドを下回った数日後の株価の変化率（買いサインから何％株価が変動したか）の分布を示します．
グレーが上昇，赤が下落を表します．

![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/34364343-9e8d-a090-4bff-5cf5c0bead46.png)

ローバンドを下回った次の日（1日後）は，株価が下落する方が上昇するよりも若干多い結果となりました．3，5，10日後は上昇確率が50%を上回る結果となりました．これらの結果から，ローバンドを下回った数日後の株価は少しではありますが上昇傾向にあると言えます．

▼ 売りサイン
アッパーバンドを上回った数日後の株価上昇率（売りサインから何％株価が変動したか）の分布を示します．

![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/874000f1-dc0b-dfd3-bb89-e6b226134654.png)

アッパーバンドを上回った1日後は，株価が下落した確率が51.73%となり，株価が下落しやすいことがわかります．しかし，3，5，10日後は下落確率が50%を下回るので，むしろ株価が上昇する方が多かったことがわかります．したがって，3，5，10日の期間で株を売買する場合は，アッパーバンドを上回ったタイミングを売りサインとすることは適切でないと言えます．


# まとめ
今回は，株価移動平均にばらつき具合（標準偏差）を取り入れた分析手法であるボリンジャーバンドを利用し，価格がアッパーバンド（+2σ）を上回ったときに売り，ローバンド（−2σ)を下回ったときに買いとする，平均値への回帰を前提とした逆張り戦略を検証しました．

今回の検証結果から，買いサインのタイミングから株価上昇傾向が見られましたが，その上昇確率は決して高いものではなく，効率的に稼げるものではないということがわかりました．また，売りサインのタイミングから1日後は株価の下落傾向が見られましたが，3，5，10日後の株価はむしろ上昇する確率の方が高いということがわかりました．したがって，今回の検証からはボリンジャーバンドを使った逆張り戦略は効率的に稼ぐための指標だとは言えません．

しかし，最初の武田薬品工業の例にあるように，ボリンジャーバンドを使った逆張り戦略は，売りタイミングや買いタイミングをうまくとらえられることもあります．今後の課題としては，ボリンジャーバンドを使った逆張り戦略が生かせるタイミングやその他のテクニカル指標（MACDなど）と組み合わせて，ボリンジャーバンドが生かせないかを検証していきたいと思います．


<font color="DarkGray" size=1>
＜Youtube＞
分析動画を投稿しています．
検証結果を多くの方に見てもらえると嬉しいです．
[https://www.youtube.com/channel/UCKM_EhOxMfXkcLFOwAdEKcQ](https://www.youtube.com/channel/UCKM_EhOxMfXkcLFOwAdEKcQ)
↑チャンネル登録していただけますと励みになります。
</font>

https://youtu.be/Jf9qfrWSPfI

https://youtu.be/S30CLeL5_M0

<font color="DarkGray" size=1>
＜過去記事＞
・[日経225全銘柄の投資効率を検証](https://qiita.com/MandT500/items/f4aaafa0de824dab92c2)
・[【5年分データ分析】ゴールデンクロスの数日後に株価は上がっているのか](https://qiita.com/MandT500/items/1f2ed62922de3037fe3c)
・[【5年分データ分析】MACDの買いサインから上がる確率を検証しました](https://qiita.com/MandT500/items/52f253bffb14306611c6)
・[コロナ・ショック後から株価上昇し続けている１５銘柄](https://qiita.com/MandT500/items/ede92d7c322d0bbf32dd)
</font>



# 付録（分析プログラム）
プログラム内で使用している自作の関数や株価データの取得方法は以下の記事をご参照ください。（執筆中）
・[株分析ツールの使い方（備忘録）](https://qiita.com/MandT500/items/f845abb8ce5a3a0729b)

```python
import trade_package.get as get
import trade_package.tech as tech
import pandas as pd
import matplotlib.pyplot as plt

# 銘柄コードの読み込み
stocks = get.topix500()
# 結果保存用データフレーム
df_roc1_u =pd.DataFrame()
df_roc3_u =pd.DataFrame()
df_roc5_u =pd.DataFrame()
df_roc10_u =pd.DataFrame()
df_roc1_l =pd.DataFrame()
df_roc3_l =pd.DataFrame()
df_roc5_l =pd.DataFrame()
df_roc10_l =pd.DataFrame()
# 株価変化率計算
def roc(df, day):
    return (df.shift(-day)["Close"]-df["Close"])/df["Close"]*100
# ヒストグラム作成
def hist(df_roc, later, filename):
    # x軸の幅
    r_max = 40
    r_min = -40
    fig, ax = plt.subplots(figsize=(16, 12))
    # ヒストグラム作成
    n, bins, patches = ax.hist(df_roc, range=(r_min, r_max), bins=40, color="lightgray", align='left', density=True)
    # 負の変化率のbinを赤色に変更
    for i in range(20):
        patches[i].set_facecolor('#ffb6b9')
    # グラフの設定
    ax.tick_params(labelsize=20)
    ax.set_xlabel('Rate of Change[%]', fontsize=24)
    ax.set_ylabel('Frequency', fontsize=24)
    ax.set_ylim(0,0.21)
    ax.set_xticks([i for i in range(-42,42,2)])
    ax.set_xticklabels(['{}~{}'.format(i, i+2) for i in range(-42,42,2)], rotation=90)
    ax.set_title('Bollinger Bands (period=20)', fontsize=24)
    prob = len(df_roc[df_roc[0]>0])/len(df_roc[0])*100
    prob_bar = 100-prob
    ax.text(-31, 0.115,'下落確率', fontsize=40, color="#ffb6b9",fontname="MS Gothic")
    ax.text(-30, 0.1,f'{round(prob_bar,2)}%', fontsize=40, color="#ffb6b9")
    ax.text(19, 0.115,'上昇確率', fontsize=40, color="lightgray",fontname="MS Gothic")
    ax.text(20, 0.1,f'{round(prob,2)}%', fontsize=40, color="lightgray")
    ax.text(-40, 0.175,f'{filename[5:]}日後', fontsize=40, fontname="MS Gothic")
    print(filename,round(prob,2),round(prob_bar,2))
    # グラフ保存
    plt.savefig('{}.png'.format(filename), bbox_inches="tight")
    
for code in stocks.code:
    print(code)
    # 価格データ取得
    price_data = get.price(code)
    data = price_data.copy()
    # dataフレームにボリンジャーバンドのデータを追加
    tech.bb(data, period=20)
    # ローーバンドを下回るか計算
    data["sign_l"] = data["Close"]-data["bb_l"]
    # アッパーバンドを上回るか計算
    data["sign_u"] = data["bb_u"]-data["Close"]
    # 数日後の株価変動率計算
    data["roc1"]   = roc(data,1)
    data["roc3"]   = roc(data,3)
    data["roc5"]   = roc(data,5)
    data["roc10"]  = roc(data,10)
    # 結果データフレームにボリンジャーバンドをから出たデータフレームのみ追加
    df_roc1_u = pd.concat([df_roc1_u, data[data["sign_u"]<0].roc1])
    df_roc3_u = pd.concat([df_roc3_u, data[data["sign_u"]<0].roc3])
    df_roc5_u = pd.concat([df_roc5_u, data[data["sign_u"]<0].roc5])
    df_roc10_u = pd.concat([df_roc10_u, data[data["sign_u"]<0].roc10])
    
    df_roc1_l = pd.concat([df_roc1_l, data[data["sign_l"]<0].roc1])
    df_roc3_l = pd.concat([df_roc3_l, data[data["sign_l"]<0].roc3])
    df_roc5_l = pd.concat([df_roc5_l, data[data["sign_l"]<0].roc5])
    df_roc10_l = pd.concat([df_roc10_l, data[data["sign_l"]<0].roc10])

# ヒストグラム作成
hist(df_roc1_l,1,'l_roc1')
hist(df_roc3_l,3,'l_roc3')
hist(df_roc5_l,5,'l_roc5')
hist(df_roc10_l,10,'l_roc10')

hist(df_roc1_u,1,'u_roc1')
hist(df_roc3_u,3,'u_roc3')
hist(df_roc5_u,5,'u_roc5')
hist(df_roc10_u,10,'u_roc10')
```
# 追加検証（その他のパラメータ）
▼ 買いサイン
ローバンドを下回った数日後の株価の変化率（買いサインから何％株価が変動したか）の分布を示します．
グレーが上昇，赤が下落を表します．

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/1a50db72-701d-4ed4-3de7-a56d83134354.png)

▼ 売りサイン
アッパーバンドを上回った数日後の株価上昇率（売りサインから何％株価が変動したか）の分布を示します．

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906836/059401b6-0514-eece-51cd-ca018755b299.png)