version 11.2 cap program drop _eventivstatic program define _eventivstatic, rclass #d; syntax varlist(fv ts numeric) [aw fw pw] [if] [in], /* Covariates go in varlist. Can add fv ts later */ Panelvar(varname) /* Panel variable */ Timevar(varname) /* Time variable */ POLicyvar(varname) /* Policy variable */ proxy (varlist numeric) /* Proxy variable(s) */ [ proxyiv(string) /* Instruments. Either numlist with lags or varlist with names of instrumental variables */ nofe /* No fixed effects */ note /* No time effects */ reghdfe /* Use reghdfe for estimation */ addabsorb(string) /* Absorb additional variables in reghdfe */ impute(string) REPeatedcs /*data is repeated cross-sectional*/ STatic * ] ; #d cr marksample touse tempvar kg tousegen * kg grouped event time, grouping outside window * For eventgenvars, ignore missings in varlist mark `tousegen' `if' `in' tempname delta Vdelta bb VV bb2 VV2 delta2 Vdelta2 deltay Vdeltay deltax Vdeltax deltaxsc bby bbx VVy VVx * bb delta coefficients * VV variance of delta coefficients * bb2 delta coefficients for overlay plot * VV2 variance of delta coefficients for overlay plot * delta2 included cefficientes in overlaty plot * VVdelta2 variance of included delta coefficients in overlay plot loc i = "`panelvar'" loc t = "`timevar'" loc z = "`policyvar'" *call _eventgenvars to impute z if "`impute'"!="" { *tempvar to be imputed tempvar rr qui gen double `rr'=. _eventgenvars if `tousegen', panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') impute(`impute') `repeatedcs' `static' rr(`rr') loc impute=r(impute) if "`impute'"=="." loc impute = "" loc saveimp=r(saveimp) if "`saveimp'"=="." loc saveimp = "" *if imputation succeeded: if "`impute'"!="" { if "`saveimp'"=="" { cap confirm variable `policyvar'_imputed if !_rc { di as err _n "`policyvar'_imputed already exists. Please rename it or delete it before proceeding." exit 110 } gen `policyvar'_imputed = `rr' } loc z = "`policyvar'_imputed" else } else loc z = "`policyvar'" } *In the static setting, we cannot define an interval through the -window- option to look for the strongest lead. Therefore, we will check the dataset and look for the greatest possible lead. The maximum number of forwards I can generate equals the number of observed periods -1. qui sum `timevar' loc drange_1=r(max) - r(min) // this equals number of obs periods -1 * if dataset is repeated cross-sectional, create leads of policyvar at state level if "`repeatedcs'"!=""{ qui { preserve tempfile state_level_leads keep if `touse' keep `panelvar' `timevar' (`z') bysort `panelvar' `timevar' (`z'): keep if _n==1 xtset `panelvar' `timevar' forv v=1(1)`drange_1'{ tempvar _fd`v'`z' qui gen double `_fd`v'`z'' = f`v'.d.`z' } save `state_level_leads' restore *merge on the policyvar as well, so missing values in policyvar within a cell will not get lead values merge m:1 `panelvar' `timevar' `z' using `state_level_leads', update nogen } } loc leads : word count `proxy' if "`proxyiv'"=="" & `leads'==1 loc proxyiv "select" * If proxy specified but no proxyiv, assume numlist for leads of policyvar if "`proxyiv'"=="" { di _n "No proxy instruments specified. Using leads of policy variables as instruments." loc leads : word count `proxy' forv j=1(1)`leads' { loc proxyiv "`proxyiv' `j'" } } * IV selection if proxyiv = selection else if "`proxyiv'"=="select" { * Only for one proxy case if `leads'>1 { di as err "Proxy instrument selection only available for the one proxy - one instrument case" exit 301 } else { di as text _n "proxyiv=select. Selecting lead order of differenced policy variable to use as instrument." loc Fstart = 0 * originally: Here I test up to 5 forv v=1(1)`drange_1'{ if "`repeatedcs'"=="" { tempvar _fd`v'`z' qui gen double `_fd`v'`z'' = f`v'.d.`z' if `touse' } cap qui reg `proxy' `_fd`v'`z'' [`weight'`exp'] if `touse' if !_rc loc Floop = e(F) if `Floop' > `Fstart' { loc Fstart = `Floop' loc proxyiv "`v'" } } di as text _n "Lead `proxyiv' selected." } } * Parse proxyiv and generate leads if neccesary loc rc=0 foreach v in `proxyiv' { cap confirm integer number `v' loc rc = `rc' + _rc } * If numlist take as leads of z if `rc' == 0 { loc insvars "" foreach v in `proxyiv' { if "`repeatedcs'"!=""{ qui gen double _fd`v'`z' = `_fd`v'`z'' if `touse' } else{ qui gen double _fd`v'`z' = f`v'.d.`z' if `touse' } *qui gen double _f`v'`z' = f`v'.`z' if `touse' *loc insvars "`insvars' _f`v'`z'" loc insvars "`insvars' _fd`v'`z'" } loc instype = "numlist" } else { foreach v in `proxyiv' { confirm numeric variable `v' } loc insvars = "`proxyiv'" } if "`te'" == "note" loc tte "" else loc tte "i.`t'" * Main regression if "`reghdfe'"=="" { if "`fe'" == "nofe" { loc cmd "ivregress 2sls" loc ffe "" } else { loc cmd "xtivreg" loc ffe "fe" if "`repeatedcs'"!="" qui xtset `panelvar' //xtivreg requires panelvar to be setted } `cmd' `varlist' (`proxy' = `insvars') `z' `tte' [`weight'`exp'] if `touse' , `ffe' `options' } else { loc noabsorb "" *absorb nothing if "`fe'" == "nofe" & "`tte'"=="" & "`addabsorb'"=="" { *loc noabsorb "noabsorb" /*the only option ivreghdfe inherits from reghdfe is absorb, therefore it doesn't support noabsorb. In contrast with reghdfe, ivreghdfe doesn't require noabsorb when absorb is not specified*/ loc abs "" } *absorb only one else if "`fe'" == "nofe" & "`tte'"=="" & "`addabsorb'"!="" { loc abs "absorb(`addabsorb')" } else if "`fe'" == "nofe" & "`tte'"!="" & "`addabsorb'"=="" { loc abs "absorb(`t')" } else if "`fe'" != "nofe" & "`tte'"=="" & "`addabsorb'"=="" { loc abs "absorb(`i')" } *absorb two else if "`fe'" == "nofe" & "`tte'"!="" & "`addabsorb'"!="" { loc abs "absorb(`t' `addabsorb')" } else if "`fe'" != "nofe" & "`tte'"=="" & "`addabsorb'"!="" { loc abs "absorb(`i' `addabsorb')" } else if "`fe'" != "nofe" & "`tte'"!="" & "`addabsorb'"=="" { loc abs "absorb(`i' `t')" } *absorb three else if "`fe'" != "nofe" & "`tte'"!="" & "`addabsorb'"!="" { loc abs "absorb(`i' `t' `addabsorb')" } * else { loc abs "absorb(`i' `t' `addabsorb')" } *analyze inclusion of vce in options loc vce_y= strmatch("`options'","*vce(*)*") *if user did not specify vce option if "`vce_y'"=="0" { ivreghdfe `varlist' (`proxy' = `insvars') `z' [`weight'`exp'] if `touse', `abs' `noabsorb' `options' } *if user did specify vce option else { *find start and end of vce text loc vces=strpos("`options'","vce(") loc vcef=0 loc ocopy="`options'" while `vcef'<`vces' { loc vcef=strpos("`ocopy'", ")") loc ocopy=subinstr("`ocopy'",")", " ",1) } *substrac vce words loc svce_or=substr("`options'",`vces',`vcef') loc vce_len=strlen("`svce_or'") loc svce=substr("`svce_or'",5,`vce_len'-5) loc svce=strltrim("`svce'") loc svce=strrtrim("`svce'") *inspect whether vce contains bootstrap or jackknife loc vce_bt= strmatch("`svce'","*boot*") loc vce_jk= strmatch("`svce'","*jack*") if `vce_bt'==1 | `vce_jk'==1 { di as err "Options {bf:bootstrap} and {bf:jackknife} are not allowed" exit 301 } *if vce contains valid options, parse those options *erase vce from original options loc options_wcve=subinstr("`options'","`svce_or'"," ",1) *** parse vce(*) **** loc vce_wc=wordcount("`svce'") tokenize `svce' *extract vce arguments *robust loc vce_r= strmatch("`svce'","*robust*") loc vce_r2=0 forv i=1/`vce_wc'{ loc zz= strmatch("``i''","r") loc vce_r2=`vce_r2'+`zz' } if `vce_r'==1 | `vce_r2'==1 { loc vceop_r="robust" } *cluster loc vce_c= strmatch("`svce'","*cluster*") loc vce_c2= strmatch("`svce'","*cl*") if `vce_c'==1 | `vce_c2'==1 { forv i=1/`vce_wc'{ loc vce_r2= strmatch("``i''","*cl*") if `vce_r2'==1 { loc j=`i'+1 } } loc vceop_c="cluster(``j'')" } ivreghdfe `varlist' (`proxy' = `insvars') `z' [`weight'`exp'] if `touse', `abs' `noabsorb' `options_wcve' `vceop_r' `vceop_c' } } *clear xtset if repeatedcs and xtivreg, otherwise error message because timevar not setted if ("`repeatedcs'"!="" & "`cmd'"=="xtivreg") qui xtset, clear mat `bb' = e(b) mat `VV' = e(V) mat `delta'=e(b) mat `Vdelta'=e(V) * Drop variables if "`instype'"=="numlist" { foreach v in `proxyiv' { *drop _f`v'`z' drop _fd`v'`z' } } if "`impute'"!="" & "`saveimp'"=="" drop `policyvar'_imputed tokenize `varlist' loc depvar "`1'" return matrix b = `bb' return matrix V = `VV' return matrix delta = `delta' return matrix Vdelta = `Vdelta' loc names: subinstr global names ".." " ", all loc names: subinstr local names `"""' "", all return local names = "`names'" return local cmd = "`cmd'" return local depvar = "`depvar'" end