Voting on Adopting Majority Voting (MV)

Data step

# Connect to PostgreSQL database
library(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
pg <- dbConnect(drv, dbname = "crsp")

rs <- dbGetQuery(pg, "DROP TABLE IF EXISTS destagger.mv_fund_rank")
rs <- dbGetQuery(pg, "
    CREATE TABLE destagger.mv_fund_rank AS
        SELECT instid, num_votes, rank() OVER (ORDER BY num_votes DESC) AS fund_rank
        FROM (
            SELECT instid, count(*) AS num_votes 
            FROM (
                SELECT DISTINCT instid, itemonagendaid 
                FROM issvoting.fund_votes
                WHERE issagendaitemid='S0212') AS b
            GROUP BY instid 
            ORDER BY num_votes DESC) AS a")

# Pull in votes from ISS Voting Analytics 
rs <- dbGetQuery(pg, "DROP TABLE IF EXISTS destagger.mv_votes")
sql <- "
    CREATE TABLE destagger.mv_votes AS
    SELECT * FROM issvoting.compvotes AS a
    LEFT JOIN (        
        SELECT itemonagendaid, min(fund_rank) AS rank_fund_against
        FROM issvoting.fund_votes AS a
        INNER JOIN destagger.mv_fund_rank AS b
        USING (instid)
        WHERE fundvote='Against' 
        GROUP BY itemonagendaid) AS b
    USING (itemonagendaid)
    WHERE issagendaitemid='S0212'
    ORDER BY issagendaitemid"
rs <- dbGetQuery(pg, sql)

# Add PERMNO and GVKEY to the table (match to CUSIP)
rs <- dbGetQuery(pg, 
                 "ALTER TABLE destagger.mv_votes ADD COLUMN gvkey character(6)")
rs <- dbGetQuery(pg,
                 "ALTER TABLE destagger.mv_votes ADD COLUMN permno integer")
rs <- dbGetQuery(pg,
    "UPDATE destagger.mv_votes AS a SET gvkey = 
        (SELECT gvkey FROM destagger.gvkeys AS b 
        WHERE b.cusip=a.cusip)")
rs <- dbGetQuery(pg,
    "UPDATE destagger.mv_votes AS a SET permno = 
        (SELECT DISTINCT permno FROM crsp.stocknames AS b 
                 WHERE b.ncusip=substr(a.cusip,1,8))")

# Pull data into R
declassify <- dbGetQuery(pg, "SELECT * FROM destagger.mv_votes")
rs <- dbDisconnect(pg)
library(RPostgreSQL)
drv <- dbDriver("PostgreSQL") 
pg <- dbConnect(drv, dbname = "crsp")

# Get returns around meeting dates
dropbox.path <- path.expand("~/Dropbox/research/AGL/")
source(paste(dropbox.path,"Code/R/getEventReturns.R",sep="")) 
ret_data <- getEventReturns(declassify$permno, declassify$meetingdate,
                            days.before=0, days.after=0)
## Initializing database connection...                   0.00 seconds
## Preparing data for upload to database...              0.00 seconds
## Writing list of PERMNOs and event dates to database...0.10 seconds
## Identifying relevant trading dates...                 0.03 seconds
## Compounding raw returns...                            0.19 seconds
## Compounding value-weighted market returns...          0.01 seconds
## Compounding size-decile market returns...             0.01 seconds
ret_data$row.names <- NULL
ret_data <- unique(ret_data) # Drop duplicates (multiple votes at a single meeting)

# Put return data back in the database
rs <- dbWriteTable(pg, c("destagger", "mv_ret_data"), ret_data,
                   overwrite=TRUE, row.names=FALSE)

# Get data including a measure of shareholder support relative to "base"
# (e.g., shares outstanding) specified for each vote.
declassify <- dbGetQuery(pg, "SELECT *,
  CASE WHEN base='Outstanding' AND outstandingshares>0 THEN votedfor/outstandingshares
    WHEN base='F+A' AND votedfor+votedagainst>0
      THEN votedfor/(votedfor+votedagainst)
    WHEN base='F+A+AB' AND votedfor+votedagainst+votedabstain>0 
      THEN votedfor/(votedfor+votedagainst+votedabstain)
    END AS percent_for
  FROM destagger.mv_votes AS a
  LEFT JOIN destagger.mv_ret_data AS b
  USING (permno)
  WHERE a.meetingdate=b.event_date AND result IN ('Fail', 'Pass')")
rs <- dbDisconnect(pg)

Some descriptive statistics

Does ISS ever vary in its recommendation? Rarely so; it almost always recommends shareholders vote to adopt majority voting.

with(declassify, table(mgtrec, issrec))
##          issrec
## mgtrec    Against Do Not Vote For
##   Abstain       0           0   1
##   Against       5           1 239
##   For           0           1   7
##   None          0           0   4

There are 258 votes on majority voting in the sample, with 58.53% being rejections by shareholders. Here they are by year.

## Descriptive statistics
declassify$year <- format(declassify$meetingdate, "%Y")
with(declassify, table(year, result))
##       result
## year   Fail Pass
##   2005   42   13
##   2006   57   37
##   2007   22   15
##   2008   13   12
##   2009   17   30

The votes are fairly well dispersed around the cutoff.
Note that these are only shareholder-sponsored votes.

# Produce a histogram of (SVT - allowable cap)
library(ggplot2)
qplot(percent_for - voterequirements, 
      data=subset(declassify,
                  percent_for <1 & percent_for > 0.01), 
      binwidth=.01, 
      main="Histogram: Shareholder support minus vote requirement",
      xlab="Shareholder support minus vote requirement")

plot of chunk unnamed-chunk-1

But there's virtually no response by the market to the result of the vote.

qplot(percent_for - voterequirements, ret_mkt,
      data=subset(declassify, 
                  percent_for <1 & percent_for > 0.01),
      main="Market-adjusted Stock Returns: Days (0,1) Around Meeting Dates",
      xlab="Shareholder support minus vote requirement",
      color=issrec)

plot of chunk unnamed-chunk-2


qplot(percent_for - voterequirements, ret_mkt,
      data=subset(declassify, 
                  percent_for <1 & percent_for > 0.01),
      main="Market-adjusted Stock Returns: Days (0,1) Around Meeting Dates",
      xlab="Shareholder support minus vote requirement",
      color=mgtrec)

plot of chunk unnamed-chunk-2

Estimation and inference

source("~/Dropbox/research/rdd/rd_opt_bw.R")
# source('http://iangow.me/~iangow/rd_opt_bw.R') (4) Calculate the
# treatment effect and standard errors.
table(declassify$rank_fund_against)
## 
##   1   2   4   5   6   8  12  18  26  39 135 143 
## 150   1   7   1  31  11   1   2   1   8  37   4 
rd_data <- subset(declassify, subset = percent_for < 1 & percent_for > 
    0.01, select = c(ret_mkt, percent_for, voterequirements))
rd_data$fundvote <- 1
rd_data$x <- (rd_data$percent_for - rd_data$voterequirements) * rd_data$fundvote
rd_data$y <- rd_data$ret_mkt

# First, get bandwidth
h <- with(rd_data, rd_opt_bw(y, x, c = 0))
X <- rd_data$x
c <- 0

## Weights based on triangular kernel
wgts <- with(rd_data, (1 - abs(X - c)/h) * (abs(X - c) <= h))
local.lm <- lm(y ~ (x >= c) * x, weights = wgts, data = rd_data)

rd.est <- coef(local.lm)[[2]]
sd.est <- sqrt(vcov(local.lm)[2, 2])

## Output
out <- c(h, rd.est, sd.est, rd.est/sd.est)
names(out) <- c("Optimal Bandwidth", "RD Estimate", "Standard Error", 
    "t-statistic")
print(out)
## Optimal Bandwidth       RD Estimate    Standard Error       t-statistic 
##          0.177364          0.006574          0.005441          1.208205 

A plot of the data with fitted values

# A function to estimate local linear regression around a point (x_i)
# using bandwidth h, the triangular kernel and limiting observations to
# those on the same side of the cutoff c. In some sense, this is purely
# visual, as the IK bandwidth is optimized for x \in [c-h, c+h] and other
# data are not involved.
ll <- function(x_i, y, x, h, c) {
    wgts <- (1 - abs(x - x_i)/h) * (abs(x - x_i) <= h) * (sign(x_i - c) == sign(x - 
        c) | x_i == c)
    lm.fitted <- lm(y ~ x, weights = wgts)
    if (sum(wgts > 0) > 10) {
        # Require 10 observations around x_i
        return(predict(lm.fitted, newdata = data.frame(x = x_i)))
    } else {
        return(NA)
    }
}

# Add the fitted value to the dataset
library(parallel)
rd_data$y_fitted <- with(rd_data, unlist(mclapply(X, ll, y, X, h, 
    c, mc.cores = 12)))

# Make a plot
library(ggplot2)
ggplot(rd_data, aes(x)) + geom_point(aes(y = y, color = x > c)) + 
    geom_line(aes(y = y_fitted, color = x > c))

plot of chunk plot

Fund voting behavior

While there is essentially no variation in how ISS recommends its clients vote on shareholder proposals to adopt majority voting, it seems there is quite a bit of variation in how mutual funds vote. Some funds mostly side with management, others go with ISS (though it is very difficult to argue causality without additional evidence), while others mix it up. It might be interesting to see whether the ones that mix it up do so in a way consistent with shareholder-value maximization, but inconsistent with the view of ISS (and Bebchuk) of a one-size-fits-all solution here. For example, if we looked at stock returns around the time of the vote, is there a relationship (say, using RDD) between the outcome of the vote, stock returns, and how these mutual funds voted. More specifically, if the “horses for courses” shareholders voted to reject the shareholder proposal, did the market react positively (negatively) to a failed (passed) proposal? (Note that it's not clear exactly how to measure how “horses for courses” shareholders voted, as it's unlikely that all such shareholders voted in the same way on each measure.)

##                                 institutionname percent_for num_votes
## 1                Fidelity Management & Research     0.46774       376
## 2                      BlackRock Advisors, Inc.     0.69970       344
## 3                            Transamerica Funds     0.71472       341
## 4                    IQ Investment Advisors LLC     0.72483       338
## 5                 AST Investment Services, Inc.     0.66771       334
## 6                          Prudential Financial     0.77083       307
## 7                       John Hancock Funds, LLC     0.63704       297
## 8             Northern Trust Global Investments     0.50355       286
## 9        Jackson National Asset Management, LLC     0.89668       277
## 10          T. Rowe Price Associates, Inc. (MD)     0.98148       272
## 11                                Phoenix Funds     0.87938       266
## 12            General Electric Asset Management     0.15000       263
## 13                    Northwestern Mutual Funds     0.89370       258
## 14             RS Investment Management Co. LLC     0.89370       256
## 15      New York Life Investment Management LLC     0.86290       251
## 16                         Vanguard Group, Inc.     0.08130       248
## 17                     Russell Investment Group     0.82231       246
## 18                    Munder Capital Management     0.96721       244
## 19               TIAA-CREF Asset Management LLC     0.79476       241
## 20         JPMorgan Asset Management, Inc. (US)     0.90789       240
## 21                  RiverSource Investments LLC     0.97854       239
## 22         Rodney Square Management Corporation     0.06481       239
## 23                   AIM Management Group, Inc.     0.93590       239
## 24                            Rydex Investments     0.03211       236
## 25            Wells Fargo Funds Management, LLC     0.95575       226
## 26   Charles Schwab Investment Management, Inc.     0.94203       210
## 27 American Century Investment Management, Inc.     0.01951       209
## 28    Evergreen Investment Management Co., Inc.     0.97790       187
## 29                  Nationwide Fund<a0>Advisors     0.63536       182
## 30                     Nationwide Fund Advisors     0.63636       114
## 31     Charles Schwab Investment Management, In     0.97778        47
## 32     Evergreen Investment Management Co., Inc     0.97778        45
## 33      American Century Investment Management,     0.00000        41
## 34                     Nationwide Fund Advisors     0.93333        32