version 13 program define _eventiv, 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 */ LWindow(string) /* Left window */ RWindow(string) /* Right window */ w_type(string) /* Window defined by the user (numeric) or define window based on the data time limits (string: max or balanced) */ 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 */ SAVek(string) /* Generate the time-to-event dummies, trend and keep them in the dataset */ nogen /* Do not generate k variables */ kvars(string) /* Stub for event dummies to include, if they have been generated already */ norm(numlist integer max=1) /* Normalization */ reghdfe /* Use reghdfe for estimation */ IMPute(string) /*imputation on policyvar*/ *static /* in this ado used for calling the part of _eventgenvars that imputes*/ addabsorb(string) /* Absorb additional variables in reghdfe */ REPeatedcs /*indicate that the input data is a repeated cross-sectional dataset*/ DIFFavg /* Obtain regular DiD estimate implied by the model */ * ] ; #d cr marksample touse tempvar mkvarlist qui gen byte `mkvarlist' = `touse' tempname delta Vdelta bb VV bb2 VV2 delta2 Vdelta2 deltaov Vdeltaov deltax Vdeltax deltaxsc bby bbx VVy VVx tousegen * 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 * For eventgenvars, ignore missings in varlist mark `tousegen' `if' `in' * Set norm to -1 if missing if "`norm'"=="" loc norm -1 loc i = "`panelvar'" loc t = "`timevar'" loc z = "`policyvar'" *parse savek if "`savek'"!="" parsesavek `savek' foreach l in savek noestimate kreplace { loc `l' = r(`l') if "``l''"=="." loc `l' "" return loc `l' = "``l''" } *If imputation is specified, _eventiv will call _eventgenvars twice. *The first call only imputes the policyvar, but the second call imputes both the policyvar and the event-time dummies *First call: bring the imputed policyvar calling only _eventgenvars' imputation code. This call is neccesary to choose the lead order using the imputed policyvar if ("`impute'"!="") { *rr is the tempvar to be imputed: create it in _eventiv, so after _eventgenvars we can still have access to it. tempvar rr qui gen double `rr'=. *call _eventgenvars _eventgenvars if `tousegen', panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') impute(`impute') static rr(`rr') lwindow(`lwindow') w_type(`w_type') mkvarlist(`mkvarlist') `repeatedcs' //with option static, we skip the code that generates the event-time dummies // Include options lwindow and w_type because when selecting lead order for proxyiv we need to evaluate all lead orders limited by the calculated left window in case the user specified window(max) or window(balanced) loc impute=r(impute) if "`impute'"=="." loc impute = "" *if imputation succeeded, use the values brought by rr if "`impute'"!="" { tempvar zimp qui gen double `zimp'=`rr' loc z="`zimp'" } *otherwise, keep using the original policyvar else loc z = "`policyvar'" * if window(max) or window(balanced), what value is left window? if "`w_type'"=="string" { loc lwindow_call1 = r(lwindow) } } *define local for left window. Can be the input by the user or the value calculated with the data if "`w_type'"=="numeric" loc lwindow_iter = `lwindow' else loc lwindow_iter = `lwindow_call1' * 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)`=-`lwindow_iter''{ 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 as text _n "No proxy instruments specified. Using leads of differenced 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 if `lwindow_iter'== 0 { di as err _n "Estimation window must contain at least 1 period before the policy change" di as err "for proxy instrument selection." exit 301 } forv v=1(1)`=-`lwindow_iter'' { if "`repeatedcs'"=="" { tempvar _fd`v'`z' qui gen double `_fd`v'`z'' = f`v'.d.`z' if `touse' } qui reg `proxy' `_fd`v'`z'' if `touse' 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 loc ivwords = 0 foreach v in `proxyiv' { cap confirm integer number `v' if _rc loc ++rc loc ++ivwords } * Three possible types of lists: all numbers for leads, all vars for external instruments, or mixed * All numbers if `rc' == 0 { loc leadivs "" 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' } loc leadivs "`leadivs' _fd`v'`z'" } loc instype = "numlist" loc varivs = "" } * All words else if `rc'==`ivwords' { foreach v in `proxyiv' { confirm numeric variable `v' } loc instype = "varlist" loc leadivs = "" loc varivs = "`proxyiv'" } * Mixed else { loc leadivs "" loc varivs "" foreach v in `proxyiv' { cap confirm integer number `v' if _rc loc varivs "`varivs' `v'" else { 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' } loc leadivs "`leadivs' _fd`v'`z'" } } loc instype "mixed" } * Count normalizations and set omitted coefs for plot accordingly * Need one more normalization per IV loc komit "" loc norm0 "`norm'" *split proxyiv into two lists: only numbers or only varnames loc proxyiv_numbers "" loc proxyiv_vrnames "" foreach v in `proxyiv' { cap confirm number `v' if !_rc loc proxyiv_numbers "`proxyiv_numbers' `v'" else loc proxyiv_vrnames "`proxyiv_vrnames' `v'" } foreach v in `proxyiv_numbers' { cap confirm integer number `v' if _rc { di as err "Lead of policy variable to be used as instrument must be an integer." exit 301 } } * Check that leads in proxyiv are in the estimation window foreach v in `proxyiv_numbers' { if (`v' > `=-`lwindow_iter'+1') { di as err "Lead `v' of policy variable to be used as instrument is outside estimation window." exit 301 } } * Set normalizations in case these are numbers, so we are using leads of delta z loc ivnorm "" if "`instype'"=="numlist" | "`instype'"=="mixed" { foreach v in `proxyiv_numbers' { if `=-`v''==`norm' { loc ivnorm "`ivnorm' `=-`v'-1'" di as txt _n "The corresponding coefficient of lead `v' and the normalized coefficient were the same. Lead `=`v'' has been changed to `=`v'+1'." if (-`ivnorm' > `=-`lwindow_iter'+1') { di as err "Lead `= - `ivnorm'' of policy variable to be used as instrument is outside estimation window." exit 301 } loc repeatlead=strmatch("`proxyiv_numbers'","*`=`v'+1'*") if "`repeatlead'"=="0"{ di as txt _n "The coefficient at `norm' is normalized to zero." di as txt _n "For estimation with proxy variables, an additional coefficient needs to be normalized to zero." di as txt _n "The coefficient at `=-`v'-1' was selected to be normalized to zero." } } else { loc ivnorm "`ivnorm' -`v'" di as txt _n "The coefficient at `norm' is normalized to zero." di as txt _n "For estimation with proxy variables, an additional coefficient needs to be normalized to zero." di as txt _n "The coefficient at `=-`v'' was selected to be normalized to zero." } } } *set normalizations for external instruments *get the pool of available coefficients for normalization loc available "" forvalues l=1/`=-`lwindow_iter'+1'{ loc l = -`l' loc available "`available' `l'" } loc available: list available - norm foreach var of loc proxyiv_vrnames{ loc available: list available - ivnorm loc lenav: word count(`available') if `lenav'==1 { di as err "Number of instruments specified in {bf:proxyiv} reached the maximum imposed by the number of pre-event periods." exit 301 } *normalize one extra coefficient per external instrument loc avcomma : subinstr loc available " " ",", all loc avmax = max(`avcomma') //choose the coefficient closest to zero loc ivnorm "`ivnorm' `avmax'" // add it to ivnorm di as text _n "The coefficient at `avmax' was selected to be normalized to zero" } * Normalize one more lag if normalization = number of proxys if "`instype'"=="numlist" | "`instype'"=="mixed" { loc np: word count `proxy' * loc npiv: word count `norm' `ivnorm' loc npiv : list norm | ivnorm loc npiv : list uniq npiv loc npiv : word count `npiv' if `np'==`npiv' { loc ivnormcomma : subinstr local ivnorm " " ",", all loc ivmin = min(`ivnormcomma') loc ivnorm "`ivnorm' `=`ivmin'-1'" } } * No need to normalize for external instruments. If the user generates a lead of z and uses it as a variable, the instrument is collinear. foreach j in `norm' `ivnorm' { loc norm "`norm' `j' " loc komit "`komit' `j'" } loc komit: list uniq komit if "`gen'" != "nogen" { *If impute was specified, this is the second call to _eventgenvars: this time, both the policyvar and the event-time dummies will be imputed. Additional computations will happen as well (e.g., macros, etc.). _eventgenvars if `tousegen', panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') lwindow(`lwindow') rwindow(`rwindow') w_type(`w_type') `trend' norm(`norm') impute(`impute') mkvarlist(`mkvarlist') `repeatedcs' loc included=r(included) loc names=r(names) loc komittrend=r(komittrend) loc ambiguous = r(ambiguous) if "`komittrend'"=="." loc komittrend = "" *if window was max or balanced, use calculated left and right window limits if "`w_type'"=="string" { loc lwindow = r(lwindow) loc rwindow = r(rwindow) } } else { loc kvstub "`kvars'" loc j=1 loc names "" loc included "" foreach var of varlist `kvstub'* { if `norm' < 0 loc kvomit = "m`=abs(`norm')'" else loc kvomit "p`=abs(`norm')'" if "`var'"=="`kvstub'_evtime" | "`var'" == "`kvstub'_eq_`kvomit'" continue if "`kvstub'"!="_k" { loc sub : subinstr local var "`kvstub'" "_k", all clonevar `sub' = `var' } else { loc sub = "`var'" } if `j'==1 loc names `""`sub'""' else loc names `"`names'.."`sub'""' * " loc included "`included' `sub'" loc ++ j } loc komittrend=r(komittrend) if "`komittrend'"=="." loc komittrend = "" } *" loc komit "`norm' `komittrend'" loc komit = strtrim(stritrim("`komit'")) loc komit: list uniq komit * Check that the iv normalization works foreach v in `leadivs' `varivs' { cap _rmdcoll `v' `included' if `touse' if _rc { di as err "Instrument {bf:`v'} is collinear with the included event-time dummies. You may have generated leads of the policy variable and included them in the proxyiv option instead of specifying the lead numbers." exit 301 } } if "`te'" == "note" loc tte "" else loc tte "i.`t'" **** Main regression ** In the repeated cross section case with fixed effects, cannot use xtivreg, so default to reghdfe if "`repeatedcs'"!="" & "`fe'"!="nofe" { loc reghdfe = "reghdfe" di as text _n "Using {cmd:reghdfe} for fixed effects estimation with repeated cross-sectional data." } if "`noestimate'"==""{ if "`reghdfe'"=="" { if "`fe'" == "nofe" { loc cmd "ivregress 2sls" loc ffe "" loc small "small" } else { loc cmd "xtivreg" loc ffe "fe" } *translate standard error specification: *analyze inclusion of cluster or robust in options parse_es ,`options' foreach orig in cl_orig rob_orig vce_orig other_opts{ loc `orig' = r(`orig') if "``orig''"=="." loc `orig' "" } *if xtivreg, warn the user about robust estandar errors equivalent to vce(cluster panelvar) if "`cmd'"=="xtivreg" & (("`vce_orig'"=="robust" | "`vce_orig'"=="r") | "`rob_orig'"!=""){ di as text _n "You asked for robust standard errors and the underlying estimation command is {cmd:xtivreg}. Standard errors will be clustered by panelvar. See {help xtivreg##options_fe:xtivreg}." } *if it doesn't contain cluster and robust: if "`cl_orig'"=="" & "`rob_orig'"=="" { `cmd' `varlist' (`proxy' = `leadivs' `varivs') `included' `tte' [`weight'`exp'] if `touse' , `ffe' `small' `options' } *if it contains either cluster or robust: else{ *if the user already specified vce, then we cannot specify a second vce if "`vce_orig'"!="" { *execute as defined by the user and expect some error `cmd' `varlist' (`proxy' = `leadivs' `varivs') `included' `tte' [`weight'`exp'] if `touse' , `ffe' `small' `options' } else{ loc vce_opt "" *parse cluster if "`cl_orig'"!=""{ loc vce_opt = "vce(cluster `cl_orig')" //if robust is also specified, no need to add it } else { loc vce_opt = "vce(robust)" } `cmd' `varlist' (`proxy' = `leadivs' `varivs') `included' `tte' [`weight'`exp'] if `touse' , `ffe' `small' `vce_opt' `other_opts' } } } 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' = `leadivs' `varivs') `included' [`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' = `leadivs' `varivs') `included' [`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 * Return coefficients and variance matrix of the delta k estimates separately mat `bb'=e(b) mat `VV'=e(V) mat `delta' = `bb'[1,`names'] mat `Vdelta' = `VV'[`names',`names'] if "`reghdfe'"=="" { if "`fe'" == "nofe" { loc df=e(df_r) } else { loc df=e(df_rz) } } else { loc df=e(df_r) if `df'==. loc df=e(Fdf2) } loc kmax=`=`rwindow'+1' loc kmin=`=`lwindow'-1' tempvar esample gen byte `esample' = e(sample) if "`diffavg'"!=""{ *list of omitted coefficients loc komit_comma : subinstr local komit " " ",", all * fill in lists of pre and post coefficients loc pre_plus "" loc post_plus "" forvalues v = `=`lwindow'-1'/`=`rwindow'+1' { if inlist(`v', `komit_comma') continue if `v'<0 { loc pre_plus "`pre_plus' _k_eq_m`=-`v''" } else { loc post_plus "`post_plus' _k_eq_p`=`v''" } } loc pre_plus = strtrim("`pre_plus'") if "`pre_plus'"=="" { di as err "No pre-event coefficients to calulate the difference in averages" exit 301 } loc post_plus = strtrim("`post_plus'") if "`post_plus'"=="" { di as err "No post-event coefficients to calulate the difference in averages" exit 301 } loc pre_plus : subinstr local pre_plus " " " + ", all loc post_plus : subinstr local post_plus " " " + ", all di as text _n "Difference in pre and post-period averages from lincom:" lincom ((`post_plus') / (`rwindow' + 2)) - ((`pre_plus') / (`=-`lwindow'' + 1)), cformat(%9.4g) } * Plots * Calculate mean before change in policy for 2nd axis in plot * This needs to be relative to normalization tempvar temp_k if `norm0' < 0 loc kvomit = "m`=abs(`norm0')'" else loc kvomit "p`=abs(`norm0')'" qui gen `temp_k'=_k_eq_`kvomit' tokenize `varlist' qui su `1' if `temp_k'!=0 & `temp_k'!=. & `esample', meanonly loc y1 = r(mean) loc depvar "`1'" * Calculate mean proxy before change in policy for 2nd axis in plot if "`proxy'"!="" { loc nproxy: word count `proxy' if `nproxy' ==1 { qui su `proxy' if `temp_k'!=0 & `temp_k'!=. & `esample', meanonly loc x1 = r(mean) } else loc x1 = . } * Variables for overlay plots * Need the ols estimates for y and x * Do not exclude vars other than m1 *loc toexc = "_k_eq_m1" *unab included2: _k_eq_* *loc included2 : list included2 - toexc _estimates hold main qui _eventols `varlist' [`weight'`exp'] if `touse' , panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') lwindow(`lwindow') rwindow(`rwindow') `fe' `te' nogen nodrop kvars(_k) norm(`norm0') impute(`impute') mat `deltaov' = r(delta) mat `Vdeltaov' = r(Vdelta) *mat `deltay' = `bby'[1,${names}] *mat `Vdeltay' = `VVy'[${names},${names}] qui _eventols `proxy' [`weight'`exp'] if `touse', panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') lwindow(`lwindow') rwindow(`rwindow') `fe' `te' nogen nodrop kvars(_k) norm(`norm0') impute(`impute') mat `deltax' = r(delta) mat `Vdeltax' = r(Vdelta) *mat `deltax' = `bb'[1,${names}] * mat `Vdeltax' = `VV'[${names},${names}] * Scaling factor loc ivnormcomma = strtrim("`ivnorm'") loc ivnorms : list sizeof ivnormcomma loc ivnormcomma : subinstr local ivnormcomma " " ",", all if `ivnorms'>1 loc scfactlead = -max(`ivnormcomma') else loc scfactlead = -`ivnormcomma' mat Mfn = `deltaov'[1,"_k_eq_m`scfactlead'"] mat Mfd = `deltax'[1,"_k_eq_m`scfactlead'"] loc fn = Mfn[1,1] loc fd = Mfd[1,1] loc factor = `fn'/`fd' * Scale x estimates by factor mat `deltaxsc' = `factor'*`deltax' } *recover omitted k vars loc kvars_omit "" if "`komit'"!=""{ foreach k in `komit' { if `k'<0 loc kvars_omit "`kvars_omit' _k_eq_m`=abs(`k')'" else loc kvars_omit "`kvars_omit' _k_eq_p`=abs(`k')'" } } *full list of event-time dummies (included + omitted) loc eventtd = "`included' `kvars_omit'" * Drop variables if "`savek'" == "" { cap confirm var `eventtd', exact if !_rc drop `eventtd' cap confirm var __k, exact if !_rc qui drop __k } else { *change prefix loc eventtd_savek : subinstr local eventtd "_k" "`savek'", all *If replace suboption, drop the existing variables before renaming the recently created ones if "`kreplace'"!="" { *event-time dummies foreach v in `eventtd_savek' { cap confirm variable `v', exact if !_rc drop `v' } *event-time variable cap confirm variable `savek'_evtime, exact if !_rc drop `savek'_evtime } *Check that variables don't exist cap confirm variable `eventtd_savek', exact if !_rc { di as err _n "You specified to save the event-time dummy variables using the prefix {bf:`savek'}, but you already have event-time dummy variables saved with that prefix." di as err _n "Use the {bf:replace} suboption to replace the existing variables." exit 110 } cap confirm variable `savek'_evtime, exact if !_rc { di as err _n "You specified to save the event-time variable using the prefix {bf:`savek'}, but you already have an event-time variable saved with that prefix." di as err _n "Use the {bf:replace} suboption to replace the existing variable." exit 110 } ren __k `savek'_evtime ren (`eventtd') (`eventtd_savek') } if "`instype'"=="numlist" | "`instype'"=="mixed" { foreach v in `leadivs' { drop `v' } } *skip the rest of the program if the user indicated not to estimate if "`noestimate'"!="" exit * Returns _estimates unhold main return matrix b = `bb' return matrix V = `VV' return matrix delta = `delta' return matrix Vdelta = `Vdelta' return matrix deltaov = `deltaov' return matrix Vdeltaov = `Vdeltaov' return matrix deltax = `deltax' return matrix Vdeltax = `Vdeltax' return matrix deltaxsc = `deltaxsc' loc names: subinstr local names ".." " ", all loc names: subinstr local names `"""' "", all return local names = `"`names'"' * " return local cmd = "`cmd'" return local df = `df' return local komit = "`komit'" return local kmiss = "`kmiss'" return local ambiguous = "`ambiguous'" return local y1 = `y1' return local depvar = "`depvar'" if `x1'!=. return local x1 = `x1' return local method = "iv" end *program to parse savek program define parsesavek, rclass syntax [anything] , [NOEstimate replace] return local savek "`anything'" return local noestimate "`noestimate'" return local kreplace "`replace'" end *program to parse standar error specification program define parse_es, rclass #d; syntax [anything], [ CLuster(varname) Robust vce(string) * ] ; #d cr return local cl_orig "`cluster'" return local rob_orig "`robust'" return local vce_orig "`vce'" return local other_opts "`options'" end