Nazaj finance R

Uvod

Krivulja donosnosti obveznic (angl. yield curve) se pogosto uporablja kot indikator prihajajoče recesije. V tem prispevku se bomo osredotočili na krivuljo donosnosti ameriških obveznic in hipotezo preverili na zgodovinskih podatkih.

Kaj je krivulja donosnosti obveznic?

Krivulja donosnosti obvezni je črta, ki povezuje donose različnih zapadlosti obveznic. Krivulja je ponavadi obrnjena navzgor in pogosto ni ravna črta, kar je odvisno od tveganja, segmentacije, likvidnosti in ostalih bolj kompleksnih elementov. Ko se krivulja obrne, so donosi kratkoročnih obveznic večji od donosov dolgoročnih obveznic. Razlogov za obrat je več, vendar se pogosto obrat interpretira kot znak prihajajoče recesije.

Zakaj naj bi obrnjena krivulja donosnosti obveznic napovedovala recesijo? To sicer ni nobena zakonitost, a vlagatelji in finančni svetovalci pogosto verjamejo, da omenjeno drži, ker:

Trenutni ni splošnega soglasja o tem, kateri del krivulje donosnosti obveznic naj uporabimo za za napovedovanje recesije. Pogosto se sicer uporabljajo donosi kratkoročnih in dolgoročnih obveznic, kjer se osredotočimo na medsebojne razlike.

Pri analizi podatkov bomo potrebovali knjižnico xlsx, s katero bomo prebrali podatke iz Excel datoteke (Federal Reserve Bank of New York 2021) in knjižnico tidyverse za manipulacijo s podatki in njihovo vizualizacijo.

library(xlsx)
library(tidyverse)

Podatki Federal Reserve Bank of New York (2021) so na voljo v obliki Excel datoteke (glej tabelo 1). Vsaka vrstica predstavlja povzetek tekočega meseca od leta \(1959\) naprej, kjer je na voljo donosnost \(10\) letne in \(3\) mesečne obveznice, medsebojna razlika v donosu, napovedana verjetnost recesije in dejanski indikator ali je recesija prisotna.

podatki <-
  read.xlsx2(
    file = "data/allmonth.xls", sheetIndex = 1, check.names = FALSE, 
    colClasses = c("integer", rep("numeric", 6))
  ) %>%
  mutate_at(2:7, function(x) { ifelse(is.nan(x), NA, x) }) %>%
  mutate(Date = as.Date(Date, origin = "1899-12-30"))
Tabela 1: Podatki iz Federal Reserve Bank of New York (2021)

Iz podatkov izluščimo začetke in konce vseh gospodarskih recesij v ZDA ter dodajmo kratke opise (glej tabelo 2), ki jih bomo prikazali na grafu 1.

recesije <-
  podatki %>%
  select(Date, NBER_Rec) %>%
  filter(!is.na(NBER_Rec)) %>%
  mutate(
    NBER_Rec_prev = lag(NBER_Rec),
    NBER_Rec_next = lead(NBER_Rec),
    akcija = ifelse((NBER_Rec_prev == 0 | is.na(NBER_Rec_prev)) & NBER_Rec == 1, "zacetek", NA),
    akcija = ifelse((NBER_Rec_next == 0 | is.na(NBER_Rec_next)) & NBER_Rec == 1, "konec", akcija)
  ) %>%
  filter(!is.na(akcija)) %>%
  select(Date, akcija) %>%
  rownames_to_column(var = "id") %>%
  mutate(id = ceiling(as.numeric(id)/2)) %>%
  pivot_wider(names_from = akcija, values_from = Date) %>%
  select(-id) %>%
  cbind("Opis" = c(
    "Recesija 1960-61", "Recesija 1970", "Recesija 1973-75", "Recesija 1980", "Recesija 1981-82", 
    "Recesija 1990-91", "Recesija 2001", "Velika recesija 2008-09", "COVID-19 recesija"
  ))
Tabela 2: Gospodarske recesije od leta \(1959\) naprej
Začetek Konec Opis
1960-05-31 1961-02-28 Recesija 1960-61
1970-01-31 1970-11-30 Recesija 1970
1973-12-31 1975-03-31 Recesija 1973-75
1980-02-29 1980-07-31 Recesija 1980
1981-08-31 1982-11-30 Recesija 1981-82
1990-08-31 1991-03-31 Recesija 1990-91
2001-04-30 2001-11-30 Recesija 2001
2008-01-31 2009-06-30 Velika recesija 2008-09
2020-03-31 2020-11-30 COVID-19 recesija

Graf na sliki 1 prikazuje razliko v donosu dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) ameriških obveznic, kjer so zasenčeno s sivo barvo označena obdobja gospodarskih recesij.

yMin <- min(podatki[, "Spread"], na.rm = TRUE)
yMax <- max(podatki[, "Spread"], na.rm = TRUE)

podatki %>%
  filter(!is.na(Spread)) %>%
  ggplot(aes(x = Date, y = Spread)) +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray", size = .3) +
  geom_rect(
    data = recesije %>% mutate(Date = zacetek, Spread = 0), alpha = .1, 
    mapping = aes(xmin = zacetek, xmax = konec, ymin = yMin, ymax = yMax)
  ) +
  geom_line(color = "blue") +
  geom_label_repel(
    data = recesije %>% 
      mutate(
        Date = recesije$zacetek + difftime(recesije$konec, recesije$zacetek)/2, 
        Spread = yMax
      ),
    mapping = aes(label = Opis),
    force = 10,
    direction = "both",
    nudge_y = 1, 
    color = "gray", size = 4
  ) +
  ylim(c(yMin, yMax * 1.3)) +
  xlab("") + ylab("Razlika v donosu (%)") +
  theme_classic() + 
  theme(
    axis.text = element_text(size = 12),
    axis.title = element_text(size = 12)
  )
