program define nlsm version 3.0 /* sorig contains original compound smoother s contains compound smoother with ",twice" removed twice is "twice" if ",twice" was removed */ local sorig = upper("`1'") local s "`sorig'" if "`s'"=="" { exit 198 } local l=index("`s'",",TWICE") if `l' { if (substr("`s'",`l',.)!=",TWICE") { exit 198 } local s=substr("`s'",1,`l'-1) local sorig=substr("`s'",1,`l'-1)+",twice" local twice "twice" } /* parse request */ mac shift local varlist "req ex max(1)" local options "Generate(str) DRYRUN noShift" parse "`*'" /* if not dryrun, finish parse, perform dryun */ if "`dryrun'"=="" { if "`generat'"=="" { di in red "generate(newvar) required" exit 198 } confirm new var `generat' capture assert `varlist'!=. nlsm "`s'" `varlist', dryrun `shift' /* note, no twice */ } else { if _rc { di in red "`varlist' contains missing values" exit 498 } local x "*" } /* Note, lines marked `x' are executed only if not dryrun */ `x' tempvar base res `x' local type : type `varlist' `x' if "`type'"!="double" { local type "float" } `x' qui gen `type' `res' = `varlist' if "`twice'"!="" { /* not dryrun by definition */ tempvar res1 rough res2 nlsm `s' `res', gen(`res1') noshift qui gen `type' `rough'=`varlist'-`res1' qui nlsm `s' `rough', gen(`res2') noshift qui replace `res'=`res1'+`res2' local evens=2*$S_1 /* retrieve shift information */ } else { local evens 0 local Snext 0 while "`s'"!="" { `x' capture drop `base' `x' rename `res' `base' local Sokay `Snext' local Snext 0 local s1=substr("`s'",1,1) if (`Sokay' & "`s1'"=="S") { if (substr("`s'",1,2)=="SR") { `x' nlsm_rpt nlsm_s `base' `res' local s=substr("`s'",3,.) } else { `x' nlsm_s `base' `res' local s=substr("`s'",2,.) } local Snext 1 } else if real("`s1'")!=. { if `s1'==0 { exit 198 } if `s1'==3 { local Snext 1 } local evens = `evens' + /* */ cond(int(`s1'/2)*2==`s1',1,0) if substr("`s'",2,1)=="R" { `x' nlsm_rpt "nlsm_m `s1'" `base' `res' local s=substr("`s'",3,.) } else { `x' nlsm_m `s1' `base' `res' local s=substr("`s'",2,.) } } else if "`s1'"=="H" { `x' nlsm_h `base' `res' local s=substr("`s'",2,.) } else if "`s1'"=="E" { `x' nlsm_e `base' `res' local s=substr("`s'",2,.) } else { di in red "`s1' not allowed in `sorig'" exit 198 } } /* while */ } /* else */ /* closeout code -- check whether we shift */ mac def S_1 = `evens'/2 if ("`shift'"=="") { if "`dryrun'"!="" { if int($S_1)*2!=`evens' { di in bl "(note: result at t+1/2)" } } else { local shift = int($S_1) if `shift' { tempvar h qui gen double `h' = `res' qui replace `res' = `h'[_n-`shift'] } } } `x' label var `res' "`sorig' `varlist'" `x' rename `res' `generat' end exit nlsm non-linear smoothers. nlsm varname, gen(varname) where a is a sequence of smoothers, and the smoothers are: # running median #R running median, repeated S split followed by 3R, allowed only after 3 or 3R, or S. SS implied by above SR repeated S H Hanning Subroutines: nlsm_m # running-median smoother nlsm_ep E end-point adjustments nlsm_s S split followed by 3R, must only be called after 3 or 3R. nlsm_3r 3R running-median smoother nlsm_rpt R repeat operator (but not 3R because no end-point adj made) nlsm_h H hanning smoother Syntax: nlsm_m # varname, gen(newvar) nlsm_ep varname nlsm_s varname, gen(newvar) nlsm_3r varname, gen(newvar) nlsm_rpt "cmd_less_gen" nlsm_m running-median smoother (corresponds to #) nlsm_ep end-point adjustments (E)