*! nbercycles 1.0.7 30jan2024 CFBaum * 1.0.1 revise syntax for max=1, minval/maxval * 1.0.2 require from and to if varname not provided * 1.0.3 error trap above should ref varlist * 1.0.4 add current recession, logic to handle * 1.0.5 add end of 2007-2009 recession * 1.0.6 add start of pandemic recession; set end to current month/quarter while recession is underway * 1.0.7 terminate pamdemic recession in April 2020 program define nbercycles, rclass version 9.2 syntax [varlist(max=1 default=none)] [if], FILE(string) [FROM(string) TO(string) MINval(real 0) MAXval(real 1) GROPT(string asis) REPLACE ] marksample touse local tsl 0 * get the current tsset settings and check for M, Q qui tsset local tv `r(timevar)' local tu `r(unit1)' local tsf `r(tsfmt)' tempvar junk1 junk2 range tempname nber tminn tmaxx hh if "`tu'" != "q" & "`tu'" != "m" { di as err "Error: nbercycles only defined for monthly, quarterly frequencies." error 198 } * if varname not provided, from and to must be supplied if "`varlist'" == "" & "`from'" == "" & "`to'" == "" { di as err "Error: without a varname, from() and to() must be provided." error 198 } * if from and to not provided, use current tsset limits (should honor [if]) if "`from'" == "" & "`to'" == "" { local from `r(tmins)' local to `r(tmaxs)' local tmin `r(tmin)' local tmax `r(tmax)' local u2min `tu' } else { * validate the from and to entries if given qui tsmktim `junk1', start(`from') scalar `tminn' = `r(tmin)' local u1min `r(unit1)' qui tsmktim `junk2', start(`to') scalar `tmaxx' = `r(tmin)' local u2min `r(unit1)' if "`u1min'" != "`u2min'" { di as err "Error: both from() and to() must refer to same frequency." * restore orginal tsset qui tsset `tv' error 198 } } * check the variable if provided, and get its limits if "`varlist'" != "" { summ `varlist' if `touse', meanonly local minval = 0.99 * `r(min)' local maxval = 1.01 * `r(max)' * local minval = floor(`r(min)') * local maxval = ceil(`r(max)') summ `tv' if `touse', meanonly scalar `tminn' = `r(min)' scalar `tmaxx' = `r(max)' local tsl 1 } * generate the selected range of peaks and troughs // add recession for feb-apr 2020 // DISABLE assuming it is still ongoing, get current month, quarter using 9.2 syntax for date() // loc cdt "`c(current_date)'" // loc qqqq = qofd(date("`cdt'", "dmy")) // loc mmmm = mofd(date("`cdt'", "dmy")) if "`u2min'" == "m" { mat nber = ( -1231,-1213 \ -1191,-1183 \ -1137,-1105 \ -1087,-1069 \ -1035,-970 \ -934,-896 \ -874,-861 \ -834,-824 \ -804,-787 \ -769,-751 \ -727,-709 \ -688,-665 \ -632,-619 \ -600,-576 \ -564,-541 \ -497,-490 \ -480,-462 \ -440,-426 \ -399,-386 \ -366,-322 \ -272,-259 \ -179,-171 \ -134,-123 \ -78,-68 \ -29,-21 \ 3,13 \ 119,130 \ 166,182 \ 240,246 \ 258,274 \ 366,374 \ 494,502 \ 575,593 \ 721,723) } else { mat nber = ( -411,-405 \ -397,-395 \ -379,-369 \ -363,-357 \ -345,-324 \ -312,-299 \ -292,-287 \ -278,-275 \ -268,-263 \ -257,-251 \ -243,-237 \ -230,-222 \ -211,-207 \ -200,-192 \ -188,-181 \ -166,-164 \ -160,-154 \ -147,-142 \ -133,-129 \ -122,-108 \ -91,-87 \ -60,-57 \ -45,-41 \ -26,-23 \ -10,-7 \ 1,4 \ 39,43 \ 55,60 \ 80,82 \ 86,91 \ 122,124 \ 164,167 \ 191,197 \ 240,241) } svmat long nber, names(`nber') // l `nber'1 `nber'2 if `nber'1 < . // di as err "`from' `to'" qui { // replace `nber'1 = . if `nber'1 < `tminn' | `nber'1 > `tmaxx' // replace `nber'2 = . if `nber'2 < `tminn' | `nber'2 > `tmaxx' // 1.0.4: pick up boundaries replace `nber'1 = . if `nber'1 > `tmaxx' replace `nber'2 = . if `nber'2 < `tminn' gen byte `range' = (`nber'1 < . & `nber'2 < .) * _n replace `range' = . if `range' == 0 } sum `range', meanonly if `r(N)' == 0 { di as err "Error: no recessions during `from' - `to'" * restore orginal tsset qui tsset `tv' error 198 } local fcycle `r(min)' local lcycle `r(max)' local ncycle = `lcycle'-`fcycle'+1 local nc1 = `ncycle'+1 file open `hh' using `file', write `replace' file write `hh' "* append your graph command to this file: e.g." _n file write `hh' "* tsline timeseriesvar, xlabel(,format(`tsf')) `gropt' legend(order(`nc1' 1 " _char(34) "Recession" _char(34) "))" _n file write `hh' "twoway " forv i=`fcycle'/`lcycle' { local fv = `nber'1 in `i' local lv = `nber'2 in `i' file write `hh' "function y=`maxval',range(`fv' `lv') recast(area) color(gs12) base(`minval') || /// " _n } * if `varlist' provided, write that command and do the graph if "`varlist'" != "" { // di as err "`gropt'" file write `hh' "tsline `varlist' `if', xlabel(,format(`tsf')) `gropt' legend(order(`nc1' 1 " _char(34) "Recession" _char(34) "))" _n * file write `hh' xscale(range(" (`tminn') " " (`tmaxx') "))" _n } file close `hh' * restore orginal tsset qui tsset `tv' // di _n "Code to graph NBER recession dates for `from' - `to' written to `file'" _n di _n "Code to graph NBER recession dates written to `file'" _n if `tsl' { do `file' } end