knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
The EventStudy package uses an object-oriented model system based on R6 classes.
Every model inherits from ModelBase, which defines the interface that the
pipeline expects. This vignette shows how to create your own custom model and
plug it into the event study workflow.
All models must implement two methods:
fit(data_tbl) -- Estimate model parameters from the estimation window.abnormal_returns(data_tbl) -- Compute abnormal returns for all
observations (estimation + event windows).The fit() method should also populate private$.statistics with at least
sigma and degree_of_freedom, which are used by the test statistics.
Suppose you want an industry-adjusted model where the expected return equals the industry index return rather than the broad market index.
library(EventStudy) IndustryAdjustedModel <- R6::R6Class("IndustryAdjustedModel", inherit = ModelBase, public = list( model_name = "IndustryAdjustedModel", fit = function(data_tbl) { # No estimation needed -- just compute statistics private$.is_fitted <- TRUE private$calculate_statistics(data_tbl) }, abnormal_returns = function(data_tbl) { # AR = firm return - industry index return # Assumes data_tbl has an 'industry_return' column data_tbl %>% dplyr::mutate(abnormal_returns = firm_returns - industry_return) } ), private = list( calculate_statistics = function(data_tbl) { estimation_tbl <- data_tbl %>% dplyr::filter(estimation_window == 1) residuals <- estimation_tbl$firm_returns - estimation_tbl$industry_return private$add_residuals(residuals) private$first_order_autocorrelation(residuals) sigma <- sd(residuals, na.rm = TRUE) private$.statistics$sigma <- sigma private$.statistics$degree_of_freedom <- length(residuals) - 1 # Forecast error correction event_window_tbl <- data_tbl %>% dplyr::filter(event_window == 1) private$calculate_forecast_error_correction( sigma, nrow(estimation_tbl), estimation_tbl$index_returns, event_window_tbl$index_returns ) } ) )
Once defined, use your model exactly like any built-in model:
# Create parameter set with custom model params <- ParameterSet$new( return_model = IndustryAdjustedModel$new() ) # Run the event study task <- EventStudyTask$new(firm_data, index_data, request_data) task <- run_event_study(task, params)
A model that simply computes excess returns over the risk-free rate:
ExcessReturnModel <- R6::R6Class("ExcessReturnModel", inherit = ModelBase, public = list( model_name = "ExcessReturnModel", risk_free_rate = 0.0001, # daily risk-free rate initialize = function(risk_free_rate = 0.0001) { self$risk_free_rate <- risk_free_rate }, fit = function(data_tbl) { private$.is_fitted <- TRUE estimation_tbl <- data_tbl %>% dplyr::filter(estimation_window == 1) residuals <- estimation_tbl$firm_returns - self$risk_free_rate private$.statistics$sigma <- sd(residuals, na.rm = TRUE) private$.statistics$degree_of_freedom <- length(residuals) - 1 private$add_residuals(residuals) private$first_order_autocorrelation(residuals) }, abnormal_returns = function(data_tbl) { data_tbl %>% dplyr::mutate(abnormal_returns = firm_returns - self$risk_free_rate) } ) )
The package includes several built-in factor models that inherit from
LinearFactorModel:
FamaFrench3FactorModel -- SMB, HML, market excessFamaFrench5FactorModel -- adds RMW, CMACarhart4FactorModel -- 3-factor + momentumThese require factor data to be provided via the factor_tbl argument in
EventStudyTask:
# Factor data with date column matching firm/index data factor_data <- tibble::tibble( date = dates, smb = smb_returns, hml = hml_returns, risk_free_rate = rf_rate ) task <- EventStudyTask$new(firm_data, index_data, request_data, factor_tbl = factor_data) params <- ParameterSet$new( return_model = FamaFrench3FactorModel$new() ) task <- run_event_study(task, params)
ModelBasefit() and abnormal_returns()private$.statistics$sigma and private$.statistics$degree_of_freedomprivate$add_residuals() and private$first_order_autocorrelation()
for diagnostics compatibilityprivate$.is_fitted <- TRUE after successful fittingAny scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.