Eric Zivot
Monday, May 11, 2015
options(digits=3, width=70)
library(boot)  
library(IntroCompFinR)## Loading required package: xts
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## 
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numericlibrary(PerformanceAnalytics)## 
## Attaching package: 'PerformanceAnalytics'
## 
## The following object is masked from 'package:graphics':
## 
##     legendsample()Consider random sampling from the vector r=c(0.1,0.05,-0.02,0.03,-0.04).
sample() to create a random sample from the integers 1 to 5 and use it to subset the vector rr = c(0.1,0.05,-0.02,0.03,-0.04)
set.seed(123)
idx = sample(5, replace=TRUE)
idx## [1] 2 4 3 5 5r[idx]## [1]  0.05  0.03 -0.02 -0.04 -0.04sample()sample() directly to automate the previous two step process:set.seed(123)
sample(r, replace=TRUE)## [1]  0.05  0.03 -0.02 -0.04 -0.04my.panel <- function(...) {
  lines(...)
  abline(h=0)
}
plot.zoo(msftRetC, col="blue", lwd=2, main="", panel=my.panel, type="l")xts data in matrix for use with R package bootreturns.mat = as.matrix(cerRetC)
MSFT = returns.mat[,"MSFT", drop=FALSE]Compute CER model estimates for MSFT
n.obs = nrow(MSFT)
muhat.MSFT = mean(MSFT)
sigmahat.MSFT = sd(MSFT)
estimate = c(muhat.MSFT, sigmahat.MSFT)Calculate analytic standard errors
se.muhat.MSFT = sigmahat.MSFT/sqrt(n.obs)
se.sigmahat.MSFT = sigmahat.MSFT/sqrt(2*n.obs)
se = c(se.muhat.MSFT, se.sigmahat.MSFT)Show estimates with analytic standard errors
ans = rbind(estimate, se)
colnames(ans) = c("Mu", "Sigma")
ans##               Mu  Sigma
## estimate 0.00413 0.1002
## se       0.00764 0.0054Same idea as Monte Carlo Simulation but instead of generating random data from an assumed distribution or model, you generate random data by sampling with replacement from the observed data using sample().
Example: Bootstrap \(\hat{\mu}_{MSFT}\)
# Create bootstrap simulation for muhat
B = 999
muhat.boot = rep(0, B)
n.obs = nrow(MSFT)
set.seed(123)
for (i in 1:B) {
  boot.data = sample(MSFT, n.obs, replace=TRUE)
  muhat.boot[i] = mean(boot.data)
}Calculate bootstrap bias estimate
mean(muhat.boot) - muhat.MSFT## [1] 0.000199Bootstrap bias is close to zero
Calculate bootstrap SE and compare with analytic SE
sd(muhat.boot)## [1] 0.00746# analytic SE
se.muhat.MSFT## [1] 0.00764bootstrap SE is very close to analytic SE.
# plot bootstrap distribution and show normal qq-plot
par(mfrow=c(1,2))
  hist(muhat.boot, col="cornflowerblue")
  abline(v=muhat.MSFT, col="white", lwd=2)
  qqnorm(muhat.boot, col="cornflowerblue")
  qqline(muhat.boot)par(mfrow=c(1,1))Bootstrap distribution looks like normal distribution.
