Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save alexchinco/d58ebd7750904db1b94c to your computer and use it in GitHub Desktop.
Save alexchinco/d58ebd7750904db1b94c to your computer and use it in GitHub Desktop.
Code to replicate main results in Ang, Hodrick, Xing, and Zhang (2006)
## Prep workspace
rm(list=ls())
library(foreign)
library(grid)
library(plyr)
library(ggplot2)
library(tikzDevice)
print(options('tikzLatexPackages'))
options(tikzLatexPackages =
c("\\usepackage{tikz}\n",
"\\usepackage[active,tightpage,psfixbb]{preview}\n",
"\\PreviewEnvironment{pgfpicture}\n",
"\\setlength\\PreviewBorder{0pt}\n",
"\\usepackage{amsmath}\n",
"\\usepackage{xfrac}\n"
)
)
setTikzDefaults(overwrite = FALSE)
print(options('tikzLatexPackages'))
library(reshape)
library(vars)
library(scales)
library(zoo)
scl.str.DAT_DIR <- "~/Dropbox/research/correlation_term_structure/data/"
scl.str.FIG_DIR <- "~/Dropbox/research/correlation_term_structure/figures/"
## Load data
mat.df.DATA <- read.csv(paste(scl.str.DAT_DIR, "aggregate-volatility-portfolios--07may2014.csv", sep = ""),
stringsAsFactors = FALSE
)
mat.df.DATA <- mat.df.DATA[is.na(mat.df.DATA$rank) == FALSE, ]
mat.df.DATA$t <- as.Date(mat.df.DATA$date, format = "%d%b%Y")
mat.df.DATA$cret <- NA
mat.df.DATA$cretx <- NA
for (p in 1:5) {
mat.df.DATA[mat.df.DATA$rank == p, ]$cret <- cumsum(mat.df.DATA[mat.df.DATA$rank == p, ]$ret/100)
mat.df.DATA[mat.df.DATA$rank == p, ]$cretx <- cumsum(mat.df.DATA[mat.df.DATA$rank == p, ]$retx/100)
}
## Plot portfolio returns
if (TRUE == FALSE) {
mat.df.PLOT <- mat.df.DATA[, c("t", "rank", "cret")]
names(mat.df.PLOT) <- c("t", "variable", "value")
mat.df.PLOT$variable <- factor(as.character(mat.df.PLOT$variable),
levels = c("1","2","3","4","5"),
labels = c("$L$", "$2$", "$3$", "$4$", "$H$")
)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--aggregate-volatility-portfolio-cumulative-returns'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_path(data = mat.df.PLOT,
aes(x = t,
y = value * 100,
group = variable,
colour = variable,
linetype = variable
),
size = 0.75
)
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("$\\%$")
obj.gg2.PLOT <- obj.gg2.PLOT + guides(colour = guide_legend(reverse = TRUE), linetype = guide_legend(reverse = TRUE))
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = c(0.10,0.655),
legend.background = element_blank(),
legend.title = element_blank(),
legend.margin = unit(0, "cm"),
legend.text = element_text(size = 7),
axis.text = element_text(size = 6),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Cumulative Return on Aggregate Volatility Exposure Portfolios")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
## Compute summary statistics
mat.df.SUM_STAT <- mat.df.DATA[mat.df.DATA$t <= as.Date("2000-12-31"), ]
mat.df.SUM_STAT$m <- format(mat.df.SUM_STAT$t, "%Y-%m")
mat.df.SUM_STAT <- ddply(mat.df.SUM_STAT, c("rank", "m"), function(X)c(sum(X$ret), sum(X$retx), sum(X$mkt), mean(X$mcap)))
names(mat.df.SUM_STAT) <- c("rank", "m", "ret", "retx", "mkt", "mcap")
mat.df.SUM_STAT <- ddply(mat.df.SUM_STAT, c("rank"), function(X)c(mean(X$ret),
sd(X$ret),
summary(lm(X$retx ~ X$mkt))$coef[1,1],
summary(lm(X$retx ~ X$mkt))$coef[1,2],
summary(lm(X$retx ~ X$mkt))$coef[1,3],
mean(X$mcap)
)
)
names(mat.df.SUM_STAT) <- c("rank", "avg", "sd", "a", "se", "t", "mcap")
## Plot portfolio CAPM alphas
if (TRUE == TRUE) {
mat.df.PLOT <- mat.df.SUM_STAT
mat.df.PLOT$rank <- factor(as.character(mat.df.PLOT$rank),
levels = c("1","2","3","4","5"),
labels = c("$L$", "$2$", "$3$", "$4$", "$H$")
)
mat.df.PLOT$ub <- mat.df.PLOT$a + 2 * mat.df.PLOT$se
mat.df.PLOT$lb <- mat.df.PLOT$a - 2 * mat.df.PLOT$se
mat.df.PLOT$signif <- (abs(mat.df.PLOT$t) < 1.96)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--ahxz06-table-1--capm-alphas'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_hline(yintercept = 0,
size = 0.50,
linetype = 4
)
obj.gg2.PLOT <- obj.gg2.PLOT + geom_pointrange(data = mat.df.PLOT,
aes(x = rank,
ymax = ub,
ymin = lb,
y = a,
group = rank,
colour = signif
),
size = 1
)
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("$\\%/\\text{Month}$")
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + scale_y_continuous(breaks = c(-0.50,-0.25,0.00,0.25,0.50))
obj.gg2.PLOT <- obj.gg2.PLOT + coord_cartesian(ylim = c(-0.75, 0.75))
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = "none",
axis.text = element_text(size = 6),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Abnormal Returns, $\\widehat{\\alpha}_j$, on Aggregate Volatility Exposure Portfolios")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
asdas;
## Compute aggregate volatility factor
mat.df.REG <- mat.df.DATA[, c("t", "mkt", "dVxo", "rank", "ret")]
mat.df.REG$rank <- paste("p", mat.df.REG$rank, sep="")
mat.df.REG <- cast(mat.df.REG, t + dVxo ~ rank)
mat.df.REG$m <- format(mat.df.REG$t, "%Y-%m")
mat.df.COEF <- ddply(mat.df.REG,
c("m"),
function(X)summary(lm(X$dVxo ~ X$p1 + X$p2 + X$p3 + X$p4 + X$p5))$coef[2:6,1]
)
names(mat.df.COEF) <- c("m", "b1", "b2", "b3", "b4", "b5")
mat.df.FVXO <- merge(mat.df.REG, mat.df.COEF, by = ("m"))
mat.df.FVXO$fVxo <- with(mat.df.FVXO, p1*b1 + p2*b2 + p3*b3 + p4*b4 + p5*b5)
## Plot aggregate volatility factor
if (TRUE == FALSE) {
mat.df.PLOT <- ddply(mat.df.FVXO, c("m"), function(X)c(sum(X$dVxo, na.rm = TRUE), sum(X$fVxo)))
names(mat.df.PLOT) <- c("t", "$\\Delta\\sigma_{x,m}$", "$f_m$")
mat.df.PLOT <- melt(mat.df.PLOT, c("t"))
mat.df.PLOT$t <- paste(mat.df.PLOT$t, "-01", sep="")
mat.df.PLOT$t <- as.Date(mat.df.PLOT$t)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--aggregate-volatility-factor'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_path(data = mat.df.PLOT,
aes(x = t,
y = value,
group = variable,
colour = variable,
linetype = variable
),
size = 0.75
)
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("$\\%/\\mathrm{Month}$")
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = c(0.925,0.825),
legend.background = element_blank(),
legend.title = element_blank(),
legend.margin = unit(0, "cm"),
legend.text = element_text(size = 7),
axis.text = element_text(size = 6),
axis.title = element_text(size = 10)
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Factor Mimicking Portfolio Return vs. Aggregate Volatility Factor")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
## Test for mispricing
mat.df.TEST <- mat.df.DATA[mat.df.DATA$t < as.Date("2001-01-01"), c("t", "rank", "mkt", "retx")]
names(mat.df.TEST) <- c("t", "rank", "mkt", "retx")
mat.df.TEST$m <- format(mat.df.TEST$t, "%Y-%m")
mat.df.TEST <- ddply(mat.df.TEST,
c("rank", "m"),
function(X)c(sum(X$mkt, na.rm = TRUE), sum(X$retx, na.rm = TRUE))
)
names(mat.df.TEST) <- c("rank", "m", "mkt", "retx")
mat.df.TEST <- merge(mat.df.TEST, mat.df.FVXO[, c("m", "fVxo")], by = c("m"))
mat.df.TEST <- ddply(mat.df.TEST,
c("rank"),
function(X)c(summary(lm(X$retx ~ X$mkt + X$fVxo))$coef[3,1],
summary(lm(X$retx ~ X$mkt + X$fVxo))$coef[3,2],
summary(lm(X$retx ~ X$mkt + X$fVxo))$coef[3,3]
)
)
names(mat.df.TEST) <- c("rank", "est", "se", "t")
## Plot portfolio coefficients after controlling for fVXO
if (TRUE == TRUE) {
mat.df.PLOT <- mat.df.TEST
mat.df.PLOT$rank <- factor(as.character(mat.df.PLOT$rank),
levels = c("1","2","3","4","5"),
labels = c("$L$", "$2$", "$3$", "$4$", "$H$")
)
mat.df.PLOT$ub <- mat.df.PLOT$est + 2 * mat.df.PLOT$se
mat.df.PLOT$lb <- mat.df.PLOT$est - 2 * mat.df.PLOT$se
mat.df.PLOT$signif <- (abs(mat.df.PLOT$t) < 1.96)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--ahxz06-table-1--factor-loadings'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_hline(yintercept = 0,
size = 0.50,
linetype = 4
)
obj.gg2.PLOT <- obj.gg2.PLOT + geom_pointrange(data = mat.df.PLOT,
aes(x = rank,
ymax = ub,
ymin = lb,
y = est,
group = rank,
colour = signif
),
size = 1
)
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("")
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + scale_y_continuous(breaks = c(-0.050,-0.025,0.000,0.025,0.05))
obj.gg2.PLOT <- obj.gg2.PLOT + coord_cartesian(ylim = c(-0.075, 0.075))
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = "none",
axis.text = element_text(size = 6),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Factor Loadings, $\\widehat{\\theta}_j$, on Aggregate Volatility Exposure Portfolios")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
## Prep workspace
rm(list=ls())
library(foreign)
library(grid)
library(plyr)
library(ggplot2)
library(tikzDevice)
print(options('tikzLatexPackages'))
options(tikzLatexPackages =
c("\\usepackage{tikz}\n",
"\\usepackage[active,tightpage,psfixbb]{preview}\n",
"\\PreviewEnvironment{pgfpicture}\n",
"\\setlength\\PreviewBorder{0pt}\n",
"\\usepackage{amsmath}\n",
"\\usepackage{xfrac}\n"
)
)
setTikzDefaults(overwrite = FALSE)
print(options('tikzLatexPackages'))
library(reshape)
library(vars)
library(scales)
library(zoo)
scl.str.DAT_DIR <- "~/Dropbox/research/correlation_term_structure/data/"
scl.str.FIG_DIR <- "~/Dropbox/research/correlation_term_structure/figures/"
## Load data
mat.df.DATA <- read.csv(paste(scl.str.DAT_DIR, "idiosyncratic-volatility-portfolios--14may2014b.csv", sep = ""),
stringsAsFactors = FALSE
)
mat.df.DATA <- mat.df.DATA[is.na(mat.df.DATA$rank) == FALSE, ]
mat.df.DATA$t <- as.Date(mat.df.DATA$date, format = "%d%b%Y")
mat.df.DATA$cret <- NA
mat.df.DATA$cretx <- NA
for (p in 1:5) {
mat.df.DATA[mat.df.DATA$rank == p, ]$cret <- cumsum(mat.df.DATA[mat.df.DATA$rank == p, ]$ret/100)
mat.df.DATA[mat.df.DATA$rank == p, ]$cretx <- cumsum(mat.df.DATA[mat.df.DATA$rank == p, ]$retx/100)
}
## Plot portfolio returns
if (TRUE == TRUE) {
mat.df.PLOT <- mat.df.DATA[, c("t", "rank", "cret")]
names(mat.df.PLOT) <- c("t", "variable", "value")
mat.df.PLOT$variable <- factor(as.character(mat.df.PLOT$variable),
levels = c("1","2","3","4","5"),
labels = c("$L$", "$2$", "$3$", "$4$", "$H$")
)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--idiosyncratic-volatility-portfolio-cumulative-returns'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_path(data = mat.df.PLOT,
aes(x = t,
y = value * 100,
group = variable,
colour = variable,
linetype = variable
),
size = 0.75
)
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("$\\%$")
obj.gg2.PLOT <- obj.gg2.PLOT + guides(colour = guide_legend(reverse = TRUE), linetype = guide_legend(reverse = TRUE))
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = c(0.10,0.655),
legend.background = element_blank(),
legend.title = element_blank(),
legend.margin = unit(0, "cm"),
legend.text = element_text(size = 7),
axis.text = element_text(size = 6),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Cumulative Return on Idiosyncratic Volatility Exposure Portfolios")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
## Compute summary statistics
mat.df.SUM_STAT <- mat.df.DATA[mat.df.DATA$t <= as.Date("2000-12-31"), ]
mat.df.SUM_STAT$m <- format(mat.df.SUM_STAT$t, "%Y-%m")
mat.df.SUM_STAT <- ddply(mat.df.SUM_STAT, c("rank", "m"), function(X)c(sum(X$ret), sum(X$retx), sum(X$mkt), mean(X$mcap)))
names(mat.df.SUM_STAT) <- c("rank", "m", "ret", "retx", "mkt", "mcap")
mat.df.SUM_STAT <- ddply(mat.df.SUM_STAT, c("rank"), function(X)c(mean(X$ret),
sd(X$ret),
summary(lm(X$retx ~ X$mkt))$coef[1,1],
summary(lm(X$retx ~ X$mkt))$coef[1,2],
summary(lm(X$retx ~ X$mkt))$coef[1,3],
mean(X$mcap)
)
)
names(mat.df.SUM_STAT) <- c("rank", "avg", "sd", "a", "se", "t", "mcap")
## Plot portfolio CAPM alphas
if (TRUE == TRUE) {
mat.df.PLOT <- mat.df.SUM_STAT
mat.df.PLOT$rank <- factor(as.character(mat.df.PLOT$rank),
levels = c("1","2","3","4","5"),
labels = c("$L$", "$2$", "$3$", "$4$", "$H$")
)
mat.df.PLOT$ub <- mat.df.PLOT$a + 2 * mat.df.PLOT$se
mat.df.PLOT$lb <- mat.df.PLOT$a - 2 * mat.df.PLOT$se
mat.df.PLOT$signif <- (abs(mat.df.PLOT$t) < 1.96)
theme_set(theme_bw())
scl.str.RAW_FILE <- 'plot--ahxz06-table-6--capm-alphas'
scl.str.TEX_FILE <- paste(scl.str.RAW_FILE,'.tex',sep='')
scl.str.PDF_FILE <- paste(scl.str.RAW_FILE,'.pdf',sep='')
scl.str.PNG_FILE <- paste(scl.str.RAW_FILE,'.png',sep='')
scl.str.AUX_FILE <- paste(scl.str.RAW_FILE,'.aux',sep='')
scl.str.LOG_FILE <- paste(scl.str.RAW_FILE,'.log',sep='')
tikz(file = scl.str.TEX_FILE, height = 2, width = 7, standAlone=TRUE)
obj.gg2.PLOT <- ggplot()
obj.gg2.PLOT <- obj.gg2.PLOT + scale_colour_brewer(palette="Set1")
obj.gg2.PLOT <- obj.gg2.PLOT + geom_hline(yintercept = 0,
size = 0.50,
linetype = 4
)
obj.gg2.PLOT <- obj.gg2.PLOT + geom_pointrange(data = mat.df.PLOT,
aes(x = rank,
ymax = ub,
ymin = lb,
y = a,
group = rank,
colour = signif
),
size = 1
)
obj.gg2.PLOT <- obj.gg2.PLOT + ylab("$\\%/\\text{Month}$")
obj.gg2.PLOT <- obj.gg2.PLOT + xlab("")
obj.gg2.PLOT <- obj.gg2.PLOT + scale_y_continuous(breaks = c(-0.50,-0.25,0.00,0.25,0.50))
obj.gg2.PLOT <- obj.gg2.PLOT + coord_cartesian(ylim = c(-0.75, 0.75))
obj.gg2.PLOT <- obj.gg2.PLOT + theme(plot.margin = unit(c(1,0.65,-0.75,0), "lines"),
plot.title = element_text(vjust = 1.75),
legend.position = "none",
axis.text = element_text(size = 6),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)
obj.gg2.PLOT <- obj.gg2.PLOT + ggtitle("Abnormal Returns, $\\widehat{\\alpha}_j$, on Idiosyncratic Volatility Exposure Portfolios")
print(obj.gg2.PLOT)
dev.off()
system(paste('lualatex', file.path(scl.str.TEX_FILE)), ignore.stdout = TRUE)
system(paste('convert -density 600', file.path(scl.str.PDF_FILE), ' ', file.path(scl.str.PNG_FILE)))
system(paste('mv ', scl.str.PNG_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.TEX_FILE, sep = ''))
system(paste('mv ', scl.str.PDF_FILE, ' ', scl.str.FIG_DIR, sep = ''))
system(paste('rm ', scl.str.AUX_FILE, sep = ''))
system(paste('rm ', scl.str.LOG_FILE, sep = ''))
}
;/*************************************************************************************
@author: Alex Chinco
@date: May 15th, 2014
**************************************************************************************/
OPTIONS LINESIZE = 256;
OPTIONS PAGESIZE = 256;
LIBNAME crsp '/wrds/crsp/sasdata/a_stock';
LIBNAME comp '/wrds/comp/sasdata/naa';
LIBNAME cc '/wrds/crsp/sasdata/a_ccm';
LIBNAME cboe '/wrds/cboe/sasdata';
LIBNAME ff '/wrds/ff/sasdata';
%LET START_DATE = '01JAN1986'd;
%LET END_DATE = '31DEC2012'd;
%INCLUDE '/home/uiuc/chinco/ang-hodrick-xing-zhang-2006/ROLLING_REG.sas';
;/*************************************************************************************
@section: Pull daily volatility data
**************************************************************************************/
PROC SQL;
CREATE TABLE vxoData AS
SELECT a.date FORMAT=DATE9. AS date,
a.vxo FORMAT=BEST16. AS vxo
FROM cboe.cboe AS a
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.date;
QUIT;
DATA vxoData;
SET vxoData;
RETAIN lVxo;
IF first.date THEN
DO;
lVxo = vxo;
END;
ELSE
DO;
dVxo = vxo - lVxo;
lVxo = vxo;
END;
DROP lVxo;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM vxoData AS a;
QUIT;
PROC SQL;
SELECT MEAN(a.vxo) AS vxoMean,
STD(a.vxo) AS vxoStd,
MEAN(a.dVxo) AS dVxoMean,
STD(a.dVxo) AS dVxoStd
FROM vxoData AS a;
QUIT;
;/*************************************************************************************
@section: Pull daily return data
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date FORMAT=DATE9. AS date,
a.ret * 100 FORMAT=BEST8. AS ret,
a.prc FORMAT=BEST8. AS prc,
a.shrout FORMAT=BEST8. AS shrout,
b.exchcd,
b.shrcd
FROM crsp.dsf(KEEP = date permno ret prc shrout) AS a LEFT JOIN
crsp.dseall(KEEP = date permno exchcd shrcd) AS b
ON (a.permno = b.permno) AND
(a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
DATA retData;
SET retData;
BY permno date;
RETAIN lexchcd lshrcd;
IF first.permno THEN
DO;
lexchcd = exchcd;
lshrcd = shrcd;
END;
ELSE
DO;
IF MISSING(exchcd) THEN
DO;
exchcd = lexchcd;
END;
ELSE
DO;
lexchcd = exchcd;
END;
IF MISSING(shrcd) THEN
DO;
shrcd = lshrcd;
END;
ELSE
DO;
lshrcd = shrcd;
END;
END;
IF (exchcd IN (1,2,3));
IF (shrcd IN (10,11));
IF (NOT MISSING(ret));
IF (ret NOT IN (-66.0,-77.0,-88.0,-99.0));
IF (NOT MISSING(prc));
IF (NOT MISSING(shrout));
IF (prc < 0) THEN
DO;
prc = ABS(prc);
END;
mcap = prc * shrout * 1000;
DROP lexchcd lshrcd shrcd exchcd prc shrout;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge on last month's market cap
**************************************************************************************/
PROC SQL;
CREATE TABLE mcapData AS
SELECT a.permno,
a.date,
a.mcap
FROM retData AS a
ORDER BY a.permno,
-a.date;
QUIT;
DATA mcapData;
SET mcapData;
BY permno;
RETAIN lDate;
IF first.date THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
IF (MONTH(date) = MONTH(lDate)) THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
last = 1;
lDate = date;
END;
END;
DROP lDate;
IF (last = 1);
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM mcapData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date,
a.ret,
b.mcap
FROM retData AS a LEFT JOIN
mcapData AS b
ON (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge on daily FF93 factors
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
b.mktrf * 100 FORMAT=BEST8. AS mkt,
b.smb * 100 FORMAT=BEST8. AS smb,
b.hml * 100 FORMAT=BEST8. AS hml,
(a.ret - b.rf * 100) FORMAT=BEST8. AS retx
FROM retData AS a LEFT JOIN
ff.factors_daily AS b
ON (a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge daily volatility and return data
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
MONTH(a.date) FORMAT=2. AS month,
YEAR(a.date) FORMAT=4. AS year,
b.vxo,
b.dVxo
FROM retData AS a LEFT JOIN
vxoData AS b
ON (a.date = b.date)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Keep month x permno pairs with at least 17 observations
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
MONTH(a.date) FORMAT=2. AS month,
YEAR(a.date) FORMAT=4. AS year
FROM retData AS a
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL;
CREATE TABLE obsData AS
SELECT a.permno,
a.year,
a.month,
COUNT(a.retx) as obs
FROM retData AS a
GROUP BY a.permno,
a.year,
a.month;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM obsData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
b.obs
FROM retData AS a LEFT JOIN
obsData AS b
ON (a.permno = b.permno) AND
(a.year = b.year) AND
(a.month = b.month)
WHERE (b.obs >= 17)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Estimate daily factor exposures each month
**************************************************************************************/
%ROLLINGREG(
DATA = retData,
OUT_DS = aCoefData,
ID = permno,
DATE = date,
MODEL_EQUATION = retx = mkt dVxo,
START_DATE = 1-1-1986,
END_DATE = 12-31-2012,
FREQ = month,
S = 1,
N = 1
);
PROC SQL OUTOBS = 25;
SELECT a.*
FROM aCoefData AS a;
QUIT;
PROC SQL;
CREATE TABLE aCoefData AS
SELECT a.*
FROM aCoefData AS a
ORDER BY a.date2;
QUIT;
%ROLLINGREG(
DATA = retData,
OUT_DS = iCoefData,
ID = permno,
DATE = date,
MODEL_EQUATION = retx = mkt smb hml,
START_DATE = 1-1-1986,
END_DATE = 12-31-2012,
FREQ = month,
S = 1,
N = 1
);
PROC SQL OUTOBS = 25;
SELECT a.*
FROM iCoefData AS a;
QUIT;
PROC SQL;
CREATE TABLE iCoefData AS
SELECT a.*
FROM iCoefData AS a
ORDER BY a.date2;
QUIT;
;/*************************************************************************************
@section: Create aggregate and idiosyncratic volatility portfolios
**************************************************************************************/
PROC RANK DATA = aCoefData
OUT = aRankData
GROUP = 5;
BY date2;
VAR dVxo;
RANKS aRank;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM aRankData AS a;
QUIT;
PROC RANK DATA = iCoefData
OUT = iRankData
GROUP = 5;
BY date2;
VAR _RMSE_;
RANKS iRank;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM iRankData AS a;
QUIT;
PROC SQL;
CREATE TABLE portData AS
SELECT a.*,
(b.aRank + 1) FORMAT=1. AS aRank
FROM retData AS a,
aRankData AS b
WHERE (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date2, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date2, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL;
CREATE TABLE portData AS
SELECT a.*,
(b.iRank + 1) FORMAT=1. AS iRank
FROM portData AS a,
iRankData AS b
WHERE (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date2, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date2, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM portData AS a;
QUIT;
PROC SQL;
CREATE TABLE portData AS
SELECT a.aRank,
a.iRank,
a.date,
MEAN(a.mkt) FORMAT=BEST8. AS mkt,
MEAN(a.smb) FORMAT=BEST8. AS smb,
MEAN(a.hml) FORMAT=BEST8. AS hml,
MEAN(a.dVxo) FORMAT=BEST8. AS dVxo,
SUM(a.ret * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS ret,
SUM(a.retx * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS retx,
MEAN(LOG(a.mcap/1000000)) FORMAT=BEST8. AS mcap
FROM portData AS a
GROUP BY a.aRank,
a.iRank,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM portData AS a;
QUIT;
;/*************************************************************************************
@section: Print data to CSV
**************************************************************************************/
PROC EXPORT
DATA = portData
OUTFILE = "double-sort-portfolios.csv"
DBMS = CSV
REPLACE;
RUN;
;/*************************************************************************************
@author: Alex Chinco
@date: May 7th, 2014
**************************************************************************************/
OPTIONS LINESIZE = 256;
OPTIONS PAGESIZE = 256;
LIBNAME crsp '/wrds/crsp/sasdata/a_stock';
LIBNAME cboe '/wrds/cboe/sasdata';
LIBNAME ff '/wrds/ff/sasdata';
%LET START_DATE = '01JAN1986'd;
%LET END_DATE = '31DEC2012'd;
%INCLUDE '/home/uiuc/chinco/ang-hodrick-xing-zhang-2006/ROLLING_REG.sas';
;/*************************************************************************************
@section: Pull daily volatility data
**************************************************************************************/
PROC SQL;
CREATE TABLE vxoData AS
SELECT a.date FORMAT=DATE9. AS date,
a.vxo FORMAT=BEST16. AS vxo
FROM cboe.cboe AS a
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.date;
QUIT;
DATA vxoData;
SET vxoData;
RETAIN lVxo;
IF first.date THEN
DO;
lVxo = vxo;
END;
ELSE
DO;
dVxo = vxo - lVxo;
lVxo = vxo;
END;
DROP lVxo;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM vxoData AS a;
QUIT;
PROC SQL;
SELECT MEAN(a.vxo) AS vxoMean,
STD(a.vxo) AS vxoStd,
MEAN(a.dVxo) AS dVxoMean,
STD(a.dVxo) AS dVxoStd
FROM vxoData AS a;
QUIT;
;/*************************************************************************************
@section: Pull daily return data
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date FORMAT=DATE9. AS date,
a.ret * 100 FORMAT=BEST16. AS ret,
a.prc FORMAT=BEST16. AS prc,
a.shrout FORMAT=BEST16. AS shrout,
b.exchcd,
b.shrcd
FROM crsp.dsf(KEEP = date permno ret prc shrout) AS a LEFT JOIN
crsp.dseall(KEEP = date permno exchcd shrcd) AS b
ON (a.permno = b.permno) AND
(a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
DATA retData;
SET retData;
BY permno date;
RETAIN lexchcd lshrcd;
IF first.permno THEN
DO;
lexchcd = exchcd;
lshrcd = shrcd;
END;
ELSE
DO;
IF MISSING(exchcd) THEN
DO;
exchcd = lexchcd;
END;
ELSE
DO;
lexchcd = exchcd;
END;
IF MISSING(shrcd) THEN
DO;
shrcd = lshrcd;
END;
ELSE
DO;
lshrcd = shrcd;
END;
END;
IF (exchcd IN (1,2,3));
IF (shrcd IN (10,11));
IF (NOT MISSING(ret));
IF (ret NOT IN (-66.0,-77.0,-88.0,-99.0));
IF (NOT MISSING(prc));
IF (NOT MISSING(shrout));
IF (prc < 0) THEN
DO;
prc = ABS(prc);
END;
shr = 1000 * shrout;
mcap = prc * shr;
DROP lexchcd lshrcd shrcd exchcd shrout;
RUN;
PROC SQL;
CREATE TABLE mcapData AS
SELECT a.permno,
a.date,
a.mcap
FROM retData AS a
ORDER BY a.permno,
-a.date;
QUIT;
DATA mcapData;
SET mcapData;
BY permno;
RETAIN lDate;
IF first.date THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
IF (MONTH(date) = MONTH(lDate)) THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
last = 1;
lDate = date;
END;
END;
DROP lDate;
IF (last = 1);
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM mcapData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date,
a.ret,
b.mcap
FROM retData AS a LEFT JOIN
mcapData AS b
ON (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
b.mktrf * 100 FORMAT=BEST16. AS mkt,
(a.ret - b.rf * 100) FORMAT=BEST16. AS retx
FROM retData AS a LEFT JOIN
ff.factors_daily AS b
ON (a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge daily volatility and return data
**************************************************************************************/
PROC SQL;
CREATE TABLE regData AS
SELECT a.*,
MONTH(a.date) FORMAT=2. AS month,
YEAR(a.date) FORMAT=4. AS year,
b.vxo,
b.dVxo
FROM retData AS a LEFT JOIN
vxoData AS b
ON (a.date = b.date)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM regData AS a;
QUIT;
PROC SQL;
CREATE TABLE obsPerMonthData AS
SELECT a.permno,
a.year,
a.month,
COUNT(a.retx) as obsPerMonth
FROM regData AS a
GROUP BY a.permno,
a.year,
a.month;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM obsPerMonthData AS a;
QUIT;
PROC SQL;
CREATE TABLE regData AS
SELECT a.*,
b.obsPerMonth
FROM regData AS a LEFT JOIN
obsPerMonthData AS b
ON (a.permno = b.permno) AND
(a.year = b.year) AND
(a.month = b.month)
WHERE (b.obsPerMonth >= 17)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM regData AS a;
QUIT;
PROC SQL;
SELECT MIN(a.obsPerMonth),
MEAN(a.obsPerMonth),
MAX(a.obsPerMonth)
FROM regData AS a;
QUIT;
;/*************************************************************************************
@section: Estimate daily factor exposures each month
**************************************************************************************/
%ROLLINGREG(
DATA = regData,
OUT_DS = coefData,
ID = permno,
DATE = date,
MODEL_EQUATION = retx = mkt dVxo,
START_DATE = 1-1-1986,
END_DATE = 12-31-2012,
FREQ = month,
S = 1,
N = 1
);
PROC SQL OUTOBS = 25;
SELECT a.*
FROM coefData AS a;
QUIT;
PROC SQL;
CREATE TABLE coefData AS
SELECT a.*
FROM coefData AS a
ORDER BY a.date2;
QUIT;
;/*************************************************************************************
@section: Create volatility beta portfolios
**************************************************************************************/
PROC RANK DATA = coefData
OUT = rankData
GROUP = 5;
BY date2;
VAR dVxo;
RANKS rank;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM rankData AS a;
QUIT;
PROC SQL;
CREATE TABLE volPortfolioData AS
SELECT a.*,
(b.rank + 1) FORMAT=1. AS rank
FROM regData AS a,
rankData AS b
WHERE (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date2, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date2, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM volPortfolioData AS a;
QUIT;
PROC SQL;
CREATE TABLE volPortfolioData AS
SELECT a.rank,
a.date,
MEAN(a.mkt) FORMAT=BEST8. AS mkt,
MEAN(a.vxo) FORMAT=BEST8. AS vxo,
MEAN(a.dVxo) FORMAT=BEST8. AS dVxo,
SUM(a.ret * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS ret,
SUM(a.retx * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS retx,
MEAN(LOG(a.mcap/1000000)) FORMAT=BEST8. AS mcap
FROM volPortfolioData AS a
GROUP BY a.rank,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM volPortfolioData AS a;
QUIT;
;/*************************************************************************************
@section: Print data to CSV
**************************************************************************************/
PROC EXPORT
DATA = volPortfolioData
OUTFILE = "aggregate-volatility-portfolios.csv"
DBMS = CSV
REPLACE;
RUN;
;/*************************************************************************************
@author: Alex Chinco
@date: May 14th, 2014
**************************************************************************************/
OPTIONS LINESIZE = 256;
OPTIONS PAGESIZE = 256;
LIBNAME crsp '/wrds/crsp/sasdata/a_stock';
LIBNAME cboe '/wrds/cboe/sasdata';
LIBNAME ff '/wrds/ff/sasdata';
%LET START_DATE = '01JAN1963'd;
%LET END_DATE = '31DEC2012'd;
%INCLUDE '/home/uiuc/chinco/ang-hodrick-xing-zhang-2006/ROLLING_REG.sas';
;/*************************************************************************************
@section: Pull daily return data
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date FORMAT=DATE9. AS date,
a.ret * 100 FORMAT=BEST8. AS ret,
a.prc FORMAT=BEST8. AS prc,
a.shrout FORMAT=BEST8. AS shrout,
b.exchcd,
b.shrcd
FROM crsp.dsf(KEEP = date permno ret prc shrout) AS a LEFT JOIN
crsp.dseall(KEEP = date permno exchcd shrcd) AS b
ON (a.permno = b.permno) AND
(a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
DATA retData;
SET retData;
BY permno date;
RETAIN lexchcd lshrcd;
IF first.permno THEN
DO;
lexchcd = exchcd;
lshrcd = shrcd;
END;
ELSE
DO;
IF MISSING(exchcd) THEN
DO;
exchcd = lexchcd;
END;
ELSE
DO;
lexchcd = exchcd;
END;
IF MISSING(shrcd) THEN
DO;
shrcd = lshrcd;
END;
ELSE
DO;
lshrcd = shrcd;
END;
END;
IF (exchcd IN (1,2,3));
IF (shrcd IN (10,11));
IF (NOT MISSING(ret));
IF (ret NOT IN (-66.0,-77.0,-88.0,-99.0));
IF (NOT MISSING(prc));
IF (NOT MISSING(shrout));
IF (prc < 0) THEN
DO;
prc = ABS(prc);
END;
mcap = prc * shrout * 1000;
DROP lexchcd lshrcd shrcd exchcd prc shrout;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge on last month's market cap
**************************************************************************************/
PROC SQL;
CREATE TABLE mcapData AS
SELECT a.permno,
a.date,
a.mcap
FROM retData AS a
ORDER BY a.permno,
-a.date;
QUIT;
DATA mcapData;
SET mcapData;
BY permno;
RETAIN lDate;
IF first.date THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
IF (MONTH(date) = MONTH(lDate)) THEN
DO;
last = 0;
lDate = date;
END;
ELSE
DO;
last = 1;
lDate = date;
END;
END;
DROP lDate;
IF (last = 1);
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM mcapData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.permno,
a.date,
a.ret,
b.mcap
FROM retData AS a LEFT JOIN
mcapData AS b
ON (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Merge on daily FF93 factors
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
b.mktrf * 100 FORMAT=BEST8. AS mkt,
b.smb * 100 FORMAT=BEST8. AS smb,
b.hml * 100 FORMAT=BEST8. AS hml,
(a.ret - b.rf * 100) FORMAT=BEST8. AS retx
FROM retData AS a LEFT JOIN
ff.factors_daily AS b
ON (a.date = b.date)
WHERE (&START_DATE <= a.date <= &END_DATE)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Keep month x permno pairs with at least 17 observations
**************************************************************************************/
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
MONTH(a.date) FORMAT=2. AS month,
YEAR(a.date) FORMAT=4. AS year
FROM retData AS a
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL;
CREATE TABLE obsData AS
SELECT a.permno,
a.year,
a.month,
COUNT(a.retx) as obs
FROM retData AS a
GROUP BY a.permno,
a.year,
a.month;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM obsData AS a;
QUIT;
PROC SQL;
CREATE TABLE retData AS
SELECT a.*,
b.obs
FROM retData AS a LEFT JOIN
obsData AS b
ON (a.permno = b.permno) AND
(a.year = b.year) AND
(a.month = b.month)
WHERE (b.obs >= 17)
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM retData AS a;
QUIT;
;/*************************************************************************************
@section: Estimate daily factor exposures each month
**************************************************************************************/
%ROLLINGREG(
DATA = retData,
OUT_DS = coefData,
ID = permno,
DATE = date,
MODEL_EQUATION = retx = mkt smb hml,
START_DATE = 1-1-1963,
END_DATE = 12-31-2012,
FREQ = month,
S = 1,
N = 1
);
PROC SQL OUTOBS = 25;
SELECT a.*
FROM coefData AS a;
QUIT;
PROC SQL;
CREATE TABLE coefData AS
SELECT a.*
FROM coefData AS a
ORDER BY a.date2;
QUIT;
;/*************************************************************************************
@section: Create volatility beta portfolios
**************************************************************************************/
PROC RANK DATA = coefData
OUT = rankData
GROUP = 5;
BY date2;
VAR _RMSE_;
RANKS rank;
RUN;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM rankData AS a;
QUIT;
PROC SQL;
CREATE TABLE portData AS
SELECT a.*,
(b.rank + 1) FORMAT=1. AS rank
FROM retData AS a,
rankData AS b
WHERE (a.permno = b.permno) AND
(MONTH(INTNX('month', b.date2, 1)) = MONTH(a.date)) AND
(YEAR(INTNX('month', b.date2, 1)) = YEAR(a.date))
ORDER BY a.permno,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM portData AS a;
QUIT;
PROC SQL;
CREATE TABLE portData AS
SELECT a.rank,
a.date,
MEAN(a.mkt) FORMAT=BEST8. AS mkt,
MEAN(a.smb) FORMAT=BEST8. AS smb,
MEAN(a.hml) FORMAT=BEST8. AS hml,
SUM(a.ret * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS ret,
SUM(a.retx * a.mcap)/SUM(a.mcap) FORMAT=BEST8. AS retx,
MEAN(LOG(a.mcap/1000000)) FORMAT=BEST8. AS mcap
FROM portData AS a
GROUP BY a.rank,
a.date;
QUIT;
PROC SQL OUTOBS = 25;
SELECT a.*
FROM portData AS a;
QUIT;
;/*************************************************************************************
@section: Print data to CSV
**************************************************************************************/
PROC EXPORT
DATA = portData
OUTFILE = "idiosyncratic-volatility-portfolios.csv"
DBMS = CSV
REPLACE;
RUN;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment