【投資・R】統計や機械学習使って"金持ち"になりたい~欠損値補填~【第2話】


前回はこちら。株のチャート再現

前回のあらすじ

・株よくわからんわ
・推移plotするわ
・ボリンジャーバンドスレスレなら買いじゃないか
(結局株はわかってない)

今後の目的
・ボリンジャーバンドも下がり続けるかもしれないし、今後どう動くか気になる
・周期とか考えて"上がるタイミング"とか"下がるタイミング"を知って"買い"や"売り"のタイミングをつかみたい

今回の話
・周期分析のための時系列データ前処理

今回の記事は不得意な数学部分に片足を突っ込んだので、
間違っている部分は優しめにぶっ叩いてほしい。
できればアホでもわかるように。
ELI5でお願いします。

周期性の分析

前回作成した移動平均を見てみます。

plot(get_ind$ind, df3$M_line, type="l", col="black")

コイツです。

分析に入る前に問題がありまして、今まで小技を使ってごまかしていたんですが、
このデータには土日祝日などが含まれていません。

株式市場のやっている244日のデータしかないので、土日や祝日を埋めてやる必要があります。
(でも土日は毎年あるわけだし、このデータはすでに244日という周期で成り立っているのでは???)
なんて考えはとりあえず置いておいて。
経験にもなるし補填してみるか。

欠損値の補填

library(dplyr)
df3$ind <- get_ind$ind
df_tbl<-left_join(plot_label, df3, by = "ind")
head(df_tbl, 100)

カレンダーの時刻と、SQLでいうleft outer joinを行ってみるとこのようになります。
土日がすっかり抜けています。
68行目まで抜けているのは前回カレンダーの時刻を発生させるときに多めに発生させたのと、
移動平均の処理で発生した部分です。
とりあえず68行目までは削除して、df_tblのind列も1からに修正します。
また、tailにも余白があるのでtailで確認して削除しました。

df_tbl_2 <- df_tbl[-c(1:68),]
df_tbl_2$ind <- c(1:nrow(df_tbl_2))
tail(df_tbl_2,100)
df_tbl_2 <- df_tbl_2[-c(3119:3134),]

さて、NAの扱いですが、単純に2日間だけ空いているならば前後の5日間の平日で数値の平均をとって埋めてもいいでしょう。
しかし、お正月やゴールデンウィークのように不規則に一週間丸々抜けている箇所もあります。

他の列情報があり、それでいて欠損しているならば重回帰やSVMやランダムフォレストの出番なわけですが・・・
パッケージでいうとForImpとかが使えそう。

考える補填方法は、周辺の数値の平均値をとるとか。
周辺の値から回帰して埋めるとか。
なんにせよ線形補間がうれしいです。
滑らかにつないでくれる補填を探し、手法をいくつか使ってみます。

test.day<-df_tbl_2$day[1:365]
test.index<-df_tbl_2$ind[1:365]
test.val<-df_tbl_2$open[1:365]

library(zoo)

fill_approx<-na.approx(test.val)
fill_spline<-na.spline(test.val)
fill_spline_natural<-na.spline(test.val,method="natural")

xaxis_length<-20
set_at <- seq(1, length(test.val), length=xaxis_length)


par(mfrow=c(4,1))

par(oma=c(5, 4, 4, 2))

par(mar=c(2,2,2,2))
plot(test.index,test.val,type="p",main="missing",xlab="",ylab="",xaxt="n")
axis(side=1,tck=1,lty="dotted",labels=F)
par(mar=c(2,2,2,2))
plot(test.index,fill_approx,type="p",main="approx",xlab="",ylab="",xaxt="n")
axis(side=1,tck=1,lty="dotted",labels=F)
par(mar=c(2,2,2,2))
plot(test.index,fill_spline,type="p",main="spline",xlab="",ylab="",xaxt="n")
axis(side=1,tck=1,lty="dotted",labels=F)

par(mar=c(2,2,2,2))
plot(test.index,fill_spline_natural,type="p",main="spline_natural",xlab="",ylab="",xaxt="n")
axis(side=1,tck=1,lty="dotted",labels=F)

axis(side=1, labels=as.character(test.day)[set_at], las=2, at=set_at)

こうして比較してみると、approxは単純に直線で埋めています。
あまり良いセンスとは思えません。
実際のデータが無いので、もし土日も株式市場が開いているような平行世界があって、実は直線のほうが正しい。なんてこともあるかもしれませんが、ここは勝手に却下とさせて頂きます。

splineとspline_naturalはそんなに差は無くどちらも滑らかにつないでくれています。
どちらを選んでも良さそうです

さて今回必要だったのは移動平均だったので移動平均の平滑化を単純スプラインで行って終わりです。

fill_data<-NULL
fill_data <- data.frame(ind = df_tbl_2$ind,
                        day = df_tbl_2$day,
                        move = na.spline(df_tbl_2$M_line))

次回は周期性を分析

回すお金がないんじゃー