カルマンフィルターは株価のトレンド予測に利用できるか
この記事の概要について
株価のトレンドの予測のためのカルマンフィルターの実装とその感想です。
結論から言うと「短期については利用できるかも」です。
google colabの上で動かしてます。
カルマンフィルターとは何か
もともとロボットやロケットの制御のためなどに使われてるもので、誤差のある観測値を利用して、そのシステムの状態がどうなっているか推定するためのものです。
今回はその中でも一番単純なものを使ってます。
前提
株価の変動をある確率分布に従って変動していると考えて、それに基づいて予測しているので指標の一つとしてみてください。
また、今回では株価の変動の潜在的な仕方およびそれが実際に変化する仕方は、正規分布に従ってると仮定しているので非現実的な仮定をしています。
なので、株価がある程度安定的に動いているものに対してはしっかり働いてくれる一方で、急な変化にはついていけないと思われます。
計算式(実装)
計算式がなぜそうなるかはめんどくさいので、見たい人はwikiを参考にしてください。
実装の上では、以下の関数を定義してあげれば問題ないです。
数列を引数として受け取り、それと同じ長さの数列を返します。
import numpy as np
def kalman(s,x,P):
res_x=[]#その時点における推定される位置
res_v=[]#その時点における推定される速度
for i in range(len(s)):
Z=np.array([s[i]])
y=Z-H@x
S=H@P@H.T+R
K=P@H.T@np.linalg.inv(S)
x=x+K@y
P=(I-K@H)@P
#predicion
x=(F@x)+u
P=F@P@F.T
res_x.append(x[0,0])
return res_x
x=np.array([[0.], [0.]])#一つ目が位置で二つ目が速度を表す
P=np.array([[1000., 0.], [0., 1000.]])#共分散行列
u=np.array([[0.], [0.]])#外力だけど今回はないと想定
F=np.array([[1., 1.], [0, 1.]])#位置と速度の関係の定義
H=np.array([[1., 0.]])
R=np.array([[1.]])
I=np.array([[1., 0.], [0., 1.]])
t=[1,2,4,3,7,4,6,5.2]#入れる数列
print(kalman(t,x,P))
結果は以下のようになりました。
[0.999000999000999,2.9980029930179533,5.332389258923225,4.500249550392171,7.299929903069252,6.400310235003376, 7.000316132748338, 6.886095984845674]
与えた数列に今回は特に規則性がないので、正しく予想できませんが、確率分布に従って乱数を発生させるとなかなかの精度で推定してくれます。
実際に株価に適用してみた
この記事を書いているのが8月14日で、コロナで株価が冷えて二番底?になってそろそろ上がってくれるかな?みたいな時期です。
カルマンフィルターによって得た値を、本来の株価であると想定すると、株価はそれに戻ろうとすると考えられます。
適用してみた銘柄で、特徴的だったものをあげます。
その一つが、ENEOSホールディングス(5020.T)です。
一見何かわからないのですが、フィルターに当てはめ始める時期が異なります。
2018年の12月ごろには、トランプ政権による影響で株式市場全体が急落し、2020年の2~3月頃には、コロナの影響で株価が急落しています。
これらのイベントは、外れ値もいいところなので、いきなりカルマンフィルタの推定が大きくずれてることがわかります。
なので、それぞれの急落のイベント後からまたカルマンフィルタを適用してあげることで、比較的良い推定ができているとわかります。
結論
特に大きなイベントが起きなければ、一つの指標(特に買いを入れるときの)として使えると思います。
個人的には、ある時点のカルマンフィルタの値と株価の中間まで上がると考えて他の指標も合わせて買いを入れてます。
ただ、株価が大きく変化した時は適用する初期値をずらさないとまずいでしょう。
追加
デイトレでも使えるんじゃないかなと思ってます。
むしろデイトレの方が値動きは正規分布に近そうなので...
何か意見があれば教えていただけるとありがたいです。
あとこのカルマンフィルタは、そのままロボットの方に利用できます。