library(lubridate)
library(tidyverse)
::walk(list.files(here::here("R"), full.names = T), source) purrr
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
First import all (fake) OIS data. This contains OIS data for all available time points.
<- readr::read_csv(here::here("data", "fake-data", "ois-all.csv"))
ois_all 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.
<- readr::read_csv(here::here("data", "mp-surprises", "mp-dates.csv" ))
mp_dates
<- mp_dates %>% filter(type == "board_meeting")
mp_board_dates 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
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)
<- data_window_extract(ois_all, mp_board_dates$date_time, pre = 30, post = 90, open_window = 60)
ois_mp
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>
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_mp %>%
ois_surprise 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>
To create the measure of monetary policy surprises first take the ois_surprise
data and perform the principal component analysis.
<- ois_surprise %>%
pca_data select(-ois_1w, -ois_18m, -ois_2y, -ois_3y) # remove tenors not used in the analysis.
<- pca_data[ rowSums(is.na(pca_data)) == 0 , ] # remove row if it contains an NA
pca_data
<- prcomp(pca_data %>% select(-date_time), center = T, scale. = T ) # perform pca
pca
<- bind_cols( decision_date_time = pca_data$date_time,
pca_surprise 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.
<- left_join(pca_surprise, ois_surprise, by = c("decision_date_time" = "date_time" )) %>%
mp_surprises_all 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:
<- ggplot(mp_surprises_all, aes(x = decision_date, y = pc1_scaled)) +
p 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
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.
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.
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