Introduction
This is the home page of the article "Nonparametric volatility prediction", written by Jussi Klemelä.
Abstract of the article
Volatility prediction can be defined as the estimation of the conditional expectation of a squared return of a financial asset. Many of the classical nonparametric regression estimators can be applied in volatility prediction. Examples of nonparametric estimators include moving averages and kernel estimators. However, it has been difficult to beat some parametric estimators from the GARCH family using nonparametric estimators. We review some promising suggestions for nonparamteric volatility prediction.
Reference
@article{wiresvola, title = {Nonparametric volatility prediction}, author = {Klemel\"a, J.}, year = {2020}, journal = {{WIRE}s Comput. Statist.}, volume = {12}, number = {3}, note = {e1491}, web = {https://doi.org/10.1002/wics.1491}, }
Reproducing the computations
Install software
source("http://jklm.fi/regpro/regpro.R")
Read SP500 Data
file<-"http://jklm.fi/statopti/GSPC.csv" gspc0<-read.csv(file=file) gspc<-gspc0[,6] n0<-length(gspc) retu<-gspc[2:n0]/gspc[1:(n0-1)] r<-log(retu) n<-length(r) times<-matrix(0,n,1) delta<-1/251.63 alku<-1950+0/12 for (i in 1:length(times)) times[i]<-alku+(i-1)*delta
Figure 1
t0<-1000 # GARCH(1,1) for SP500: Rolling library("tseries") roll<-2500 t0<-250 step<-1 ota<-seq(t0+1,n,step) alpha0t<-matrix(0,n,1) alpha1t<-matrix(0,n,1) betat<-matrix(0,n,1) sigmat<-matrix(0,n,1) for (t in 1:t0){ now<-r[1:t] sigmat[t]<-sd(now) } for (i in 1:length(ota)){ t<-ota[i] # if (i==length(ota)) up<-n else up<-ota[i+1]-1 if (is.null(roll)) beg<-1 else beg<-max(1,t-roll) now<-r[beg:t] # ga<-garch(now,control=garch.control(trace=FALSE)) #-mean(y)) alpha0<-as.numeric(ga$coef[1]) alpha1<-as.numeric(ga$coef[2]) beta<-as.numeric(ga$coef[3]) alpha0t[t]<-alpha0 alpha1t[t]<-alpha1 betat[t]<-beta sigmat[t]<-sqrt(alpha0+alpha1*r[t]^2+beta*sigmat[t-1]^2) } sigmat[1]<-sigmat[2] # one-day prediction hori<-1 potti<-matrix(0,n,2) potti[,1]<-r^2 for (i in (hori+1):n) potti[i,2]<-sigmat[i-hori]^2 # prediction of realized volatility realvola<-matrix(0,n,1) observed<-matrix(0,n,1) hori<-20 for (i in (1+hori):n){ observed[i]<-sum(r[(i-hori+1):i]^2) # for (eta in 1:hori){ sigma<-sigmat[i-hori] a0<-alpha0t[i-hori] a1<-alpha1t[i-hori] b<-betat[i-hori] barsigma2<-a0/(1-a1-b) vest<-barsigma2+(a1+b)^(eta-1)*(sigma^2-barsigma2) # realvola[i]<-realvola[i]+vest } } sotti<-matrix(0,n,2) sotti[,1]<-observed sotti[,2]<-realvola # Figure 1 cex.axis<-1.5 cex.lab<-1.5 cex.sub<-1.5 cex<-1.5 lty<-1.5 ota<-c(1000:n) matplot(times[ota],potti[ota,],type="l",lty=1,ylim=c(0,0.005), xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) mtext("squared return",side=2,cex=1.5,line=2.4) title(sub="(a)",cex.sub=cex.sub) ota<-c((n-400):n) matplot(times[ota],potti[ota,],type="l",lty=1,ylim=c(0,0.0006), xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) mtext("squared return",side=2,cex=1.5,line=2.4) title(sub="(b)",cex.sub=cex.sub) ota<-c(1000:n) matplot(times[ota],sotti[ota,],type="l",lty=1,ylim=c(0,0.008), xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) mtext("realized volatility",side=2,cex=1.5,line=2.4) title(sub="(c)",cex.sub=cex.sub) ota<-c((n-400):n) matplot(times[ota],sotti[ota,],type="l",lty=1, #,ylim=c(0,0.008)) xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) mtext("realized volatility",side=2,cex=1.5,line=2.4) title(sub="(d)",cex.sub=cex.sub)
Figure 2
t0<-1000 eta<-1 # GARCH(1,1) for SP500: Rolling library("tseries") roll<-2500 t0<-250 step<-1 ota<-seq(t0+1,n,step) alpha0t<-matrix(0,n,1) alpha1t<-matrix(0,n,1) betat<-matrix(0,n,1) sigmat<-matrix(0,n,1) for (t in 1:t0){ now<-r[1:t] sigmat[t]<-sd(now) } for (i in 1:length(ota)){ t<-ota[i] # if (i==length(ota)) up<-n else up<-ota[i+1]-1 if (is.null(roll)) beg<-1 else beg<-max(1,t-roll) now<-r[beg:t] # ga<-garch(now,control=garch.control(trace=FALSE)) #-mean(y)) alpha0<-as.numeric(ga$coef[1]) alpha1<-as.numeric(ga$coef[2]) beta<-as.numeric(ga$coef[3]) alpha0t[t]<-alpha0 alpha1t[t]<-alpha1 betat[t]<-beta sigmat[t]<-sqrt(alpha0+alpha1*r[t]^2+beta*sigmat[t-1]^2) } sigmat[1]<-sigmat[2] gcspe<-matrix(0,n,1) diffet<-matrix(0,n,1) for (i in (t0+1):(n-eta)){ sigma<-sigmat[i] a0<-alpha0t[i] a1<-alpha1t[i] b<-betat[i] barsigma2<-a0/(1-a1-b) hava<-r[i+eta] vest<-barsigma2+(a1+b)^(eta-1)*(sigma^2-barsigma2) diffet[i+eta]<-abs(vest-hava^2)^2 gcspe[i+eta]<-sum(diffet[1:(i+eta)],na.rm=TRUE) } # Heston-Nandi for SP500: Rolling library(fOptions) roll<-2500 t0<-250 alpha0t<-matrix(0,n,1) alpha1t<-matrix(0,n,1) betat<-matrix(0,n,1) gammat<-matrix(0,n,1) sigmat<-matrix(0,n,1) step<-20 ota<-seq(t0+1,n,step) for (t in 1:t0){ now<-r[1:t] sigmat[t]<-sd(now) } for (i in 1:length(ota)){ t<-ota[i] if (i==length(ota)) up<-n else up<-ota[i+1]-1 if (is.null(roll)) beg<-1 else beg<-max(1,t-roll) now<-r[beg:t] # hn<-hngarchFit(now) alpha0<-hn$model$omega alpha1<-hn$model$alpha beta<-hn$model$beta gamma<-hn$model$lambda alpha0t[t:up]<-alpha0 alpha1t[t:up]<-alpha1 betat[t:up]<-beta gammat[t:up]<-gamma } for (t in (t0+1):length(sigmat)){ alpha0<-alpha0t[t] alpha1<-alpha1t[t] beta<-betat[t] gamma<-gammat[t] sigmat[t]<- sqrt(alpha0+alpha1*(r[t]/sigmat[t-1]-gamma*sigmat[t-1])^2+beta*sigmat[t-1]^2) } sigmat[1]<-sigmat[2] hn.cspe<-matrix(0,n,1) diffet<-matrix(0,n,1) for (i in (t0+1):(n-eta)){ sigma<-sigmat[i] hava<-r[i+eta] vest<-sigma^2 diffet[i+eta]<-abs(vest-hava^2)^2 hn.cspe[i+eta]<-sum(diffet[1:(i+eta)],na.rm=TRUE) } # asymmetric MA cross-validation ####### lambdat<-c(0,0.1,0.2,0,3) hoot<-c(5,10,20,40) gammat<-exp(-1/hoot) acspet<-matrix(0,n,length(hoot)*length(lambdat)) aspet<-matrix(0,n,length(hoot)*length(lambdat)) for (ll in 1:length(lambdat)){ for (gg in 1:length(gammat)){ lambda<-lambdat[ll] gamma<-gammat[gg] diffet<-matrix(0,n,1) val<-mean(r[1:t0]^2) for (t in (t0+1):(n-eta)){ hava<-r[t+eta] val<-(1-gamma)*val*(r[t]/sqrt(val)-lambda)^2+gamma*val diffet[t+eta]<-abs(val-hava^2)^2 # ind<-length(gammat)*(ll-1)+gg acspet[t+eta,ind]<-sum(diffet[1:(t+eta)],na.rm=TRUE) aspet[t+eta,ind]<-abs(val-hava^2)^2 } }} acspe.cv<-matrix(0,n,1) for (t in (t0+1):(n-eta)){ ine<-which.min(acspet[t,]) acspe.cv[t]<-acspe.cv[t-1]+aspet[t,ine] } # Figure 2 cex.axis<-1.5 cex.lab<-1.5 cex.sub<-1.5 cex<-1.5 lty<-1.5 ero1<-hn.cspe-gcspe ero2<-acspe.cv-gcspe ota<-c(t0:(n-100)) plot(times[ota],ero1[ota],type="l",lty=1,#ylim=c(-0.0001,0.0001), xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) #text(2000,0.00014,"Heston-Nandi",col="black",cex=cex) segments(1,0,30000,0,col="green") mtext("differenced CSPE",side=2,cex=1.5,line=2.4) title(sub="(a)",cex.sub=cex.sub) ota<-c(t0:(n-100)) plot(times[ota],ero2[ota],type="l",lty=1,#ylim=c(-0.0001,0.0001), xlab="",ylab="",cex=cex,cex.axis=cex.axis,cex.lab=cex.lab) #text(2000,0.00014,"EWMA",col="black",cex=cex) segments(1,0,30000,0,col="green") mtext("differenced CSPE",side=2,cex=1.5,line=2.4) title(sub="(b)",cex.sub=cex.sub)