Calculate bootstrap 95% confidence interval based on normal distribution
se.boot = sd(muhat.boot)
lower = muhat.MSFT - 2*se.boot
upper = muhat.MSFT + 2*se.boot
width = upper - lower
c(lower, upper, width)## [1] -0.0108  0.0190  0.0298boot() bootstrap user supplied functionboot.ci() compute bootstrap confidence intervalboot() functionThe function boot() requires user-supplied functions that take two arguments: data and an index. The index is created by the boot() function and represents random resampling with replacement
# function for bootstrapping sample mean
mean.boot = function(x, idx) {
# arguments:
# x      data to be resampled
# idx    vector of scrambled indices created by boot() function
# value:
# ans        mean value computed using resampled data
     ans = mean(x[idx])
     ans
}boot() function# bootstrapping muhat
MSFT.muhat.boot = boot(MSFT, statistic = mean.boot, R=999)
class(MSFT.muhat.boot)## [1] "boot"names(MSFT.muhat.boot)##  [1] "t0"        "t"         "R"         "data"      "seed"     
##  [6] "statistic" "sim"       "call"      "stype"     "strata"   
## [11] "weights"MSFT.muhat.boot## 
## ORDINARY NONPARAMETRIC BOOTSTRAP
## 
## 
## Call:
## boot(data = MSFT, statistic = mean.boot, R = 999)
## 
## 
## Bootstrap Statistics :
##     original   bias    std. error
## t1*  0.00413 5.71e-05     0.00777Here, “original” is \(\hat{\mu}\); “bias” is bootstrap bias; “std. error” is the bootstrap SE. Recall, the analytic SE is 0.008.
boot” objectsPlot method shows histogram of bootstrap values and normal qq-plot.
plot(MSFT.muhat.boot)Use the function boot.ci() to compute bootstrap confidence intervals
boot.ci(MSFT.muhat.boot, conf = 0.95, type = c("norm","perc"))## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 999 bootstrap replicates
## 
## CALL : 
## boot.ci(boot.out = MSFT.muhat.boot, conf = 0.95, type = c("norm", 
##     "perc"))
## 
## Intervals : 
## Level      Normal             Percentile     
## 95%   (-0.0112,  0.0193 )   (-0.0111,  0.0193 )  
## Calculations and Intervals on Original Scale# function for bootstrapping sample standard deviation
sd.boot = function(x, idx) {
# arguments:
# x     data to be resampled
# idx       vector of scrambled indices created by boot() function
# value:
# ans       sd value computed using resampled data
     ans = sd(x[idx])
     ans
}# bootstrap sigmahat
MSFT.sigmahat.boot = boot(MSFT, statistic = sd.boot, R=999)
MSFT.sigmahat.boot## 
## ORDINARY NONPARAMETRIC BOOTSTRAP
## 
## 
## Call:
## boot(data = MSFT, statistic = sd.boot, R = 999)
## 
## 
## Bootstrap Statistics :
##     original    bias    std. error
## t1*      0.1 -0.000526     0.00794Recall, the analytic SE for sigmahat is 0.005. Here the bootstrap SE should be more accurate because the analytic SE is only an approximation based on the central limit theorem.
# plot bootstrap distribution
plot(MSFT.sigmahat.boot)Bootstrap distribution looks pretty normal
# compute 95% confidence intervals
boot.ci(MSFT.sigmahat.boot, conf=0.95, type=c("norm", "perc"))## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 999 bootstrap replicates
## 
## CALL : 
## boot.ci(boot.out = MSFT.sigmahat.boot, conf = 0.95, type = c("norm", 
##     "perc"))
## 
## Intervals : 
## Level      Normal             Percentile     
## 95%   ( 0.0852,  0.1163 )   ( 0.0843,  0.1167 )  
## Calculations and Intervals on Original ScaleCreate function to compute normal Value-at-Risk to be passed to boot()
ValueAtRisk.boot = function(x, idx, p=0.05, w=100000) {
# x     data to be resampled
# idx       vector of scrambled indices created by boot() function
# p       probability value for VaR calculation
# w       value of initial investment
# value:
# ans       Value-at-Risk computed using resampled data
    q = mean(x[idx]) + sd(x[idx])*qnorm(p)
    VaR = (exp(q) - 1)*w
    VaR
}MSFT.VaR.boot = boot(MSFT, statistic = ValueAtRisk.boot, R=999)
MSFT.VaR.boot## 
## ORDINARY NONPARAMETRIC BOOTSTRAP
## 
## 
## Call:
## boot(data = MSFT, statistic = ValueAtRisk.boot, R = 999)
## 
## 
## Bootstrap Statistics :
##     original  bias    std. error
## t1*   -14846  -0.534        1299plot(MSFT.VaR.boot)boot.ci(MSFT.VaR.boot, conf=0.95, type=c("norm", "perc"))## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 999 bootstrap replicates
## 
## CALL : 
## boot.ci(boot.out = MSFT.VaR.boot, conf = 0.95, type = c("norm", 
##     "perc"))
## 
## Intervals : 
## Level      Normal             Percentile     
## 95%   (-17392, -12299 )   (-17396, -12274 )  
## Calculations and Intervals on Original Scale95% confidence interval for 5% VaR is fairly wide.