技術大全

「ボリンジャーバンド ±2σ 内側の確率は95%なので逆張り…」は大きな間違い

こんにちは、オノノです。

今回は、多くの人が売買シグナルとしている「ボリンジャーバンド ±2σ 内側の確率は95%なので逆張り…」について、認識が間違っているよということを記述しています。

世間一般のボリンジャーバンドの見方は「+2σを超えることは長く続かないので+2σに納まる ≠ +2σを超えた後には価格は下降する」ですが、これは勘違いです。

ボリンジャーバンドの各線は標準偏差を示しますが、「統計学上データは +1σ から -1σ の間に 68.3%、+2σ から ー2σ の間に 95.5% 入るため、±2σ を超える/割り込むことは 5%以下なので、+2σ を超えたら買われすぎということで売り -2σ を割り込んだら売られすぎということで買う」ということは正しそうですが間違いです。

これは統計学的にその数値が有効なのは価格が正規分布であるときという条件が必要だからです。

オノノが言っているように「世間一般の見方は本当に間違い??」を立証するために「為替の値動きは正規分布に従わないよ!」という視点から書きたいと思います。

実行環境

・maxOS High Sierra
・Anaconda Python3.5 の仮想環境
・Jupyter Notebook
・PyMC2

使用する為替データは USD-JPYの15分足 2005.01.01〜2019.12.31 終値で最新から10000区間分を使います。

今回は「為替の値動きが本当に正規分布に従っているのか?」について、PyMC2を使用してMCMC法でパラメータを推測してみたいと思います(PyMC2や確率分布あたりの詳細な説明は省かせていただきます)

MCMCとは?

MCMCは確率的アプローチによってベイズ推論を行う手法のことです。

では、ベイズ推論とは何でしょう?簡略化した頻度主義(一般的な統計学)とベイズ主義の違いを簡単にまとめます。

  • 頻度主義(統計学)は、唯一絶対の母集団の確率分布パラメータが存在していると考え、その確率分布に従ってたまたま今のデータが得られたとして母集団の確率分布パラメータの議論をする
  • ベイズ主義は、母集団の確率分布のパラメータは決まっていないものとして考え、得られたデータからそのデータが得られる確率が最も高くなるような母集団の確率分布パラメータを推測していく

これらは似て非なるものですが、得られる結果は似たようなものになることが多いです。

ベイズ的手法は数学的に難解なので直接は使えないため、モンテカルロ法を使用した確率的アプローチが使用されることが多いです(これがMCMC法です)

今回は PyMC を用いて MCMC法 でデータが従っているであろう確率分布のパラメータを推測していきます。

為替データを見る

まずは為替データを見てみましょう。

mcmc.py

import scipy.stats as stats
from IPython.core.pylabtools import figsize
import numpy as np
import matplotlib.pyplot as plt
import pymc as pm
import pandas as pd
%matplotlib inline

df = pd.read_csv(‘USDJPY_UTC_15Mins_Bid_2003.09.01_2017.11.17.csv’, sep=’,’)
value = np.array(df.loc[:, “Close”])[::-1] #新しい順にNumpy arrayにする
print(df.head(3))

figsize(14, 13)

