library(lubridate)
library(tidyverse)
purrr::walk(list.files(here::here("R"), full.names = T), source)

This file will show how the monetary policy surprises were constructed using a synthetic data series.

The output from using the actual data can be found in ./data/mp-surprises/mp-surprises.csv and ./data/mp-surprises/mp-surprises_all.csv

1 Import (fake) OIS data

First import all (fake) OIS data. This contains OIS data for all available time points.

ois_all <- readr::read_csv(here::here("data", "fake-data", "ois-all.csv"))
ois_all
## # A tibble: 475,314 x 13
##    date_time           ois_9m ois_2m ois_3m ois_1y ois_5m ois_1m ois_6m ois_4m
##    <dttm>               <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
##  1 2001-03-19 10:30:00   4.38  9.65   0.759  6.96   5.48    7.69   6.47 8.70  
##  2 2001-03-19 11:00:00   5.94  7.46   8.18   1.32   7.11    1.10   7.73 7.24  
##  3 2001-03-19 11:30:00   1.48  8.72   3.39   3.11   9.42    2.70   9.15 6.57  
##  4 2001-03-19 12:00:00   1.86  5.37   8.01   5.32   0.841   5.28   7.18 0.0108
##  5 2001-03-19 12:30:00   7.95  8.02   1.91   6.21   6.00    1.56   8.85 0.134 
##  6 2001-03-19 13:00:00   8.55  2.01   9.09   0.157  5.04    6.69   3.47 1.72  
##  7 2001-03-19 13:30:00   4.45  0.116  3.46   0.534  1.20    4.19   9.86 2.91  
##  8 2001-03-19 14:00:00   7.37  3.23   7.72   3.92   0.494   2.62   6.30 7.43  
##  9 2001-03-19 14:30:00   3.39  2.21   0.839  4.94   1.23    3.20   1.73 9.24  
## 10 2001-03-19 15:00:00   1.39  9.12   7.36   4.32   6.25    7.12   2.12 1.89  
## # ... with 475,304 more rows, and 4 more variables: ois_1w <dbl>, ois_2y <dbl>,
## #   ois_3y <dbl>, ois_18m <dbl>

From this object we need to extract the data around monetary policy events/announcements. To do this we must first import a series of monetary policy events/announcements.

mp_dates <- readr::read_csv(here::here("data", "mp-surprises", "mp-dates.csv" ))

mp_board_dates <- mp_dates %>% filter(type == "board_meeting")
mp_board_dates
## # A tibble: 222 x 2
##    date_time           type         
##    <dttm>              <chr>        
##  1 2001-04-04 09:30:00 board_meeting
##  2 2001-05-02 09:30:00 board_meeting
##  3 2001-06-06 09:30:00 board_meeting
##  4 2001-07-04 09:30:00 board_meeting
##  5 2001-08-08 09:30:00 board_meeting
##  6 2001-09-05 09:30:00 board_meeting
##  7 2001-10-03 09:30:00 board_meeting
##  8 2001-11-07 09:30:00 board_meeting
##  9 2001-12-05 09:30:00 board_meeting
## 10 2002-02-06 09:30:00 board_meeting
## # ... with 212 more rows

2 Extract relevant data

Using the user defined function data_window_extract I feed through the ois_all object and ask it to extract the data around the mp_board_dates$date_time. The window is given through the arguments pre (minutes before), post (minutes after) and open_window (minutes after open if the monetary policy event falls between close and open)

ois_mp <- data_window_extract(ois_all, mp_board_dates$date_time, pre = 30, post = 90, open_window = 60)

ois_mp
## # A tibble: 424 x 15
##    date_time           name  value               ois_9m ois_2m ois_3m ois_1y
##    <dttm>              <chr> <dttm>               <dbl>  <dbl>  <dbl>  <dbl>
##  1 2001-04-04 09:30:00 pre   2001-04-04 09:00:00  0.836   9.43   9.03  8.17 
##  2 2001-04-04 09:30:00 post  2001-04-04 11:00:00  5.33    6.59   6.49  7.98 
##  3 2001-05-02 09:30:00 pre   2001-05-02 09:00:00  3.68    9.69   3.72  8.34 
##  4 2001-05-02 09:30:00 post  2001-05-02 11:00:00  3.05    3.35   6.00  0.452
##  5 2001-06-06 09:30:00 pre   2001-06-06 09:00:00  0.688   4.88   4.80  8.13 
##  6 2001-06-06 09:30:00 post  2001-06-06 11:00:00  5.45    3.86   7.39  9.49 
##  7 2001-07-04 09:30:00 pre   2001-07-04 09:00:00  8.51    8.79   5.08  1.42 
##  8 2001-07-04 09:30:00 post  2001-07-04 11:00:00  4.05    7.37   1.38  0.187
##  9 2001-08-08 09:30:00 pre   2001-08-08 09:00:00  3.32    9.71   1.51  7.11 
## 10 2001-08-08 09:30:00 post  2001-08-08 11:00:00  5.43    7.49   1.00  0.449
## # ... with 414 more rows, and 8 more variables: ois_5m <dbl>, ois_1m <dbl>,
## #   ois_6m <dbl>, ois_4m <dbl>, ois_1w <dbl>, ois_2y <dbl>, ois_3y <dbl>,
## #   ois_18m <dbl>

