雑記

意味がないであろうことをやったら意味がなかったけどMOTTAINAI精神で記事を上げておく。
データは以下の日経平均株価(日足)を使用する。
日経平均株価 日足 時系列データ CSVダウンロード

f:id:cookie-box:20160501123618p:plain:w750
データは 2010 年以降を取得しておく。

x_2016 <- read.table("indices_I101_1d_2016.csv", sep=",", header=FALSE, skip=1)
x_2015 <- read.table("indices_I101_1d_2015.csv", sep=",", header=FALSE, skip=1)
x_2014 <- read.table("indices_I101_1d_2014.csv", sep=",", header=FALSE, skip=1)
x_2013 <- read.table("indices_I101_1d_2013.csv", sep=",", header=FALSE, skip=1)
x_2012 <- read.table("indices_I101_1d_2012.csv", sep=",", header=FALSE, skip=1)
x_2011 <- read.table("indices_I101_1d_2011.csv", sep=",", header=FALSE, skip=1)
x_2010 <- read.table("indices_I101_1d_2010.csv", sep=",", header=FALSE, skip=1)
x <- rbind(x_2016, x_2015, x_2014, x_2013, x_2012, x_2011, x_2010)
colnames(x) <- c("DATE", "OPEN", "HIGH", "LOW", "CLOSE")
x$DATE <- as.Date(x$DATE)
x <- x[order(x$DATE),]
N <- nrow(x)

グラフ出力は以下。Mac で日本語が出なかったのですが、下記ページを参考にさせていただきました。
png/jpgなどにplotする際に適切に日本語文字列を描画する - Qiita

png("plot1.png", width=1000, height=400)
par(ps=16)
par(mar=c(8,5,2,2))
par(family="HiraMaruProN-W4")
xplot(1:N, x$CLOSE, main="日経平均株価", xlab="", ylab="終値", type="n", xaxt="n")
abline(h=seq(0, 30000, by=10000), lty=1, col="dimgray")
abline(h=setdiff(seq(0, 30000, by=2000), seq(0, 30000, by=10000)), lty=2, col="dimgray")
abline(v=which(x$DATE %in% as.Date(c("2010-01-04", "2011-01-04", "2012-01-04", "2013-01-04", "2014-01-06", "2015-01-05", "2016-01-04"))), lty=1, col="dimgray")
lines(1:N, x$CLOSE, lwd=2)
indices <- seq(1, N, by=40)
text(indices, par("usr")[3], labels=x$DATE[indices], srt=90, pos=2, xpd=TRUE)
dev.off()
k近傍法による予測

明日の終値が、今日の終値より上がるか下がるかを予測したい。
今回は、「過去の日付から今日と似た 始値、高値、安値、終値 を記録した日を集めてきて、その翌日がどうなったかを調べれば株価が上がるか下がるかがわかるはず」と考えてみる。= k近傍法(kNN)を利用する。

  • いうまでもなく、k近傍法は最も単純な部類のクラス分類法であって、特に時系列データの予測のためのものではない。
  • さらに、時系列データの予測に適用するにしても、何をもって似ているとするかはいくらでも考えられる。今回は「始値 - 高値 - 安値 - 終値 空間」での「ユークリッド距離」をもって近い遠いといっているだけ。なおかつもっと色々な工夫もありうる。

以下のページが同じ内容なので、ほぼこれを参考にする。以下のページでは、AppleGoogleMicrosoft の株価を材料に Apple の株価の増減を予測しようとしたが、上手くいくわけないというところまでちゃんと書いてある。
Using kNN Classifier to Predict Whether the Price of Stock Will Increase | R-bloggers

library(class)
library(dplyr)
library(lubridate)
set.seed(1) # 再現性のため

x$DIFF_CLOSE <- c(x$CLOSE[[1]] - 10546.44, diff(x$CLOSE))
x$INCREASE <- x$DIFF_CLOSE > 0.0

predictors <- cbind(
  lag(x$OPEN,  default=10707.51), # 2009-12-30 の値
  lag(x$HIGH,  default=10707.51), # 2009-12-30 の値
  lag(x$LOW,   default=10546.44), # 2009-12-30 の値
  lag(x$CLOSE, default=10546.44)  # 2009-12-30 の値
)

indices_train <- which(x$DATE <  as.Date("2015-01-01")) # 2014年以前を学習データに
indices_test  <- which(x$DATE >= as.Date("2015-01-01")) # 2015年以降をテストデータに

prediction <- knn(
  predictors[indices_train,],
  predictors[indices_test,],
  x$INCREASE[indices_train],
  k=3 # 距離が近い何点までをみるか
)
print(table(prediction, x$INCREASE[indices_test]))
print(mean(prediction == x$INCREASE[indices_test]))

上記のスクリプトを実行すると、52.6% の確率で、2015年以降の株価が前日から上がるか/下がるかが予測できる(要するに、参考にならない)。k を変えても、結果はあまり変わらない。

実際には下がった 実際には上がった
予測によると下がる 18 19
予測によると上がる 135 153

予測につかう材料が生の株価水準だと悪そうな気がするので、対数差分系列にしてみても、特に変わらない。

predictors <- cbind(
  diff(log(c(10611.85, 10707.51, x$OPEN[1:(N-1)]))),
  diff(log(c(10683.12, 10707.51, x$HIGH[1:(N-1)]))),
  diff(log(c(10597.41, 10546.44, x$LOW[1:(N-1)]))),
  diff(log(c(10683.06, 10546.44, x$CLOSE[1:(N-1)])))
)

近傍に株価が上がる日/下がる日のどちらかが多いときにだけ判断するようにしても、特に変わらない。

prediction <- knn(
  predictors[indices_train,],
  predictors[indices_test,],
  x$INCREASE[indices_train],
  k=2,
  prob=TRUE
)
probs <- attr(prediction, "prob") # 選択したクラスが近傍を占めていた割合
answer <- x$INCREASE[indices_test]

print(table(prediction, x$INCREASE[indices_test]))
print(mean(prediction == x$INCREASE[indices_test]))

print(table(prediction[probs > 0.5], answer[probs > 0.5]))  # 近傍にあるクラスが占める割合が多い場合のみ(閾値 0.5 なら、k が偶数のときのランダムな判断の排除)
print(mean(prediction[probs > 0.5] == answer[probs > 0.5]))