Forecasting extremes on the S&P500

I’m occasionally participating in an on-going forecasting competition (Forecast World Events), and the financial forecasts in particular are interesting. Today I received a request for a forecast relating to the S&P500:

What will be the largest single-day GAIN or LOSS for any trading day between 2012-2-06 and 2012-02-10?

Allocate 100% probability across these categories:

  1. <1%
  2. 1% to 1.99%
  3. 2% to 2.99%
  4. 3% or more

The status right now is below:

 

Unless you have very precise estimates of what will happen over the next 5 trading day, a good estimate would come from history. So using the incredibly convenient R program (code below), I pulled historical data on the S&P500. We can check this question in history a couple of ways:

  1. Using all week periods since 1980
  2. Using all week periods in February since 1980

The results are surprisingly consistent with history. As of Feb 4, 2012, the consensus was expecting the upcoming week to be more volatile than history, with double the odds of seeing a 3%+ movement up or down, and double odds of a movement between 2 and 3%. The modal historical outcome of between 1% and 2% is underweight by about 13%, not a massive difference.

What would be interesting is seeing how “common” this view is, i.e. is the consistency with history because the majority of people are close to history, or are a majority of extreme positions cancelling each other out?

 

R Code:

rm(list=ls())
install.packages(quantmod)
library(quantmod)<
sp500<- getSymbols("^GSPC",auto.assign=FALSE,from="1980-01-01")
rets<-periodReturn(sp500,period="daily")
cat.rets<-as.data.frame(rets)
str(cat.rets)
cat.rets$ret.cat=NA
cat.rets$ret.cat[abs(cat.rets$daily.returns)<0.01]=1
cat.rets$ret.cat[abs(cat.rets$daily.returns)>=0.01]=2
cat.rets$ret.cat[abs(cat.rets$daily.returns)>=0.02]=3
cat.rets$ret.cat[abs(cat.rets$daily.returns)>=0.03]=4
cat.rets$year<-as.POSIXlt(as.POSIXct(strptime(as.character(row.names(cat.rets)),format="%Y-%m-%d")))$year+1900
table(cat.rets$year,cat.rets$ret.cat)

cat.rets$dow<-cat.rets$dow<-as.POSIXlt(as.POSIXct(strptime(as.character(row.names(cat.rets)),format="%Y-%m-%d")))$wday
#Using Monday as anchor, define greatest return over the next 5 days

cat.rets$max.week.ret<-NA
for (i in 1:nrow(cat.rets)) {
  if (cat.rets$dow[i]==1) {
    j=i+5
    cat.rets$max.week.ret[i]<-max(cat.rets$ret.cat[i:j],na.rm=TRUE)
  }
  else next
}

table(cat.rets$max.week.ret)
prop.table(table(cat.rets$max.week.ret))

################################
#Just Februaries
nrow(cat.rets)
cat.rets$month<-as.POSIXlt(as.POSIXct(strptime(as.character(row.names(cat.rets)),format="%Y-%m-%d")))$mon
table(cat.rets$month)

cat.rets$max.feb.week.ret<-NA
for (i in 1:nrow(cat.rets)) {
  if (cat.rets$month[i]!=1) {
  if (cat.rets$dow[i]==1) {
    j=i+5
    cat.rets$max.feb.week.ret[i]<-max(cat.rets$ret.cat[i:j],na.rm=TRUE)
  }
  }
  else next
}
row.names(probabilities)<-c("<1%","1-2%","2-3%",">=3%")
prop.table(table(cat.rets$max.feb.week.ret))
probabilities<- cbind(c(.13,.37,.32,.18),prop.table(table(cat.rets$max.week.ret)),prop.table(table(cat.rets$max.feb.week.ret)))

2 thoughts on “Forecasting extremes on the S&P500”

  1. A better approach would be to fit a garch model to a history of daily data, and then simulate the model 5 days ahead multiple times with the model’s estimate of the current state. This takes into account that the level of volatility changes over time, and it is a short enough horizon that the inexactness of the model shouldn’t matter too much.

Leave a Reply

Your email address will not be published. Required fields are marked *