Advertisement
MetricT

Yield Curve, with wavelet-denoised trend and 3 mo forecast

Jan 28th, 2020
1,412
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 7.26 KB | None | 0 0
  1. ################################################################################
  2. ### Script to analyze the yield curve for seasonality
  3. ###    by /u/MetricT
  4. ################################################################################
  5.  
  6. ### Set your FRED API key here.  You may request an API key at:
  7. ### https://research.stlouisfed.org/useraccount/apikeys
  8. api_key_fred <- "WHATEVER_YOUR_FRED_API_KEY_IS"
  9.  
  10. ### Load necessary libraries, installing them if necessary
  11. packages <- c("fredr", "forecast", "lubridate", "tidyverse",
  12.               "tsibble", "WaveletComp")
  13.              
  14. new_packages <- packages[!(packages %in% installed.packages()[, "Package"])]
  15. if (length(new_packages)) install.packages(new_packages, quiet = TRUE)
  16. invisible(lapply(packages, "library", quietly = TRUE, character.only = TRUE))
  17.  
  18. ### Set start/end dates for our graph.   Note that this only affects the final
  19. ### graph, all computations are still done with the full dataset.
  20. date_start <- "2019-01-01" %>% as.Date()
  21. date_end   <- Sys.Date()   %>% as.Date()
  22.  
  23. ### Now that the "fredr" library is loaded, set the FRED API key
  24. fredr_set_key(api_key_fred)
  25.  
  26. ### A list of possible series we can use
  27. series_10yr <- c("DGS10",  "10 Yr")
  28. series_2yr  <- c("DGS2",   "2 Yr")
  29. series_3mo  <- c("DGS3MO", "3 Mo")
  30.  
  31. ### Select the yield curve series to graph.
  32. series_longmaturity  <- series_10yr
  33. series_shortmaturity <- series_3mo
  34.  
  35. ### Pull data for the long and short maturity asset
  36. data_longmaturity  <- fredr(series_id = series_longmaturity[1],
  37.                             frequency = "d") %>%
  38.                             select(date, value) %>%
  39.                             na.omit()
  40.  
  41. data_shortmaturity <- fredr(series_id = series_shortmaturity[1],
  42.                             frequency = "d") %>%
  43.                             select(date, value) %>%
  44.                             na.omit()
  45.  
  46. ### Find the common ground between the two datasets
  47. data_full <- data_longmaturity %>%
  48.              inner_join(data_shortmaturity, by = "date") %>%
  49.              `colnames<-`(c("date", "longmaturity", "shortmaturity"))
  50.  
  51. ### Create a text version of the data to use in the graph title
  52. date_txt <- data_full$date %>% tail(n = 1) %>% format("%B %d, %Y")
  53.  
  54. ### Remove any fractional year data at the beginning of the list, it confuses
  55. ### the forecast() method for some reason.
  56. month_min <- data_full$date %>% head(n = 1) %>% month()
  57. if (month_min != 1) {
  58.      year_min  <- data_full$date %>% head(n = 1) %>% year()
  59.      year_next <- year_min + 1
  60.      date_rounded <- paste(year_next, "-01-01", sep = "")
  61.      data_full <- data_full %>% filter(date >= date_rounded)    
  62. }
  63.  
  64. data_min <- min(data_full$date)
  65.  
  66. ### Computing the yield curve.  This part is easy...
  67. data_full$yield_curve <- data_full$longmaturity - data_full$shortmaturity
  68.  
  69. ### Pull out the raw data
  70. date               <- data_full %>% pull("date")
  71. longmaturity       <- data_full %>% pull("longmaturity")
  72. shortmaturity      <- data_full %>% pull("shortmaturity")
  73.  
  74. ### We'll need this defined later, saves on typing
  75. ts_date <- c(year(min(date)), month(min(date)))
  76.  
  77. ### Decompose the data and extract trend/seasonal/remainder
  78. mstl_longmaturity  <- data_full$longmaturity  %>%
  79.                       ts(frequency = 250, start = ts_date) %>%
  80.                       mstl()
  81.  
  82. mstl_shortmaturity <- data_full$shortmaturity %>%
  83.                       ts(frequency = 250, start = ts_date) %>%
  84.                       mstl()
  85.  
  86. trend_longmaturity      <- mstl_longmaturity  %>% trendcycle()
  87. seasonal_longmaturity   <- mstl_longmaturity  %>% seasonal()
  88. remainder_longmaturity  <- mstl_longmaturity  %>% remainder()
  89.  
  90. trend_shortmaturity     <- mstl_shortmaturity %>% trendcycle()
  91. seasonal_shortmaturity  <- mstl_shortmaturity %>% seasonal()
  92. remainder_shortmaturity <- mstl_shortmaturity %>% remainder()
  93.  
  94. ### Let's save a yield curve based solely on trend
  95. data_full$yield_curve_trend <- trend_longmaturity - trend_shortmaturity
  96.  
  97. ### and another yield curve based on trend + remainder
  98. data_full$yield_curve_trend_remainder <- trend_longmaturity +
  99.                                          remainder_longmaturity -
  100.                                          trend_shortmaturity -
  101.                                          remainder_shortmaturity
  102.  
  103. ### Denoise the non-trend component with wavelets
  104. wavelet_longmaturity  <- (longmaturity - trend_longmaturity) %>%
  105.                          data.frame() %>%
  106.                          `colnames<-`(c("value")) %>%
  107.                          analyze.wavelet("value", dt = 250)
  108.  
  109. wavelet_shortmaturity <- (shortmaturity - trend_shortmaturity) %>%
  110.                          data.frame() %>%
  111.                          `colnames<-`(c("value")) %>%
  112.                          analyze.wavelet("value", dt = 250)
  113.  
  114. r_longmaturity  <- reconstruct(wavelet_longmaturity,  plot.rec = FALSE)
  115. r_shortmaturity <- reconstruct(wavelet_shortmaturity, plot.rec = FALSE)
  116.  
  117. denoised_longmaturity_remainder  <- r_longmaturity$series$value.r +
  118.                                     r_longmaturity$series$value.trend
  119.  
  120. denoised_shortmaturity_remainder <- r_shortmaturity$series$value.r +
  121.                                     r_shortmaturity$series$value.trend
  122.  
  123. ### Add the wavelet-denoised yield curve
  124. data_full$yield_curve_denoised  <- trend_longmaturity +
  125.                                    denoised_longmaturity_remainder -
  126.                                    trend_shortmaturity -
  127.                                    denoised_shortmaturity_remainder
  128.  
  129. ### Filter the data to only graph points between our start/end dates at the
  130. ### top of the script
  131. data_subset <- data_full %>%
  132.                filter(date >= date_start & date <= date_end)
  133.  
  134. ### Derive a three month forecast for the yield curve
  135. forecast <- data_full$yield_curve %>%
  136.             ts(frequency = 250, start = ts_date) %>%
  137.             mstl() %>%
  138.             forecast(h = round(250 * 3 / 12), level = c(68.27)) #, 95.45))
  139.  
  140. ### Find appropriate y limits for our graph
  141. ymin <- forecast$lower %>% data.frame() %>% pull("X68.27.") %>% min(data_subset$yield_curve)
  142. ymax <- forecast$upper %>% data.frame() %>% pull("X68.27.") %>% max(data_subset$yield_curve)
  143.  
  144. ### Labels for our graph
  145. m1 <- paste(series_longmaturity[2], "/",
  146.             series_shortmaturity[2], "Yield Curve for", date_txt, "\n")
  147. m2 <- "With wavelet-denoised trend and three-month forecast"
  148. main <- paste(m1, m2, sep = "")
  149. xlab <- "Year"
  150. ylab <- "Percent"
  151.  
  152. ### Plot the forecast
  153. plot(forecast, main = main, xlab = xlab, ylab = ylab,
  154.      xlim = decimal_date(c(date_start, date_end + months(3))),
  155.      ylim = c(ymin, ymax))
  156.  
  157. ### Add our denoised trend
  158. lines(decimal_date(data_subset$date),  data_subset$yield_curve_denoised, type = "l", col = "blue")
  159. # lines(decimal_date(data_subset$date),  data_subset$yield_curve_trend, type = "l", col = "green")
  160. # lines(decimal_date(data_subset$date),  data_subset$yield_curve_trend_remainder, type = "l", col = "red")
  161.  
  162. ### Add a line at h = 0 denoting the inversion point
  163. abline(h = 0)
  164.  
  165. ### Add lines for the Fed rate changes
  166. abline(v = decimal_date(as.Date("2019-08-01")), lty = 3)
  167. abline(v = decimal_date(as.Date("2019-09-19")), lty = 3)
  168. abline(v = decimal_date(as.Date("2019-10-31")), lty = 3)
  169.  
  170. ### Add lines at 0.4 and 0.2 to aid in seeing how quickly it's declining
  171. abline(h = 0.4, lty = 2)
  172. abline(h = 0.2, lty = 2)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement