シグナルの生成と検証

前回「スプレッドの構築」の続き。

とりあえず、写経したところまでメモ。

各種設定値およびデータの作成。

# ローリング期間
> window_length <- 10

# データ開始日・終了日
> start_date<-"2013-01-01"
> end_date<-"2013-12-31"

# データ範囲文字列の作成
> range<-paste(start_date, "::", end_date, sep="")
> range
[1] "2013-01-01::2013-12-31"

# 株価データ取得
> x<-TOPIX[range, 4]
> y<-UFJ[range,6]

> dF<-cbind(x,y)
> head(dF)
           YJ998405.Close YJ8306.Adjusted
2013-01-04         888.51             484
2013-01-07         881.06             476
2013-01-08         871.88             462
2013-01-09         879.05             469
2013-01-10         889.02             474
2013-01-11         898.69             479
> names(dF)<-c("TOPIX","UFJ")

次に線形回帰の回帰係数を取得する関数の定義と、ローリング関数を定義する。

# β計算用関数
> run_regression<-function(dF){
+  return(coef(lm(y ~ x-1, data=as.data.frame(dF))))
+ }

# ローリング関数
# rollapplyのzはデータ、widthはローリング期間、FUNは適用関数、by.columnはTRUEの場合は適用関数(FUN)が各カラムに適用される
> rolling_beta<-function(z, width){
+  rollapply(z, width=width, FUN=run_regression, by.column=FALSE, align="right")
+ }

# βの計算
> betas<-rolling_beta(diff(dF), window_length)

> betas <- rolling_beta(diff(dF), window_length)
> head(betas)
           [,1]
2013-01-04   NA
2013-01-07   NA
2013-01-08   NA
2013-01-09   NA
2013-01-10   NA
2013-01-11   NA
> data<-merge(betas, dF)
> head(data)
           betas  TOPIX UFJ
2013-01-04    NA 888.51 484
2013-01-07    NA 881.06 476
2013-01-08    NA 871.88 462
2013-01-09    NA 879.05 469
2013-01-10    NA 889.02 474
2013-01-11    NA 898.69 479
> data$spread<-data$UFJ-lag(betas,1)*data$TOPIX
> returns<-diff(dF)/dF
> return_beta<-rolling_beta(returns, window_length)
> data$spreadR<-diff(data$UFJ)/data$UFJ-return_beta*diff(data$TOPIX)/data$TOPIX
> tail(data)
               betas   TOPIX UFJ     spread       spreadR
2013-12-20 0.5370756 1261.64 654 -23.596105 -0.0085655660
2013-12-24 0.5370756 1257.55 654 -21.399465  0.0017467610
2013-12-25 0.5370756 1258.18 654 -21.737823 -0.0002689263
2013-12-26 0.5370756 1279.34 669 -18.102343  0.0135384127
2013-12-27 0.5370756 1290.07 677 -15.865165  0.0073497779
2013-12-30 0.5370756 1302.29 694  -5.428229  0.0194560438
> 

プロットする。

> par(mfrow=c(2,1))
> plot(data$spread)
> plot(data$spreadR)

さて、次に価格差スプレッドを可視化する。

> threshold<-sd(data$spread, na.rm=TRUE)
> threshold
[1] 19.12683

# 可視化
> plot(data$spread, main="UFJ vs TOPIX In-Sample", cex.main=0.8, cex.lab=0.8, cex.axis=0.8)
> abline(h=threshold, lty=2)
> abline(h=-threshold, lty=2)

次はここまで計算したスプレッドを元に、買いシグナルと売りシグナルを生成させ、それをグラフにプロットする。

# スプレッドの描画
> plot(data$spread, main="UFJ vs TOPIX In-Sample", cex.main=0.8, cex.lab=0.8, cex.axis=0.8)
> abline(h=threshold, lty=2)
> abline(h=-threshold, lty=2)

# 買いシグナルと売りシグナルの生成
# 単純に標準偏差(1σ)より大きいスプレッドの場合は買い、-1σより小さい場合は売りとする。
> buy_signal_count<-ifelse(data$spread > threshold, 1, 0)
> sell_signal_count<-ifelse(data$spread < -threshold, -1, 0)
> data$signalCount<-buy_signal_count+sell_signal_count

# シグナル結果をスプレッドのグラフ上に描画
> point_type<-rep(NA, nrow(data))
> buy_index<-which(data$signalCount == 1)
> sell_index<-which(data$signalCount == -1)
> point_type[buy_index] <- 21  #丸印
> point_type[sell_index] <- 24 #上三角印(△)
> points(data$spread, pch=point_type)

シグナル数は下記で計算可能。

> num_of_buy_signals<-sum(buy_signal_count, na.rm=TRUE)
> num_of_sell_signals<-sum(abs(sell_signal_count), na.rm=TRUE)
> num_of_buy_signals
[1] 34
> num_of_sell_signals
[1] 27
>