S&P500 Seasonal Study + Other Commodities

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 


# 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 Plot 
hist(jan$close.diff,main="Jan Mean - Normal Distribution",xlab="Mean")

# Plot 
ggplot(mean, aes(group.mymonth, mean)) +
  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)) +
  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))+

# Write output to file
write.csv(read.spx,file="C:/R Projects/seasonal.csv")

Author: Andrew Bannerman

Integrity Inspector. Quantitative Analysis is a favorite past time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s