obs = 10000
colors = [“#348ABD”, “#A60628”, “#7A68A6”, “#467821″] #plotの色

_previous_day = np.roll(value, -1) #差を求めるために1つずつずらす
sub_value = (value – _previous_day)[:obs] #10000区間の終値の差

plt.subplot(211)
plt.plot(sub_value[::-1]) #古い順で表示
plt.grid()

plt.subplot(212)
plt.hist(sub_value, bins=300, histtype=”stepfilled”,
density=True, color=colors[0], label=”sub value”)
plt.vlines(sub_value.mean(), 0, 13, “k”, “–“, linewidth=0.5)
plt.xlim(-0.67, 0.6)
plt.legend()

実行結果

Time (UTC) Open High Low Close Volume
0 2015.01.01 10:30:00 116.49 116.57 116.43 116.53│363.0
1 2015.01.01 10:45:00 116.52 116.55 116.36 116.43│411.0
2 2015.01.01 11:00:00 116.42 116.44 116.35 116.38│324.0


ヒストグラムを見ると確かに正規分布っぽい。

これがファイナンス分野で正規分布として仮定されている理由の一つみたいです。(因みに1番の理由は正規分布が数学的にとても扱いやすいからです)

しかし、これは本当に正規分布だろうか…

例えば、グラフを見ると-0.65あたりの数値が出現してますが、正規分布と仮定しヒストグラムから多めに見積もって標準偏差を0.1としても、6σ以上の数値で下側累積確率が4.016e-11とかいうとんでもない数値叩き出してますよ!!!

確かに株や為替ではこの辺の数値は珍しくありませんが…

若干正規分布に従うのか怪しいですが、このままMCMCで正規分布のパラメータを推測してみましょう。

PyMCで正規分布のパラメータを推測する

ということで、これらのデータが正規分布から得られたと仮定して平均と標準偏差を推測していきます。

まずMCMCを使用するために平均と標準偏差の事前分布を設定します。

今回は、ヒストグラムを見て

  • 平均(mu):平均0 標準偏差0.05の正規分布
  • 標準偏差(std):0~0.3の一様分布

にしました。

PyMC2では、正規分布のパラメータとして、分散の逆数である精度(τ)を使用します。

事前分布の確認

mcmc.py

figsize(11, 6)
#正規分布で近似
mu = pm.Normal(“mu”, 0, 1./ 0.05**2) #平均の事前分布は正規分布
tau = 1. / pm.Uniform(“std”, 0, 0.3)**2 #標準偏差の事前分布は一様分布

#結果のプロット
plt.subplot(211)
x = np.linspace(-0.3, 0.3, 100)
a_y = stats.norm.pdf(x, 0, scale=0.05)
plt.fill_between(x, 0, a_y, color=colors[0], linewidth=2,
edgecolor=colors[0], alpha=0.6)
plt.title(“mu prior”)
plt.xlim(-0.3, 0.3)
plt.tight_layout()
plt.grid()

plt.subplot(212)
x = np.linspace(-0.05, 0.35, 200)
b_y = stats.uniform.pdf(x, 0, 0.3)
plt.fill_between(x, 0, b_y, color=colors, linewidth=2,
edgecolor=colors, alpha=0.6)
plt.title(“std prior”)
plt.xlim(-0.05, 0.35)
plt.tight_layout()
plt.grid()

事前分布の実行結果


各種パラメータの事前分布を決めたら、データを保存してMCMCを実行します。

PyMCの実行

mcmc.py

#データが正規分布から得られたとする
obs_1 = pm.Normal(“obs_1”, mu, tau, value=sub_value, observed=True)

#データと平均、精度をモデルにしてMCMCの実行
model_1 = pm.Model([obs_1, mu, tau])
mcmc_1 = pm.MCMC(model_1)
#最後の30000回の内、さらに間引いたものをsampleとして使用
mcmc_1.sample(100000, 70000, 3)

figsize(11, 6)

#muとstdの事後分布を取り出す
mu_samples = mcmc_1.trace(“mu”)[:]
std_samples = mcmc_1.trace(“std”)[:]

#事後分布のプロット
plt.subplot(211)
plt.hist(mu_samples, bins=30, alpha=0.8, histtype=”stepfilled”,
color=colors[0], density=True)
plt.title(“mu samples”)
plt.grid()
plt.tight_layout()

plt.subplot(212)
plt.hist(std_samples, bins=30, alpha=0.8, histtype=”stepfilled”,
color=colors, density=True)
plt.title(“std samples”)
plt.grid()
plt.tight_layout()

事後分布の結果


事後分布とは、事前分布と尤度の積で表されて、簡単に言うとデータが従っていそうな確率分布のパラメータの分布の事です。(ここがベイズ主義の分かりにくいところですが、ベイズ主義では母集団のパラメータは定まっていないため、母集団のパラメータも何かの確率分布に従っているのです。)

なので、平均と標準偏差の事後分布はこのようになりました。
収束して妥当そうな分布に落ち着いています。

続いて、得られた事後分布のパラメータを使用してscipyで正規分布を描き、データのヒストグラムと重ねてみましょう。ヒストグラムは面積が1になるように正規化してあります。

得られた事後分布から正規分布を描く

mcmc.py

figsize(11, 7)

mu_mean = mu_samples.mean() #平均の事後分布の平均
std_mean = std_samples.mean() #標準偏差の事後分布の平均

print(“mu_mean”, mu_mean)
print(“std_mean”, std_mean)

#重ね合わせ
x = np.linspace(-0.67, 0.6, 500)
a_y = stats.norm.pdf(x, mu_mean, scale=std_mean)
plt.fill_between(x, 0, a_y, color=colors[0], linewidth=2,
edgecolor=colors[0], alpha=0.6, label=”norm dist\nmu:%.5f\nstd:%.5f” %(mu_mean, std_mean))
plt.hist(sub_value, bins=300, histtype=”stepfilled”, alpha=0.7,
density=True, color=colors, label=”sub value”) #densityは面積が1になるよう正規化
plt.title(“normal sample”)
plt.xlim(-0.67, 0.6)
plt.legend(loc=”upper left”)
plt.tight_layout()
plt.grid()

最終結果

mu_mean 0.00012458117978842259
std_mean 0.05501015709933814

結果から言えること

まず一目見て気づくのは、平均の周辺は全く尖度が足りていません。
また、下図のように±0.15辺りからは正規分布で対応できていないです。

結果を見ると正規分布であることを仮定するのはやはり厳しいように見えます。特に問題なのは、やはり±0.15以降の出現率を極度に過小評価してしまっている点です。例えば、この正規分布では+0.30となる確率が2.5e-8です。正規分布と仮定してしまうと、この過小評価によって大損害を被る可能性があります。


得られた分布から値動きを再現(3000区間分生成)しましたが、良くある為替の動きに見えますね。

まとめ

以上より、「統計学上データは +1σ から -1σ の間に 68.3%、+2σ から ー2σ の間に 95.5% 入るため、±2σ を超える/割り込むことは 5%以下なので、+2σ を超えたら買われすぎということで売り -2σ を割り込んだら売られすぎということで買う」ということは、為替の値動きは正規分布に従わないため間違いです。

友だち追加

 

ABOUT ME
オノノ
こんにちは専業トレーダーのオノノです。 元々はIT企業でプログラマーとしてシステム開発に携わっていました。 このサイトでは国内外問わない投資情報や分析情報など、あなたに役立つ情報を発信していこうと考えています。
error: Content is protected !!