**Razlika v donosu** dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) **ameriških obveznic** in **obdobja gospodarskih recesij**

Slika 1: Razlika v donosu dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) ameriških obveznic in obdobja gospodarskih recesij

Najprej bomo zgradili enostavni napovedni model, kjer bomo zgolj spremljali predznak razlike v dodnosu obveznic, nato pa bomo nadaljevali z napovednimi modeli, ki bodo temeljili na preprosti logistični regresiji, kjer bomo napovedovali recesijo na podlagi razlike v donosu in verjetnosti za recesijo.

napovedniModel <- function(podatki, odvisna_spremenljivka, neodvisna_spremenljivka, pogoj = 0.5, pogojFormula = NA, mnozicaDatum = NA) {
  podatki.izbrani <- 
    podatki %>% 
    filter(!is.na(!!sym(odvisna_spremenljivka)) & !is.na(!!sym(neodvisna_spremenljivka))) %>%
    select(Date, odvisna_spremenljivka, neodvisna_spremenljivka)
  
  U.datum.min <- min(podatki.izbrani$Date)
  U.datum.max <- max(podatki.izbrani$Date)
  T.datum.min <- U.datum.min
  T.datum.max <- U.datum.max
  
  if (!is.na(pogoj) & is.na(pogojFormula)) {
    if (is.na(mnozicaDatum)) {
      model <- glm(
        as.formula(paste0(odvisna_spremenljivka, " ~ ", neodvisna_spremenljivka)), 
        podatki.izbrani, family = binomial
      )
      napoved <- predict(model, podatki.izbrani, type = "response")
      verjetnosti <- rep(0, nrow(podatki.izbrani))
      verjetnosti[napoved > pogoj] <- 1
   
    } else {
      model <- glm(
        as.formula(paste0(odvisna_spremenljivka, " ~ ", neodvisna_spremenljivka)), 
        podatki.izbrani[podatki.izbrani$Date < mnozicaDatum, ], family = binomial
      )
      napoved <- predict(model, podatki.izbrani[podatki.izbrani$Date >= mnozicaDatum, ], type = "response")
      verjetnosti <- rep(0, nrow(podatki.izbrani[podatki.izbrani$Date >= mnozicaDatum, ]))
      verjetnosti[napoved > pogoj] <- 1
      
      U.datum.min <- min(podatki.izbrani[podatki.izbrani$Date < mnozicaDatum, "Date"])
      U.datum.max <- max(podatki.izbrani[podatki.izbrani$Date < mnozicaDatum, "Date"])
      T.datum.min <- min(podatki.izbrani[podatki.izbrani$Date >= mnozicaDatum, "Date"])
      T.datum.max <- max(podatki.izbrani[podatki.izbrani$Date >= mnozicaDatum, "Date"])
    }
  } else {
    verjetnosti <- ifelse(eval(parse(text = pogojFormula)), 1, 0)
  }
  
  if (is.na(mnozicaDatum)) {
    tabelaNapacnihKlasifikacij <-
      table(
        Napoved = verjetnosti, 
        Dejansko = podatki.izbrani %>% 
          select(odvisna_spremenljivka) %>% unlist() %>% unname()
      )
  } else {
    tabelaNapacnihKlasifikacij <-
      table(
        Napoved = verjetnosti, 
        Dejansko = podatki.izbrani[podatki.izbrani$Date >= mnozicaDatum, ] %>% 
          select(odvisna_spremenljivka) %>% unlist() %>% unname()
      )    
  }

  if (dim(tabelaNapacnihKlasifikacij)[1] == 1) {
    if (row.names(tabelaNapacnihKlasifikacij) == 1) {
      FN <- tabelaNapacnihKlasifikacij[1,1]  
      TN <- tabelaNapacnihKlasifikacij[1,2]
      TP <- 0
      FP <- 0
    } else {
      FN <- 0
      TN <- 0
      TP <- tabelaNapacnihKlasifikacij[1,1]
      FP <- tabelaNapacnihKlasifikacij[1,2]  
    }
  } else {
    TP <- tabelaNapacnihKlasifikacij[1,1]
    TN <- tabelaNapacnihKlasifikacij[2,2]
    FN <- tabelaNapacnihKlasifikacij[2,1]
    FP <- tabelaNapacnihKlasifikacij[1,2]
  }

  tocnost <- (TP + TN) / (TP + TN + FN + FP)
  natancnost <- TP / (TP + FP)
  priklic <- TP / (TP + FN)
  specificnost <- TN / (TN + FP)
  NPV <- TN / (TN + FN)
  FPR <- FP / (FP + TN)
  F1 <- 2 * natancnost * priklic / (natancnost + priklic)
  
  tabelaNapacnihKlasifikacijIzpis <-
    data.frame(
      "&nbsp;" = c("ni napovedane recesije", "napovedana recesija", "$\\sum$", "", ""),
      "ni dejanske recesije" = c(
        paste0("$\\color{green}{TP} = \\boldsymbol{", TP, "}$"),
        paste0("$\\color{darkred}{FN} = \\boldsymbol{", FN, "}$"),
        paste0("$", TP + FN, "\\ (", round(100 * (TP + FN) / (TP + FN + FP + TN)), "\\ \\%)", "$"),
        paste0(
          "$\\textbf{priklic}\\ (\\text{angl. recall, sensitivity}) =$", " <br> ", 
          "$=\\ \\frac{\\color{green}{TP}}{\\color{green}{TP}\\ +\\ \\color{darkred}{FN}} = ", 
          "\\frac{", TP, "}{", TP + FN, "} \\approx ",
          "\\boldsymbol{", round(100 * priklic), "\\ \\%}$"
        ),
        ""
      ),
      "dejanska recesija" = c(
        paste0("$\\color{darkred}{FP} = \\boldsymbol{", FP, "}$"),
        paste0("$\\color{green}{TN} = \\boldsymbol{", TN, "}$"),
        paste0("$", FP + TN, "\\ (", round(100 * (FP + TN) / (TP + FN + FP + TN)), "\\ \\%)", "$"), 
        paste0(
          "$\\textbf{specifičnost}\\ (\\text{angl. specificity}) =$", " <br> ",
          "$=\\ \\frac{\\color{green}{TN}}{\\color{green}{TN}\\ +\\ \\color{darkred}{FP}} = ",
          "\\frac{", TN, "}{", TN + FP, "} \\approx ",
          "\\boldsymbol{", round(100 * specificnost), "\\ \\%}", "$"
        ),
        paste0(
          "$\\textbf{FPR}\\ (\\text{angl. false positive rate}) =$", " <br> ",
          "$=\\ \\frac{\\color{darkred}{FP}}{\\color{green}{TN}\\ +\\ \\color{darkred}{FP}} = ",
          "\\frac{", FP, "}{", TN + FP, "} \\approx ",
          "\\boldsymbol{", round(100 * FPR), "\\ \\%}", "$"
        )
      ),
      "$\\sum$" = c(
        paste0("$", TP + FP, "\\ (", round(100 * (TP + FP) / (TP + FN + FP + TN)), "\\ \\%)", "$"),
        paste0("$", FN + TN, "\\ (", round(100 * (FN + TN) / (TP + FN + FP + TN)), "\\ \\%)", "$"),
        paste0(
          "$", TP + FN + FP + TN, "\\ (", 
          round(100 * (TP + FN + FP + TN) / (TP + FN + FP + TN)), "\\ \\%)$"
        ),
        "", ""
      ),
      "&nbsp;" = c(paste0(
          "$\\textbf{natančnost}\\ (\\text{angl. precision}) =$", " <br> ", 
          "$=\\ \\frac{\\color{green}{TP}}{\\color{green}{TP}\\ +\\ \\color{darkred}{FP}} = ", 
          "\\frac{", TP, "}{", TP + FP, "} \\approx ",
          "\\boldsymbol{", round(100 * natancnost), "\\ \\%}", "$"
        ),
        paste0(
          "$\\textbf{NPV}\\ (\\text{angl. negative predictive value}) =$", " <br> ",
          "$=\\ \\frac{\\color{green}{TN}}{\\color{green}{TN}\\ +\\ \\color{darkred}{FN}} = ",
          "\\frac{", TN, "}{", TN + FN, "} \\approx ",
          "\\boldsymbol{", round(100 * NPV), "\\ \\%}", "$"
        ),
        "", 
        paste0(
          "$\\textbf{točnost}\\ (\\text{angl. accuracy}) =$", " <br> ",
          "$=\\ \\frac{\\color{green}{TP}\\ +\\ \\color{green}{TN}}", 
          "{\\color{green}{TP}\\ +\\ \\color{green}{TN}\\ +\\ ", 
          "\\color{darkred}{FP}\\ +\\ \\color{darkred}{FN}} = ",
          "\\frac{", TP + TN, "}{", TP + TN + FP + FN, "} \\approx ",
          "\\boldsymbol{", round(100 * tocnost), "\\ \\%}", "$"
        ),
        paste0(
          "$\\textbf{F1} = ",
          "\\ \\frac{2\\ \\cdot \\text{natančnost}\\ \\cdot\\ ", 
          "\\text{priklic}}{\\text{natančnost}\\ +\\ \\text{priklic}} \\approx ",
          "\\boldsymbol{", round(100 * F1), "\\ \\%}$"
        )
      ),
      check.names = FALSE
    ) %>%
    kbl(align = "c", booktabs = TRUE, escape = FALSE) %>%
    kable_styling(
      font_size = 11, 
      bootstrap_options = c("condensed", "hover"),
      full_width = FALSE
    ) %>%
    column_spec(1, bold = TRUE)
  
  rezultati = list(
    TP = TP,
    TN = TN,
    FN = FN,
    FP = FP,
    tocnost = tocnost,
    natancnost = natancnost,
    priklic = priklic,
    specificnost = specificnost,
    NPV = NPV,
    FPR = FPR,
    F1 = F1,
    tabelaNapacnihKlasifikacij = tabelaNapacnihKlasifikacij,
    tabelaNapacnihKlasifikacijIzpis = tabelaNapacnihKlasifikacijIzpis,
    U.datum.min = U.datum.min,
    U.datum.max = U.datum.max,
    T.datum.min = T.datum.min,
    T.datum.max = T.datum.max
  )
  
  rezultati
}