3 Transform data

Now we have the necessary data to create the measure of monetary policy surprises. First, for each tenor, I’ll calculate the change in the OIS contract around a monetary policy announcement.

ois_surprise <- ois_mp %>% 
    select(-value) %>% # remove `value` column which contains actual date-time of extracted data point
    pivot_longer( starts_with("ois") ,  names_to = "tenor") %>%
    pivot_wider( names_from = name, values_from = value) %>%
    mutate(mp_change = post - pre) %>%  # calculate change in OIS around monetary policy announcement
    select(-pre, - post) %>% 
    pivot_wider(names_from = tenor, values_from = mp_change) 
ois_surprise
## # A tibble: 212 x 13
##    date_time            ois_9m ois_2m ois_3m ois_1y ois_5m ois_1m ois_6m ois_4m
##    <dttm>                <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
##  1 2001-04-04 09:30:00  4.49   -2.84  -2.54  -0.189  3.38  -6.28   3.77   -9.39
##  2 2001-05-02 09:30:00 -0.632  -6.35   2.29  -7.89  -2.62   0.766  8.47    8.18
##  3 2001-06-06 09:30:00  4.77   -1.02   2.59   1.36   0.578  1.82  -1.49    2.80
##  4 2001-07-04 09:30:00 -4.46   -1.43  -3.69  -1.23  -1.28   1.71   0.394   9.03
##  5 2001-08-08 09:30:00  2.11   -2.21  -0.510 -6.67  -0.452 -0.284 -2.74   -3.98
##  6 2001-09-05 09:30:00 -0.460   0.132 -5.47  -1.27  -3.62  -1.68   1.10    6.32
##  7 2001-10-03 09:30:00 -3.28   -7.55   2.19   7.65  -0.340  6.33  -4.68    1.53
##  8 2001-11-07 09:30:00 -0.0488  4.59  -4.36  -1.74  -2.35  -0.262  1.00   -7.92
##  9 2001-12-05 09:30:00 -1.61   -9.09  -0.213 -6.74  -3.96   4.94  -1.78    2.00
## 10 2002-02-06 09:30:00  2.28    8.10   1.28  -1.64  -1.61  -5.89   8.05   -2.09
## # ... with 202 more rows, and 4 more variables: ois_1w <dbl>, ois_2y <dbl>,
## #   ois_3y <dbl>, ois_18m <dbl>

4 Create monetary policy surprises

To create the measure of monetary policy surprises first take the ois_surprise data and perform the principal component analysis.

pca_data <- ois_surprise %>% 
  select(-ois_1w, -ois_18m, -ois_2y, -ois_3y) # remove tenors not used in the analysis.

pca_data <- pca_data[ rowSums(is.na(pca_data)) == 0 , ] # remove row if it contains an NA

pca <- prcomp(pca_data %>% select(-date_time), center = T, scale. = T ) # perform pca

pca_surprise <-  bind_cols( decision_date_time = pca_data$date_time, 
                            decision_date = lubridate::date(pca_data$date_time),
                            as_tibble(pca$x)  ) # put in nice dataframe

As the factors from PCA are scaleless, I scale the PCA surprises to the change in the 1-month OIS. This allows the surprises to be interpreted as a 100 basis point change in the 1-month OIS.

mp_surprises_all <- left_join(pca_surprise, ois_surprise, by = c("decision_date_time" = "date_time" )) %>% 
                     mp_surprise_scale(., pc = "PC1", scale = "ois_1m") %>%  # scale PC1 by ois_1m
                      relocate(decision_date_time, decision_date, pc1_scaled)
