--- title: "Creating Custom Test Statistics" author: "Simon Mueller" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Creating Custom Test Statistics} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` # Introduction The EventStudy package supports two types of test statistics: 1. **Single-event statistics** -- Computed for each event individually (e.g., AR t-test, CAR t-test) 2. **Multi-event statistics** -- Computed across all events in a group (e.g., Cross-Sectional t-test, Patell Z, Sign test) Both types inherit from `TestStatisticBase` and implement a `compute()` method. This vignette walks through creating custom test statistics of each type. # The TestStatisticBase Interface Every test statistic must: 1. Inherit from `TestStatisticBase` 2. Set a `name` field (short code used as column name in results) 3. Implement `compute(data_tbl, model)` returning a tibble For single-event tests, `data_tbl` contains one event's data and `model` is the fitted model for that event. For multi-event tests, `data_tbl` contains all events in a group and `model` is a nested tibble of all models. # Example: Wilcoxon Signed-Rank Test (Single Event) A non-parametric test for whether abnormal returns in the event window are symmetrically distributed around zero: ```{r, eval=FALSE} library(EventStudy) WilcoxonARTest <- R6::R6Class("WilcoxonARTest", inherit = TestStatisticBase, public = list( name = "WilcoxonAR", compute = function(data_tbl, model) { event_data <- data_tbl %>% dplyr::filter(event_window == 1) ar <- event_data$abnormal_returns # Wilcoxon signed-rank test against 0 test_result <- wilcox.test(ar, mu = 0, conf.int = TRUE) tibble::tibble( n_obs = length(ar), V_statistic = test_result$statistic, p_value = test_result$p.value, median_ar = median(ar, na.rm = TRUE), conf_low = test_result$conf.int[1], conf_high = test_result$conf.int[2] ) } ) ) ``` # Example: Kolmogorov-Smirnov Test (Multi-Event) A non-parametric test comparing the distribution of AARs against a normal distribution: ```{r, eval=FALSE} KSTest <- R6::R6Class("KSTest", inherit = TestStatisticBase, public = list( name = "KS", compute = function(data_tbl, model) { aar_stats <- data_tbl %>% dplyr::filter(event_window == 1) %>% dplyr::group_by(relative_index) %>% dplyr::summarise( aar = mean(abnormal_returns, na.rm = TRUE), n_events = dplyr::n(), n_pos = sum(abnormal_returns > 0, na.rm = TRUE), n_neg = sum(abnormal_returns <= 0, na.rm = TRUE), .groups = "drop" ) %>% dplyr::mutate(caar = cumsum(aar)) # KS test of AARs against normal ks <- ks.test(aar_stats$aar, "pnorm", mean = 0, sd = sd(aar_stats$aar)) aar_stats %>% dplyr::mutate( ks_D = ks$statistic, ks_pvalue = ks$p.value ) } ) ) ``` # Registering Custom Statistics Add your test statistic to a statistics set: ```{r, eval=FALSE} # Single-event: add to SingleEventStatisticsSet single_stats <- SingleEventStatisticsSet$new() single_stats$add_test(WilcoxonARTest$new()) # Multi-event: add to MultiEventStatisticsSet multi_stats <- MultiEventStatisticsSet$new() multi_stats$add_test(KSTest$new()) # Or create a custom set from scratch custom_single <- StatisticsSetBase$new( tests = list(ARTTest$new(), CARTTest$new(), WilcoxonARTest$new()) ) ``` # Using Custom Statistics in the Pipeline ```{r, eval=FALSE} params <- ParameterSet$new( single_event_statistics = single_stats, multi_event_statistics = multi_stats ) task <- EventStudyTask$new(firm_data, index_data, request_data) task <- run_event_study(task, params) # Results appear as columns in the task data task$data_tbl$WilcoxonAR # single-event results task$aar_caar_tbl$KS # multi-event results ``` # Built-in Test Statistics The package includes the following built-in test statistics: **Single-event:** - `ARTTest` -- Abnormal Return t-test - `CARTTest` -- Cumulative Abnormal Return t-test - `BHARTTest` -- Buy-and-Hold Abnormal Return t-test **Multi-event:** - `CSectTTest` -- Cross-Sectional t-test (AAR/CAAR) - `PatellZTest` -- Patell standardized residual test - `SignTest` -- Simple sign test - `GeneralizedSignTest` -- Cowan (1992) generalized sign test - `RankTest` -- Corrado (1989) rank test - `BMPTest` -- Boehmer, Musumeci & Poulsen (1991) test - `CalendarTimePortfolioTest` -- Calendar-time portfolio approach # Key Points - Inherit from `TestStatisticBase` - Set a unique `name` field (becomes the column name in results) - Return a tibble from `compute()` - For multi-event stats, include `relative_index`, `aar`, `caar`, and `car_window` columns for compatibility with plotting functions - Use `add_test()` to add to existing statistics sets