We study to see if there is seasonality to the S&P500. We perform the procedure below on data from 1928 to present day (10.11.2017)

1. Calculate daily spread of closing prices

2. Group daily spread by month

3. Calculate mean of each month

We simply compute the spread of the the close to close values. We do not use the % returns here, simply close – close for every day in the series.

Next we group all days by their month. We then compute the mean for each grouped month.

The results for the S&P500 are below:

The old adage… ‘Sell In May And Go Away!’ seems to be true.

Other ETF’s:

DIA follows mostly the same seasonal pattern to the S&P500.

The best months for Crude Oil seem to be from Feb through June.

Natural Gas has its worst months in July and August.

Best months for Gold look to be Jan/Feb and August.

Silver follows a similar seasonal pattern to Gold.

Commodities tend to exhibit seasonal supply and demand flutuations which are consistently shown in the mean plots above and with a bit of googling may be explained.

In another post we will test for seasonal strategies which will attempt to exploit the above seasonal trends.

Full R Code below:

# S&P500 Seasonal Study # Calculate daily price spreads # Group by month # Average each monthly group require(lubridate) require(dplyr) require(magrittr) require(TTR) require(zoo) require(data.table) require(xts) require(ggplot2) require(ggthemes) # Data path data.dir <- "C:/Stock Market Analysis/Market Data/MASTER_DATA_DUMP" data.read.spx <- paste(data.dir,"$SPX.csv",sep="/") # Read data read.spx <- read.csv(data.read.spx,header=TRUE, sep=",",skip=0,stringsAsFactors=FALSE) # Convert Values To Numeric cols <-c(3:8) read.spx[,cols] %<>% lapply(function(x) as.numeric(as.character(x))) # Convert Date Column [1] to Date format read.spx$Date <- ymd(read.spx$Date) # Subset Date #read.spx <- subset(read.spx, Date >= as.Date("1960-01-01") ) # Compute daily price differences # We replicate NA 1 time in order to maintain correct positioning of differences # Within the data frame read.spx$close.diff <- c(rep(NA, 1), diff(read.spx$Close, lag = 1, differences = 1, arithmetic = TRUE, na.pad = TRUE)) # Group each daily difference by month group <- read.spx %>% dplyr::mutate(mymonth = lubridate::month(Date)) %>% group_by(mymonth) read.spx <- data.frame(read.spx,group$mymonth) read.spx <- arrange(read.spx,group.mymonth) # Duplicate df for.mean <- data.frame(read.spx) # Perform mean mean <- for.mean %<>% group_by(group.mymonth) %>% summarise(mean=mean(close.diff,na.rm = TRUE)) # Confidence jan <- subset(read.spx, group.mymonth == 1) feb <- subset(read.spx, group.mymonth == 2) mar <- subset(read.spx, group.mymonth == 3) apr <- subset(read.spx, group.mymonth == 4) may <- subset(read.spx, group.mymonth == 5) jun <- subset(read.spx, group.mymonth == 6) jul <- subset(read.spx, group.mymonth == 7) aug <- subset(read.spx, group.mymonth == 8) sep <- subset(read.spx, group.mymonth == 9) oct <- subset(read.spx, group.mymonth == 10) nov <- subset(read.spx, group.mymonth == 11) dec <- subset(read.spx, group.mymonth == 12) jan.t.test <- t.test(jan$close.diff, conf.level = 0.95,na.rm = TRUE) jan.t.test$estimate # Jan Plot hist(jan$close.diff,main="Jan Mean - Normal Distribution",xlab="Mean") # Plot ggplot(mean, aes(group.mymonth, mean)) + geom_col()+ theme_classic()+ scale_x_continuous(breaks = seq(0, 12, by = 1))+ ggtitle("UNG - Mean Daily Spead Per Month", subtitle = "2007 To Present") + labs(x="Month",y="Mean Daily Spread Per Month")+ theme(plot.title = element_text(hjust=0.5),plot.subtitle =element_text(hjust=0.5)) ggplot(mean, aes(group.mymonth, mean)) + geom_line()+ theme_bw() + scale_x_continuous(breaks = seq(0, 12, by = 1))+ scale_y_continuous(breaks = seq(-0.15, 0.30, by = 0.02))+ ggtitle("Mean Daily Spead Per Month", subtitle = "1928 To Present") + labs(x="Month",y="Mean Daily Spread Per Month")+ theme(plot.title = element_text(hjust=0.5),plot.subtitle =element_text(hjust=0.5))+ geom_rect(aes(xmin=4.5,xmax=9,ymin=-Inf,ymax=Inf),alpha=0.1,fill="#CC6666")+ geom_rect(aes(xmin=1,xmax=4.5,ymin=-Inf,ymax=Inf),alpha=0.1,fill="#66CC99")+ geom_rect(aes(xmin=9,xmax=12,ymin=-Inf,ymax=Inf),alpha=0.1,fill="#66CC99") # Write output to file write.csv(read.spx,file="C:/R Projects/seasonal.csv")