mp_surprises_all
## # A tibble: 212 x 23
##    decision_date_time  decision_date pc1_scaled    PC1    PC2     PC3     PC4
##    <dttm>              <date>             <dbl>  <dbl>  <dbl>   <dbl>   <dbl>
##  1 2001-04-04 09:30:00 2001-04-04        -1.05  -1.60   1.41  -1.62    1.14  
##  2 2001-05-02 09:30:00 2001-05-02        -1.06  -1.62  -2.20   0.400  -1.96  
##  3 2001-06-06 09:30:00 2001-06-06         0.183  0.279  0.233  0.713  -0.502 
##  4 2001-07-04 09:30:00 2001-07-04         0.752  1.14  -1.94   0.0117 -0.759 
##  5 2001-08-08 09:30:00 2001-08-08        -0.438 -0.667 -0.584 -0.207   0.148 
##  6 2001-09-05 09:30:00 2001-09-05         0.176  0.267 -1.42  -0.952  -0.453 
##  7 2001-10-03 09:30:00 2001-10-03         0.904  1.38  -0.595  2.44    1.52  
##  8 2001-11-07 09:30:00 2001-11-07        -0.422 -0.642  0.706 -0.715   0.530 
##  9 2001-12-05 09:30:00 2001-12-05        -0.388 -0.590 -2.67   1.32    0.0605
## 10 2002-02-06 09:30:00 2002-02-06        -0.975 -1.48   1.65  -1.37   -1.16  
## # ... with 202 more rows, and 16 more variables: PC5 <dbl>, PC6 <dbl>,
## #   PC7 <dbl>, PC8 <dbl>, ois_9m <dbl>, ois_2m <dbl>, ois_3m <dbl>,
## #   ois_1y <dbl>, ois_5m <dbl>, ois_1m <dbl>, ois_6m <dbl>, ois_4m <dbl>,
## #   ois_1w <dbl>, ois_2y <dbl>, ois_3y <dbl>, ois_18m <dbl>

You can plot the synthetic monetary policy surprises as in Figure 2 in the RDP as follows:

p <- ggplot(mp_surprises_all, aes(x = decision_date, y = pc1_scaled)) +
  geom_col() +
  rba_theme() +
  rba_syc() +
  ylab("%") +
  rba_ylim(-3, 3) +
  labs(title = "Figure 2: Monetary Policy Surprises", subtitle = "Factor 1, scaled to one-month OIS",
       caption = "Sources: RBA")  +
  rba_panel_text_size(title = 2, subtitle = 1.2) +
  scale_fill_rba()

rba_xticks_date(p) # add more x-ticks

5 All monetary policy events

The same process can be done for to create the monetary policy surprises using all monetary policy communication dates. Simply expand the object mp_board_dates to include other dates outside the monetary policy announcement.

6 Equity and earnings changes around monetary policy events

The construction of the files in ./data/equities/ and ./data/earnings/ are constructed in a similar manner to how the object ois_mp is constructed. I will therefore not replicate this process.

7 Session Information

sessionInfo()
## R version 4.0.3 (2020-10-10)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 14393)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_Australia.1252  LC_CTYPE=English_Australia.1252   
## [3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C                      
## [5] LC_TIME=English_Australia.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] forcats_0.5.1    stringr_1.4.0    dplyr_1.0.5      purrr_0.3.4     
##  [5] readr_1.4.0      tidyr_1.1.3      tibble_3.1.0     ggplot2_3.3.3   
##  [9] tidyverse_1.3.0  lubridate_1.7.10
## 
## loaded via a namespace (and not attached):
##  [1] tidyselect_1.1.0  xfun_0.20         bslib_0.2.4       haven_2.3.1      
##  [5] colorspace_2.0-0  vctrs_0.3.7       generics_0.1.0    htmltools_0.5.1.1
##  [9] yaml_2.2.1        utf8_1.2.1        rlang_0.4.10      jquerylib_0.1.3  
## [13] pillar_1.5.1      withr_2.4.1       glue_1.4.2        DBI_1.1.1        
## [17] dbplyr_2.1.0      modelr_0.1.8      readxl_1.3.1      lifecycle_1.0.0  
## [21] munsell_0.5.0     gtable_0.3.0      cellranger_1.1.0  rvest_1.0.0      
## [25] evaluate_0.14     labeling_0.4.2    knitr_1.31        fansi_0.4.2      
## [29] highr_0.8         broom_0.7.5       Rcpp_1.0.6        backports_1.2.1  
## [33] scales_1.1.1      jsonlite_1.7.2    farver_2.1.0      fs_1.5.0         
## [37] hms_1.0.0         digest_0.6.27     stringi_1.5.3     rprojroot_2.0.2  
## [41] grid_4.0.3        here_1.0.1        cli_2.4.0         tools_4.0.3      
## [45] magrittr_2.0.1    sass_0.3.1        crayon_1.4.1      pkgconfig_2.0.3  
## [49] ellipsis_0.3.1    xml2_1.3.2        reprex_1.0.0      rstudioapi_0.13  
## [53] assertthat_0.2.1  rmarkdown_2.7     httr_1.4.2        R6_2.5.0         
## [57] compiler_4.0.3