d <- as.Date(fomc$date) + 1 # the day after each statement
ok <- fomc$agree %in% TRUE # %in% TRUE: NA counts as not TRUE
bad <- fomc$agree %in% FALSE
par(mar = c(2.5, 4.5, 0.5, 0.5)) # margins in lines: bottom, left, top, right
plot(as.Date(fred$date), fred$upper, type = "s", col = "grey60", ylim = c(0, 6),
xlab = "", ylab = "Target, percent", las = 1) # "s": steps, flat between decisions
lines(as.Date(fred$date), fred$lower, type = "s", col = "grey60")
points(d[ok], fomc$upper[ok], pch = 16, cex = 0.7)
points(d[bad], fomc$lower[bad], pch = 4, cex = 1.4, lwd = 2, col = "firebrick")
segments(d[bad], fomc$fred_lower[bad], d[bad], fomc$lower[bad], col = "firebrick", lwd = 2)
rug(d[is.na(fomc$agree)], col = "darkorange", lwd = 2, ticksize = 0.04) # a tick for each NA
label_x <- as.Date(c("2010-07-01", "2013-06-01", "2015-08-01", "2021-03-01", "2018-10-01", "2025-10-01"))
label_y <- c(0.8, 1.05, 1.65, 1.0, 0.55, 1.0) # labels placed by hand at (date, percent)
text(label_x, label_y, cex = 0.9,
c("\"will maintain\"", "2014: the match\nruns too far", "\"reaffirmed\"",
"look-alike\nhyphen", "look-alike\nhyphen", "look-alike\nhyphen"),
col = c("darkorange", "firebrick", "darkorange", "firebrick", "darkorange", "darkorange"))
legend("top", ncol = 2, bty = "n", cex = 0.85,
legend = c("FRED: lower and upper", paste0("equal (", sum(ok), ")"),
paste0("wrong (", sum(bad), "): lower = upper"),
paste0("NA (", sum(is.na(fomc$agree)), ")")),
col = c("grey60", "black", "firebrick", "darkorange"),
lty = c(1, NA, 1, 1), lwd = c(1, NA, 2, 2), pch = c(NA, 16, 4, NA))