*! version 1.0.1 20040119 (SJ4-2: st0060) * J. Levinsohn, A. Petrin, and B. Poi * Created: 20030520 * Levinsohn-Petrin estimator with option for value-added or revenue * Usage: * levpet depvar [if] [in], free(freevars) proxy(proxy1 [proxy2]) * capital(capitalvar) i(panelvar) t(timevar) reps(BS reps) * level(sig. level) [VAlueadded | REVenue] justid * * where depvar = log value added if va specified (line search) * = log revenues if revenue specified (GMM) * freevars = log freely variables inputs (e.g. blue & white c. labor) * proxy = log intermediate input(s) * Max 2 if value added is LHS variable * Max 1 if revenue is LHS variable * capitalvar = log capital * i = panel ID variable * t = time variable * reps = number of bootstraps to use * level = significance level for z-stats and conf. intervals * valueadded = depvar represents log value added (line search) * (valueadded is default) * revenue = depvar represents log gross revenue (GMM) * justid = Uses only capital and lagged proxy as * instruments in GMM * grid = Uses grid search instead of -nl- for GMM capture program drop levpet program define levpet, sortpreserve eclass version 7.0 syntax varname [if] [in], free(varlist) /* */ proxy(varlist numeric min=1 max=2) /* */ capital(varname) /* */ [i(varname) t(varname) reps(integer 50) /* */ REVenue VAlueadded Level(int $S_level) /* */ justid grid] local depvar `varlist' marksample touse markout `touse' `free' `proxy' `capital' `i' `t' /* Syntax check: is data tsset? */ if ("`i'" == "" | "`t'" == "") { capture tsset if (_rc != 0) { di as error "You must tsset your data or specify i() and t()." error _rc } else { local i = r(panelvar) local t = r(timevar) } } else { quietly tsset `i' `t' } /* Is level valid? */ if (`level' < 10 | `level' > 99) { di as error "level must be between 10 and 99" error 198 } /* Value added or revenue? */ if ("`revenue'" != "" & "`valueadded'" != "") { di as error "Only one of revenue and valueadded can be specified." exit 198 } if ("`revenue'" != "") { local model "revenue" } else { local model "valueadded" } local numprox : word count `proxy' if ("`model'" == "revenue" & `numprox' > 1) { di as error "Only one proxy variable can be used with revenue." exit 198 } /* Reps reasonable? */ if (`reps' < 2) { di as error "reps() must be at least 2." exit 198 } /* Just-identified GMM? */ local just = 0 if ("`justid'" != "" & "`model'" != "revenue") { di as error "justid can only be used with revenue (GMM) model." exit 198 } else if "`justid'" != "" { local just = 1 } /* Grid search? */ local gsrch = 0 if ("`grid'" != "" & "`model'" != "revenue") { di as error "grid can only be used with revenue (GMM) model." exit 198 } else if "`grid'" != "" { local gsrch = 1 } qui count if `touse' loc capn = r(N) /* Since we're using version 7 syntax, we need to build up a list of the statistics that we want to bootstrap. */ local rmacs "" foreach var in `free' `capital' { local rmacs "`rmacs' (r(`var'))" } /* If revenue, incl. proxy */ if ("`model'" == "revenue") { local rmacs "`rmacs' (r(`proxy'))" /* there's only one */ } /* To get clustering to work right, we need to bsample and post everything ourselves. */ quietly { tempfile postfile datafile tempname post tempvar idvar gen `idvar' = `i' preserve keep if `touse' loc cmd "`depvar' , free(`free') proxy(`proxy') capital(`capital') " /* First do it to the original sample. */ tsset `idvar' `t' if ("`model'" == "valueadded") { lp_srch `cmd' i(`idvar') t(`t') } else { /* Need to store off the final values of the sample moments */ global LPone = 1 /* indicates orig. data */ lp_gmm `cmd' i(`idvar') t(`t') converrs(0) just(`just') grid(`gsrch') global LPone = 0 /* prevents overwrite during bootstrap */ } local converrs = 0 foreach x of local rmacs { if (`x' >= .) { local converrs = 1 noi di as error /* */ "Insufficient variation to identify the capital and intermediate input" noi di as error /* */ "coefficients separately. Bootstrapping for first-stage parameters only." } } if ("`model'" == "valueadded") { /* no proxies to post */ postfile `post' `free' `capital' using `"`postfile'"', /* */ double replace local rmacs "" foreach var in `free' `capital' { local rmacs "`rmacs' (r(`var'))" } } else { if `converrs' == 0 { postfile `post' `free' `capital' `proxy' using `"`postfile'"', /* */ double replace local rmacs "" foreach var in `free' `capital' { local rmacs "`rmacs' (r(`var'))" } local rmacs "`rmacs' (r(`proxy'))" /* there's only one */ } else { /* We had convergence problems, only doing free vars */ postfile `post' `free' using `"`postfile'"', double replace local rmacs "" foreach var in `free' { local rmacs "`rmacs' (r(`var'))" } } } post `post' `rmacs' /* Now do it `reps' times. */ forvalues cnt = 1/`reps' { noi di "." _continue restore, preserve keep if `touse' tempvar idvar bsample, cluster(`i') idcluster(`idvar') if ("`model'" == "valueadded") { lp_srch `cmd' i(`idvar') t(`t') } else { lp_gmm `cmd' i(`idvar') t(`t') converrs(`converrs') /* */ just(`just') grid(`gsrch') } post `post' `rmacs' } postclose `post' /* drop the LPone and LPmoments since we're done with them */ if ("`model'" == "revenue") { macro drop LPone mat drop LPmoments } /* Use post results to make e(b) and e(V). First obs in postfile is original sample results. */ tempname evar eb use `"`postfile'"', clear mat accum `evar' = * in 2/l , deviations noconstant mat `evar' = `evar' / (r(N) - 1) mkmat * in 1, matrix(`eb') /* Compute a Wald test for constant returns if no errors */ if `converrs' == 0 { tempname capr diff rvri waldcrs junk loc bsize = colsof(`eb') mat `capr' = J(1, `bsize', 1) mat `rvri' = syminv(`capr'*`evar'*`capr'') mat `diff' = `eb'*`capr'' - 1 mat `junk' = `diff'*`rvri'*`diff' scalar `waldcrs' = trace(`junk') } restore estimates post `eb' `evar' , esample(`touse') depname(`"`depvar'"') /* */ obs(`capn') if `converrs' == 0 { estimates scalar waldcrs = `waldcrs' } estimates local depvar `depvar' if ("`model'" == "revenue") { estimates local model "revenue" } else { estimates local model "value added" } estimates local predict "levpet_p" estimates local cmd "levpet" tsset `i' `t' } /* End of quietly block */ di _n _n qui xtdes , i(`i') t(`t') di as text "Levinsohn-Petrin productivity estimator" di if ("`model'" == "revenue") { di as text "Dependent variable represents revenue." _continue } else { di as text "Dependent variable represents value added." _continue } di _col(49) as text "Number of obs = " as result %9.0f `capn' di as text "Group variable (i): `i'" _continue di _col(49) as text "Number of groups = " as result %9.0f r(N) di as text "Time variable (t): `t'" di _col(49) as text "Obs per group: min = " as result %9.0f r(min) di _col(49) as text " avg = " as result %9.1f r(mean) di _col(49) as text " max = " as result %9.0f r(max) di estimates display, level(`level') if `converrs' == 0 { di as text "Wald test of constant returns to scale: Chi2 = " /* */ as result %6.2f e(waldcrs) as text " (p = " /* */ as result %6.4f chi2tail(1, e(waldcrs)) as text ")." } end