Napovedni modeli

Napovedna vrednost razlike v donosu obveznic (M1)

Analiza krivulje donosnosti obveznic je za vlagatelje verjetno koristna, v okviru tega prispevka pa nas zanima v kakšni meri. Če uporabimo razliko med dolgoročnimi (\(10\) letnimi) in kratkoročnimi (\(3\) mesečnimi) ameriškimi obveznostmi, ki jo klasificiramo kot napovedana recesija, če je razlika manjša od \(0\), sicer jo označimo kot ni napovedane recesije. To razliko smo na tem mestu uporabili preprosto zato, ker je to najenostavneje, prav tako pa jo uporablja tudi Federal Reserve Bank of New York (2021).

model1 <- napovedniModel(podatki, "NBER_Rec", "Spread", NA, "podatki.izbrani$Spread < 0")
Tabela 3: Tabela napačnih klasifikacij (angl. confusion matrix) razlike v donosu
  ni dejanske recesije dejanska recesija \(\sum\)  
ni napovedane recesije \(\color{green}{TP} = \boldsymbol{565}\) \(\color{darkred}{FP} = \boldsymbol{85}\) \(650\ (87\ \%)\) \(\textbf{natančnost}\ (\text{angl. precision}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FP}} = \frac{565}{650} \approx \boldsymbol{87\ \%}\)
napovedana recesija \(\color{darkred}{FN} = \boldsymbol{76}\) \(\color{green}{TN} = \boldsymbol{17}\) \(93\ (13\ \%)\) \(\textbf{NPV}\ (\text{angl. negative predictive value}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FN}} = \frac{17}{93} \approx \boldsymbol{18\ \%}\)
\(\sum\) \(641\ (86\ \%)\) \(102\ (14\ \%)\) \(743\ (100\ \%)\)
\(\textbf{priklic}\ (\text{angl. recall, sensitivity}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FN}} = \frac{565}{641} \approx \boldsymbol{88\ \%}\)
\(\textbf{specifičnost}\ (\text{angl. specificity}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{17}{102} \approx \boldsymbol{17\ \%}\)
\(\textbf{točnost}\ (\text{angl. accuracy}) =\)
\(=\ \frac{\color{green}{TP}\ +\ \color{green}{TN}}{\color{green}{TP}\ +\ \color{green}{TN}\ +\ \color{darkred}{FP}\ +\ \color{darkred}{FN}} = \frac{582}{743} \approx \boldsymbol{78\ \%}\)
\(\textbf{FPR}\ (\text{angl. false positive rate}) =\)
\(=\ \frac{\color{darkred}{FP}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{85}{102} \approx \boldsymbol{83\ \%}\)
\(\textbf{F1} = \ \frac{2\ \cdot \text{natančnost}\ \cdot\ \text{priklic}}{\text{natančnost}\ +\ \text{priklic}} \approx \boldsymbol{88\ \%}\)

V tabeli 3 so zbrane napačne klasifikacije tega enostavnega napovednega modela, kjer opazimo, da je točnost relativno visoka (okrog \(\boldsymbol{78\ \%}\)), kar predstavlja delež dogodkov, ko je identificirana inverzija v donosu obveznic in je prisotna recesija ter obratno (ni bilo inverzije v donosu obveznic in ni bilo prisotne recesije).

Opazimo pa tudi, da ima model težave s specifičnostjo, ki je s \(\boldsymbol{17\ \%}\) zelo nizka, kar predstavlja delež nenapovedanih recesij (v primeru našega modela razlik manjših od \(0\)), ko so recesije dejansko prisotne. Posledično je zato FPR oz. delež napačno razvrščenih negativnih primerov zelo visok z vrednostjo \(\boldsymbol{83\ \%}\). To bomo poskušali v nadaljevanju izboljšati.

Napovedna vrednost verjetnosti recesije (M2)

Ugotovili smo, da napovedna vrednost razlike v donosu obveznic v tej osnovni obliki ni najbolj koristna, zato bomo sedaj preverili napovedno vrednost verjetnosti recesije.

Ko razmišljamo o gradnji modela, se problema lotimo s preprostim napovedovanje ali bo gospodarstvo v recesiji ali ne, tj. binarna odločitev da oz. ne. Pri opredelitvi recesije bomo uporabili splošno opredelitev dveh zaporednih negativnih četrtletij rasti BDP.

Začeli bomo z enostavnim modelom logistične regresije, ki bo vračal vrednosti v intervalu \([0, 1]\). Pri tem bomo uporabili podatke Federal Reserve Bank of New York (2021), ki so prikazani na sliki 1. Na grafu lahko opazimo, da se razlika v donosu med dolgoročno (\(10\) letno) in kratkoročno (\(3\) mesečno) ameriško obveznico pred recesijo (označeno s sivo barvo) običajno nekoliko zmanjša. Upoštevati je tudi treba, da se razlika v donosu okrepi, ko je recesija v teku. Omenjena ugotovitev je zagotovo dovolj dober razlog, da inverzija, ki smo jo uporabili v prejšnjem poglavju, sama po sebi v takšni obliki nima najboljše napovedne vrednosti. Spomnimo se, da je bil delež vseh napovedanih recesij zgolj \(18\ \%\), kar nam pove, da se ob inverziji zgodil le manjši delež recesij.

podatki.izbrani <- podatki %>% filter(!is.na(NBER_Rec) & !is.na(Spread)) %>% select(Date, NBER_Rec, Spread)
napoved <- predict(glm(NBER_Rec ~ Spread, podatki.izbrani, family = binomial), podatki.izbrani, type = "response")
podatki.izbrani <- podatki.izbrani %>% mutate(Rec_prob = 100 * napoved)

Najprej na sliki 2 prikažimo odvisnost od verjetnosti recesije v primerjavi z dejanskimi obdobji recesij.

yMin <- min(podatki.izbrani[, "Rec_prob"], na.rm = TRUE)
yMax <- max(podatki.izbrani[, "Rec_prob"], na.rm = TRUE)

podatki.izbrani %>%
  ggplot(aes(x = Date, y = Rec_prob)) +
  geom_hline(
    yintercept = 100 * (model1[["FP"]] + model1[["TN"]]) / 
      (model1[["FP"]] + model1[["TN"]] + model1[["TP"]] + model1[["FN"]]), 
    linetype = "dotted", color = "gray", size = .3
  ) +
  geom_rect(
    data = recesije %>% mutate(Date = zacetek, Rec_prob = 0), alpha = .1, 
    mapping = aes(xmin = zacetek, xmax = konec, ymin = yMin, ymax = yMax)
  ) +
  geom_line(color = "blue") +
  geom_label_repel(
    data = recesije %>% 
      mutate(
        Date = recesije$zacetek + difftime(recesije$konec, recesije$zacetek)/2, 
        Rec_prob = yMax
      ),
    mapping = aes(label = Opis),
    force = 10,
    direction = "both",
    nudge_y = 10, 
    color = "gray", size = 4
  ) +
  ylim(c(yMin, yMax * 1.2)) +
  xlab("") + ylab("Verjetnost recesije (%)") +
  theme_classic() + 
  theme(
    axis.text = element_text(size = 12),
    axis.title = element_text(size = 12)
  )
**Verjetnost recesije** in **obdobja gospodarskih recesij**

Slika 2: Verjetnost recesije in obdobja gospodarskih recesij

Na prvi pogled rezultati niso vzpodbudni, saj lahko opazimo da so verjetnosti recesij zelo majhne. Glede na to, da je zaloga vrednosti v intervalu \([0, 1]\), moramo določiti mejno vrednost, kjer bomo dogodek opredelili za recesijo. Takoj nam je jasno, da pogosto uporabljen mejnik \(50\ \%\) v tem primeru ne bo koristen, saj bi vse dogodke klasificirali kot obdobje brez recesij. Ker vemo, da recesije zgodovinsko gledano niso ravno pogoste, lahko preprosto uporabimo to zgodovinsko povprečje recesij \(\approx \boldsymbol{14\ \%}\) (glej tabelo 3).

Tabela 4: Tabela napačnih klasifikacij (angl. confusion matrix) verjetnosti recesije pri meji \(14\ \%\)
model2 <- napovedniModel(
  podatki, "NBER_Rec", "Spread", 
  (model1[["FP"]] + model1[["TN"]]) / (model1[["FP"]] + model1[["TN"]] + model1[["TP"]] + model1[["FN"]])
)
  ni dejanske recesije dejanska recesija \(\sum\)  
ni napovedane recesije \(\color{green}{TP} = \boldsymbol{339}\) \(\color{darkred}{FP} = \boldsymbol{51}\) \(390\ (52\ \%)\) \(\textbf{natančnost}\ (\text{angl. precision}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FP}} = \frac{339}{390} \approx \boldsymbol{87\ \%}\)
napovedana recesija \(\color{darkred}{FN} = \boldsymbol{302}\) \(\color{green}{TN} = \boldsymbol{51}\) \(353\ (48\ \%)\) \(\textbf{NPV}\ (\text{angl. negative predictive value}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FN}} = \frac{51}{353} \approx \boldsymbol{14\ \%}\)
\(\sum\) \(641\ (86\ \%)\) \(102\ (14\ \%)\) \(743\ (100\ \%)\)
\(\textbf{priklic}\ (\text{angl. recall, sensitivity}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FN}} = \frac{339}{641} \approx \boldsymbol{53\ \%}\)
\(\textbf{specifičnost}\ (\text{angl. specificity}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{51}{102} \approx \boldsymbol{50\ \%}\)
\(\textbf{točnost}\ (\text{angl. accuracy}) =\)
\(=\ \frac{\color{green}{TP}\ +\ \color{green}{TN}}{\color{green}{TP}\ +\ \color{green}{TN}\ +\ \color{darkred}{FP}\ +\ \color{darkred}{FN}} = \frac{390}{743} \approx \boldsymbol{52\ \%}\)
\(\textbf{FPR}\ (\text{angl. false positive rate}) =\)
\(=\ \frac{\color{darkred}{FP}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{51}{102} \approx \boldsymbol{50\ \%}\)
\(\textbf{F1} = \ \frac{2\ \cdot \text{natančnost}\ \cdot\ \text{priklic}}{\text{natančnost}\ +\ \text{priklic}} \approx \boldsymbol{66\ \%}\)

Dobljeni rezultati trenutnega napovednega modela v tabeli 4 so sicer boljši kot pri prejšnjem poenostavljenem napovednem modelu v tabeli 3, a vseeno niso najboljši pri specifičnosti modela \(\approx \boldsymbol{50\ \%}\) in so približno enakovredni metu kovanca.

Kot smo že ugotovili predhodno, bi z višjimi mejami za verjetnost recesije dosegli zgolj višjo točnost, medtem ko bi specifičnost padla, saj bi vedno napovedali obdobje brez recesije. Nasprotno bi se zgodilo z nižanjem meje za verjetnost recesije, kjer bi sicer povečali specifičnost, a na račun točnosti, kar prikazuje tudi simulacija različnih mejnih vrednosti za klasifikacijo recesije na sliki 3.

Različne mejne vrednosti za klasifikacijo recesije pri modelu M2

Slika 3: Različne mejne vrednosti za klasifikacijo recesije pri modelu M2

Napovedna vrednost verjetnosti recesije zamaknjene za 6 mesecev (M3)

Model krivulje donosnosti obveznic bi moral napovedovati recesijo v prihodnosti in ne v sedanjosti, kot smo to implementirali v prejšnjih dveh modelih M1 in M2. Ker želimo, da naš model napoveduje prihodnost, bomo s to ugotovitvijo poskušali dopolnite naša že obstoječa modela.

Najprej bomo podatke krivulje donosnosti obveznic zakasnili za \(6\) mesecev, da bomo lahko primerjali krivuljo donosnosti obveznic s prisotnostjo recesije \(6\) mesecev v prihodnosti, kar prikazuje slika 4.

podatki_6 <- 
  podatki %>% 
  mutate(Spread = lag(Spread, 6))

Graf na sliki 4 prikazuje razliko v donosu dolgoročnih (\(10\) letnih) in kratkoročnih (\(3\) mesečnih) ameriških obveznic, zamaknjenih za \(6\) mesecev, glede na graf na sliki 1.

yMin <- min(podatki_6[, "Spread"], na.rm = TRUE)
yMax <- max(podatki_6[, "Spread"], na.rm = TRUE)

podatki_6 %>%
  filter(!is.na(Spread) & !is.na(NBER_Rec)) %>%
  ggplot(aes(x = Date, y = Spread)) +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray", size = .3) +
  geom_rect(
    data = recesije %>% mutate(Date = zacetek, Spread = 0), alpha = .1, 
    mapping = aes(xmin = zacetek, xmax = konec, ymin = yMin, ymax = yMax)
  ) +
  geom_line(color = "blue") +
  geom_label_repel(
    data = recesije %>% 
      mutate(
        Date = recesije$zacetek + difftime(recesije$konec, recesije$zacetek)/2, 
        Spread = yMax
      ),
    mapping = aes(label = Opis),
    force = 10,
    direction = "both",
    nudge_y = 1, 
    color = "gray", size = 4
  ) +
  ylim(c(yMin, yMax * 1.3)) +
  xlab("") + ylab("Razlika v donosu (%) zakasnjena za 6 mesecev") +
  theme_classic() + 
  theme(
    axis.text = element_text(size = 12),
    axis.title = element_text(size = 12)
  )
**Razlika v donosu** dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) **ameriških obveznic** in **obdobja gospodarskih recesij**, zamaknjena za $6$ mesecev

Slika 4: Razlika v donosu dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) ameriških obveznic in obdobja gospodarskih recesij, zamaknjena za \(6\) mesecev

