Nazaj finance R
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.
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"))
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"
))
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)
)
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(
" " = 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)), "\\ \\%)$"
),
"", ""
),
" " = 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
}
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")
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.
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)
)
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).
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.
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)
)
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.
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\ \%}\) |
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)
)
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).
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\ \%}\) |
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)
)
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.
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\ \%}\) |
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).
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.
Federal Reserve Bank of New York. 2021. “The Yield Curve as a Leading Indicator.” 2021. https://www.newyorkfed.org/research/capital_markets/ycfaq.html.