Created
May 15, 2014 15:08
-
-
Save alexchinco/d58ebd7750904db1b94c to your computer and use it in GitHub Desktop.
Code to replicate main results in Ang, Hodrick, Xing, and Zhang (2006)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## 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 = '')) | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## 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 = '')) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;/************************************************************************************* | |
@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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;/************************************************************************************* | |
@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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;/************************************************************************************* | |
@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