model3 <- napovedniModel(podatki_6, "NBER_Rec", "Spread", 0.145)

Rezultati (točnost in F1) napovednega modela M3 niso veliko boljši od začetnega poenostavljenega modela M1, smo pa bistveno izboljšali specifičnost, ki sedaj znaša \(72\ \%\), kjer je rezultat iskanja najugodnejše mejne vrednosti za klasifikacije recesije prikazan na sliki 5.

Tabela 5: Tabela napačnih klasifikacij (angl. confusion matrix) verjetnosti recesije, zamaknjene za \(6\) mesecev in meji \(15\ \%\)
  ni dejanske recesije dejanska recesija \(\sum\)  
ni napovedane recesije \(\color{green}{TP} = \boldsymbol{456}\) \(\color{darkred}{FP} = \boldsymbol{29}\) \(485\ (66\ \%)\) \(\textbf{natančnost}\ (\text{angl. precision}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FP}} = \frac{456}{485} \approx \boldsymbol{94\ \%}\)
napovedana recesija \(\color{darkred}{FN} = \boldsymbol{179}\) \(\color{green}{TN} = \boldsymbol{73}\) \(252\ (34\ \%)\) \(\textbf{NPV}\ (\text{angl. negative predictive value}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FN}} = \frac{73}{252} \approx \boldsymbol{29\ \%}\)
\(\sum\) \(635\ (86\ \%)\) \(102\ (14\ \%)\) \(737\ (100\ \%)\)
\(\textbf{priklic}\ (\text{angl. recall, sensitivity}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FN}} = \frac{456}{635} \approx \boldsymbol{72\ \%}\)
\(\textbf{specifičnost}\ (\text{angl. specificity}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{73}{102} \approx \boldsymbol{72\ \%}\)
\(\textbf{točnost}\ (\text{angl. accuracy}) =\)
\(=\ \frac{\color{green}{TP}\ +\ \color{green}{TN}}{\color{green}{TP}\ +\ \color{green}{TN}\ +\ \color{darkred}{FP}\ +\ \color{darkred}{FN}} = \frac{529}{737} \approx \boldsymbol{72\ \%}\)
\(\textbf{FPR}\ (\text{angl. false positive rate}) =\)
\(=\ \frac{\color{darkred}{FP}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{29}{102} \approx \boldsymbol{28\ \%}\)
\(\textbf{F1} = \ \frac{2\ \cdot \text{natančnost}\ \cdot\ \text{priklic}}{\text{natančnost}\ +\ \text{priklic}} \approx \boldsymbol{81\ \%}\)
Različne mejne vrednosti za klasifikacijo recesije pri modelu M3

Slika 5: Različne mejne vrednosti za klasifikacijo recesije pri modelu M3

Napovedna vrednost verjetnosti recesije zamaknjene za 12 mesecev (M4)

Preverimo še učinkovitost modela, kjer podatke krivulje donosnosti obveznic zakasnimo za \(12\) mesecev, kar prikazuje slika 6.

podatki_12 <- 
  podatki %>% 
  mutate(Spread = lag(Spread, 12))
yMin <- min(podatki_12[, "Spread"], na.rm = TRUE)
yMax <- max(podatki_12[, "Spread"], na.rm = TRUE)

podatki_12 %>%
  filter(!is.na(Spread) & !is.na(NBER_Rec)) %>%
  ggplot(aes(x = Date, y = Spread)) +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray", size = .3) +
  geom_rect(
    data = recesije %>% mutate(Date = zacetek, Spread = 0), alpha = .1, 
    mapping = aes(xmin = zacetek, xmax = konec, ymin = yMin, ymax = yMax)
  ) +
  geom_line(color = "blue") +
  geom_label_repel(
    data = recesije %>% 
      mutate(
        Date = recesije$zacetek + difftime(recesije$konec, recesije$zacetek)/2, 
        Spread = yMax
      ),
    mapping = aes(label = Opis),
    force = 10,
    direction = "both",
    nudge_y = 1, 
    color = "gray", size = 4
  ) +
  ylim(c(yMin, yMax * 1.3)) +
  xlab("") + ylab("Razlika v donosu (%) zakasnjena za 12 mesecev") +
  theme_classic() + 
  theme(
    axis.text = element_text(size = 12),
    axis.title = element_text(size = 12)
  )
**Razlika v donosu** dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) **ameriških obveznic** in **obdobja gospodarskih recesij**, zamaknjene za $12$ mesecev

Slika 6: Razlika v donosu dolgoročnih (10 letnih) in kratkoročnih (3 mesečnih) ameriških obveznic in obdobja gospodarskih recesij, zamaknjene za \(12\) mesecev

model4 <- napovedniModel(podatki %>% mutate(Spread = lag(Spread, 12)), "NBER_Rec", "Spread", 0.18)

Rezultati napovednega modela M4 so se v primerjavi s prejšnjim modelom M3 še dodatno izboljšali z vidika vseh treh osrednjih metrik (točnost, specifičnost in F1).

Tabela 6: Tabela napačnih klasifikacij (angl. confusion matrix) razlike v donosu, zakasnjene za \(12\) mesecev in meji \(18\ \%\)
  ni dejanske recesije dejanska recesija \(\sum\)  
ni napovedane recesije \(\color{green}{TP} = \boldsymbol{510}\) \(\color{darkred}{FP} = \boldsymbol{19}\) \(529\ (72\ \%)\) \(\textbf{natančnost}\ (\text{angl. precision}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FP}} = \frac{510}{529} \approx \boldsymbol{96\ \%}\)
napovedana recesija \(\color{darkred}{FN} = \boldsymbol{119}\) \(\color{green}{TN} = \boldsymbol{83}\) \(202\ (28\ \%)\) \(\textbf{NPV}\ (\text{angl. negative predictive value}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FN}} = \frac{83}{202} \approx \boldsymbol{41\ \%}\)
\(\sum\) \(629\ (86\ \%)\) \(102\ (14\ \%)\) \(731\ (100\ \%)\)
\(\textbf{priklic}\ (\text{angl. recall, sensitivity}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FN}} = \frac{510}{629} \approx \boldsymbol{81\ \%}\)
\(\textbf{specifičnost}\ (\text{angl. specificity}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{83}{102} \approx \boldsymbol{81\ \%}\)
\(\textbf{točnost}\ (\text{angl. accuracy}) =\)
\(=\ \frac{\color{green}{TP}\ +\ \color{green}{TN}}{\color{green}{TP}\ +\ \color{green}{TN}\ +\ \color{darkred}{FP}\ +\ \color{darkred}{FN}} = \frac{593}{731} \approx \boldsymbol{81\ \%}\)
\(\textbf{FPR}\ (\text{angl. false positive rate}) =\)
\(=\ \frac{\color{darkred}{FP}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{19}{102} \approx \boldsymbol{19\ \%}\)
\(\textbf{F1} = \ \frac{2\ \cdot \text{natančnost}\ \cdot\ \text{priklic}}{\text{natančnost}\ +\ \text{priklic}} \approx \boldsymbol{88\ \%}\)
Mejne vrednosti za klasifikacijo recesije

Slika 7: Mejne vrednosti za klasifikacijo recesije

Napoved verjetnosti recesij na testni množici (M4-T)

S postopno izboljšavo modelov smo ugotovili, da je najbolj učinkovit model, kjer pri napovedovanju upoštevamo \(12\) mesečni zamik. Glavna težava obstoječih modelov je, da smo jih zgradili z uporabo vseh razpoložljivih podatkih. Tako ne vemo ali bo takšen model deloval tudi na novih podatkih. Če želimo preveriti učinkovitost modela izven vzorca podatkov, na katerih smo ga naučili, lahko vse razpoložljive podatke razdelimo na učno in testno množico. Na učni množici zgradimo model, na testni pa preverimo njegovo učinkovitost.

Najprej se moramo odločiti, kako bomo razdelili podatke. Glede na to, da imamo omejeno število recesij, bomo učinkovitost našega modela preverili na zadnjih treh recesijah, zato bo točka delitve leto \(1999\).

yMin <- min(podatki_12[, "Spread"], na.rm = TRUE)
yMax <- max(podatki_12[, "Spread"], na.rm = TRUE)

podatki_12 %>%
  filter(!is.na(Spread) & !is.na(NBER_Rec)) %>%
  ggplot(aes(x = Date, y = Spread)) +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray", size = .3) +
  geom_vline(xintercept = as.Date("1999-01-01"), linetype = "dotted", color = "red") +
  geom_rect(
    data = recesije %>% mutate(Date = zacetek, Spread = 0), alpha = .1, 
    mapping = aes(xmin = zacetek, xmax = konec, ymin = yMin, ymax = yMax)
  ) +
  geom_line(color = "blue") +
  geom_label(x = as.Date("1965-06-01"), y = -2, label = "Učna množica", color = "red") +
  geom_label(x = as.Date("2015-01-01"), y = -2, label = "Testna množica", color = "red") +
  geom_label_repel(
    data = recesije %>% 
      mutate(
        Date = recesije$zacetek + difftime(recesije$konec, recesije$zacetek)/2, 
        Spread = yMax
      ),
    mapping = aes(label = Opis),
    force = 10,
    direction = "both",
    nudge_y = 1, 
    color = "gray", size = 4
  ) +
  ylim(c(yMin, yMax * 1.3)) +
  xlab("") + ylab("Razlika v donosu (%) zakasnjena za 12 mesecev") +
  theme_classic() + 
  theme(
    axis.text = element_text(size = 12),
    axis.title = element_text(size = 12)
  )
Delitev podatkov na učno in testno množico z mejno vrednostjo leta $1999$

Slika 8: Delitev podatkov na učno in testno množico z mejno vrednostjo leta \(1999\)

model4t <- napovedniModel(podatki_12, "NBER_Rec", "Spread", 0.18, NA, "1999-01-01")

Rezultati napovednega modela M4 so se v primerjavi s prejšnjim modelom M3 še dodatno izboljšali z vidika vseh treh osrednjih metrik (točnost, specifičnost in F1).

Rezultati napovednega modela M4-T (ki je enak kot prejšnji model M4, zgolj apliciran na drugo množico podatkov) se z vidika točnosti in F1 celo izboljšajo, zmanjša pa se specifičnost.

Tabela 7: Tabela napačnih klasifikacij (angl. confusion matrix) razlike v donosu, zakasnjene za \(12\) mesecev in meji \(18\ \%\) in testni množici od vključno leta \(1999\) naprej
  ni dejanske recesije dejanska recesija \(\sum\)  
ni napovedane recesije \(\color{green}{TP} = \boldsymbol{201}\) \(\color{darkred}{FP} = \boldsymbol{11}\) \(212\ (81\ \%)\) \(\textbf{natančnost}\ (\text{angl. precision}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FP}} = \frac{201}{212} \approx \boldsymbol{95\ \%}\)
napovedana recesija \(\color{darkred}{FN} = \boldsymbol{27}\) \(\color{green}{TN} = \boldsymbol{24}\) \(51\ (19\ \%)\) \(\textbf{NPV}\ (\text{angl. negative predictive value}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FN}} = \frac{24}{51} \approx \boldsymbol{47\ \%}\)
\(\sum\) \(228\ (87\ \%)\) \(35\ (13\ \%)\) \(263\ (100\ \%)\)
\(\textbf{priklic}\ (\text{angl. recall, sensitivity}) =\)
\(=\ \frac{\color{green}{TP}}{\color{green}{TP}\ +\ \color{darkred}{FN}} = \frac{201}{228} \approx \boldsymbol{88\ \%}\)
\(\textbf{specifičnost}\ (\text{angl. specificity}) =\)
\(=\ \frac{\color{green}{TN}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{24}{35} \approx \boldsymbol{69\ \%}\)
\(\textbf{točnost}\ (\text{angl. accuracy}) =\)
\(=\ \frac{\color{green}{TP}\ +\ \color{green}{TN}}{\color{green}{TP}\ +\ \color{green}{TN}\ +\ \color{darkred}{FP}\ +\ \color{darkred}{FN}} = \frac{225}{263} \approx \boldsymbol{86\ \%}\)
\(\textbf{FPR}\ (\text{angl. false positive rate}) =\)
\(=\ \frac{\color{darkred}{FP}}{\color{green}{TN}\ +\ \color{darkred}{FP}} = \frac{11}{35} \approx \boldsymbol{31\ \%}\)
\(\textbf{F1} = \ \frac{2\ \cdot \text{natančnost}\ \cdot\ \text{priklic}}{\text{natančnost}\ +\ \text{priklic}} \approx \boldsymbol{91\ \%}\)

Zaključek

V tabeli 8 je prikazan povzetek rezultatov vseh napovednih modelov, ki smo jih postopoma zgradila v prispevku na podlagi podatkov Federal Reserve Bank of New York (2021).

Tabela 8: Povzetek rezultatov vseh napovednih modelov razlik donosnosti obveznic
Model Opis Učna množica Testna množica Točnost Specifičnost F1
M1 Razlika v donosu obveznic. \(61.9\) let v obdobju
od 1959-01-31 do 2020-11-30.
\(61.9\) let v obdobju
od 1959-01-31 do 2020-11-30.
\(\color{black}{78\ \%}\) \(\color{darkred}{\boldsymbol{17\ \%}}\) \(\color{black}{88\ \%}\)
M2 Logistična regresija razlike v donosu obveznic
pri meji napovednega razreda \(14\ \%\).
\(61.9\) let v obdobju
od 1959-01-31 do 2020-11-30.
\(61.9\) let v obdobju
od 1959-01-31 do 2020-11-30.
\(\color{darkred}{\boldsymbol{52\ \%}}\) \(\color{black}{50\ \%}\) \(\color{darkred}{\boldsymbol{66\ \%}}\)
M3 Logistična regresija razlike v donosu obveznic,
zamaknjene za \(6\) mesecev,
pri meji napovedenega razreda \(15\ \%\).
\(61.4\) let v obdobju
od 1959-07-31 do 2020-11-30.
\(61.4\) let v obdobju
od 1959-07-31 do 2020-11-30.
\(\color{black}{72\ \%}\) \(\color{black}{72\ \%}\) \(\color{black}{81\ \%}\)
M4 Logistična regresija razlike v donosu obveznic,
zamaknjene za \(12\) mesecev,
pri meji napovednega razreda \(18\ \%\).
\(60.9\) let v obdobju
od 1960-01-31 do 2020-11-30.
\(60.9\) let v obdobju
od 1960-01-31 do 2020-11-30.
\(\color{black}{81\ \%}\) \(\color{green}{\boldsymbol{81\ \%}}\) \(\color{black}{88\ \%}\)
M4-T Logistična regresija razlike v donosu obveznic,
zamaknjene za \(12\) mesecev,
pri meji napovednega razreda \(18\ \%\).
\(38.9\) let v obdobju
od 1960-01-31 do 1998-12-31.
\(21.8\) let v obdobju
od 1999-01-31 do 2020-11-30.
\(\color{green}{\boldsymbol{86\ \%}}\) \(\color{black}{69\ \%}\) \(\color{green}{\boldsymbol{91\ \%}}\)

Ugotovimo lahko, da ima razlika v donosu obveznic določeno napovedno vrednost pri identifikaciji prihodnjih recesij, kjer se še najbolje izkaže napovedovanje recesije za \(12\) mesecev vnaprej. Treba pa je izpostaviti, da je podatkov o recesijah v celotni zgodovini malo (v našem vzorcu od 1959-01-31 naprej jih je na mesečni ravni zgolj \(14\ \%\)). Z vidika ocene F1 in točnosti je naš model zadovoljiv, zaskrbljujoča pa je specifičnost, ki je pri zadnjem modelu M4-T šele \(69\ \%\). To pomeni, da naš model napačno klasificira skoraj \(\frac{1}{3}\) recesij.

Literatura

Federal Reserve Bank of New York. 2021. “The Yield Curve as a Leading Indicator.” 2021. https://www.newyorkfed.org/research/capital_markets/ycfaq.html.