/****************************************************************************** PROGRAM DEFINES XTGMMFA Performs GMM estimation for factor-augmented panel data model with fixed T Author: Manh Hoang-Ba Support: hbmanh9492@gmail.com Ref.: Juodis & Sarafidis (2022) Draft 2.1: - Small sample adjustment --> Done! ******************************************************************************/ cap program drop xtgmmfa program define xtgmmfa, eclass version 11 if replay() { if "`e(cmd)'"!="xtgmmfa" { di in red "last estimate not xtgmmfa" exit 301 } else syntax [, Level(cilevel)] } else { syntax varlist(num fv ts) [if] [in] , /// GMMvars(string) /// // done [ UNOFactors(string) /// // done IVvars(varlist ts fv) /// // done Wmat(int 2) /// // done Robust /// // vcetype CLuster(varname) /// // vcetype ONEstep /// // done Level(cilevel) /// // report NOCONStant /// // done OBSFactors(varlist ts fv) /// // done rho(real 0.75) /// small /// ] local cmdline xtgmmfa `0' * - touse var tempvar touse0 touse mark `touse' `if' `in' qui gen byte `touse0' = `touse' * - idvar, tvar tempname ivar tvar b V theta Vtheta Fe_hat /// n_c r_ga df_m wald waldp bic j_df j j_s j_p le d G reg_unb ft_unb // Check for rho if `rho'<=0 { di in red "rho must be positive" exit 198 } // Check for xtset qui xtset if "`r(panelvar)'" == "" { di in red "Data must be xtset before using this command" exit 459 } * - noconstant if "`noconstant'" != "" { local nocons nocons } * - varlist: tempvars + varlist name + maxlag of y _rmcoll `varlist' if `touse', `nocons' local varlist0 "`r(varlist)'" fvrevar `varlist0' if `touse' local tempvars "`r(varlist)'" // tempvars markout `touse' `tempvars' gettoken depvar indepvars : tempvars // tempvar_names fvexpand `varlist0' if `touse' local varnames "`r(varlist)'" // varnames gettoken depname rest: varnames if "`noconstant'" != "" { local cons = 0 local indepnames "`rest'" } else { local cons = 1 local indepvars0 `indepvars' tempname _cons qui gen byte `_cons' = 1 if `touse' local tempvars `tempvars' `_cons' local indepnames "`rest' _cons" } * - gmmvars * Parsing gmmvars(varlist(ts fv), mlag(int -1)) local 0 `gmmvars' cap syntax varlist(ts fv), [mlag(int -1)] if _rc { di as err _n "gmmvars(`0') invalid." exit 198 } local gmmvars `varlist' _rmcoll `gmmvars' if `touse', //expand local gmmvars "`r(varlist)'" fvrevar `gmmvars' if `touse' local zvars1 "`r(varlist)'" qui foreach var of local zvars1 { replace `var'=0 if `var'==. & `touse' } qui _rmcoll `zvars1' if `touse', forcedrop local zvars1 "`r(varlist)'" * - ivvars if `cons' == 1 { local ivvars `ivvars' `_cons' _rmcoll `ivvars' if `touse', noconstant local ivvars "`r(varlist)'" } else { if "`ivvars'" != "" { _rmcoll `ivvars' if `touse' local ivvars "`r(varlist)'" } } fvrevar `ivvars' if `touse' local zvars2 "`r(varlist)'" qui _rmcoll `zvars2' if `touse', noconstant forcedrop local zvars2 "`r(varlist)'" local zvars `zvars1' `zvars2' markout `touse' `zvars' //`V' * - vvars * Parsing unofactors(varlist(ts fv), /// [wvar(varname) /// method(regu | bss) /// type(int 1) /// lmax(int 2) /// seed(int 120) /// power(int 0) /// er /// NOREGressor]) local 0 `unofactors' cap syntax [anything], [wvar(varname) /// bss /// type(int 1) /// lmax(int 2) /// seed(int 120) /// power(int 0) /// er /// NOREGressor] if _rc { di as err _n "unofactors(`0') invalid." exit 198 } if "`anything'" == "" { if "`noregressor'"== "" local vvars `depname' `rest' else { di in red "`noregressor' cannot be specified with an empty Vlist." di in red "unofactors(`unofactors') invalid." exit 198 } } else { local 0 `anything' cap syntax varlist(ts fv) if "`noregressor'"== "" local vvars `varlist' `depname' `rest' else local vvars `varlist' } if "`bss'"=="" local method "regu" else local method "bss" if "`method'"=="regu" local method_i = 1 else local method_i = 2 if "`er'"=="" local stat "gr" if "`small'" != "" local small_vl = 1 else local small_vl = 0 /* if "`stat'"!="er" & "`stat'"!="gr" { di in red "stat(`stat') invalid." di in red "unofactors() invalid." exit 198 } */ _rmcoll `vvars' if `touse0', nocons local vvars "`r(varlist)'" fvrevar `vvars' if `touse0' local vvars "`r(varlist)'" qui _rmcoll `vvars' if `touse0', nocons forcedrop local V "`r(varlist)'" if `type'==1 { gettoken V1 rest: V local V `V1' // use only first var in vvars } local Vtemp local Vout = 0 foreach var of local V { qui xtsum `var' if `touse0' if r(sd_w)==0 local Vout = `Vout' + 1 else local Vtemp `Vtemp' `var' } if `Vout'>0 { di in red "Vlist (including y and X) must be time-varying." di in red "`Vout' time-invariant variables are dropped." } local V `Vtemp' if "`wmat'" != "1" & "`wmat'" != "2" { di in red "wmat(`wmat') invalid." exit 198 } preserve qui xtset local timevar "`r(timevar)'" local panelvar "`r(panelvar)'" * - observed factors _rmcoll `obsfactors' if `touse0', `nocons' local obsfactors "`r(varlist)'" fvrevar `obsfactors' if `touse0' local obsfactors "`r(varlist)'" // markout `touse' `obsfactors' * - wvars tempvar w0 touse2 sort `panelvar' `timevar' if "`wvar'"=="" { qui by `panelvar': gen double `w0' = `depname'[1] if `touse0' } else { local n_w : word count `wvar' if `n_w' > 1 { di in red "too many variables specified." di in red "wvar(`wvar') invalid." exit 198 } else { qui by `panelvar': gen double `w0' = `wvar'[1] if `touse0' } } local W `w0' qui gen byte `touse2' = `touse0' markout `touse2' `V' `W' `obsfactors' // V, W and obsfactors are conditional on [if] [in] foreach var of varlist `V' `W' `obsfactors' { qui replace `var' = `var'*`touse2' qui replace `var' = 0 if `var'==. } qui egen long `ivar' = group(`panelvar') if `touse' sort `ivar' `timevar' qui sum `ivar' if `touse', mean local N = r(max) qui keep if `touse' qui keep `panelvar' `ivar' `timevar' `tempvars' `zvars' /// `V' `W' `obsfactors' `cluster' `touse' // Treat unbalanced panel local balance = 1 tempvar Ti qui egen `Ti' = sum(`touse') /*if `touse'*/, by(`ivar') qui sum `Ti' /*if `touse'*/, mean local T_bar = r(mean) local T_max = r(max) local T_min = r(min) if r(min) != r(max) { local balance = 0 local N0 = _N qui drop if `Ti' < 2 local n_drop = `N0' - _N if `n_drop' > 0 { di in red "`r(N_drop)' observations is dropped" di in red "xtgmmfa requires at least 2 periods for each group" } tempvar reg_miss ft_miss qui egen byte `reg_miss' = rowmiss(`tempvars' `zvars') /*if `touse'*/ qui gen byte `reg_unb' = (`reg_miss'==0) /*if `touse'*/ qui egen byte `ft_miss' = rowmiss(`V' `W' `obsfactors') /*if `touse'*/ qui gen byte `ft_unb' = (`ft_miss'==0) /*if `touse'*/ tempfile temp_data sort `ivar' `timevar' qui save `temp_data', replace qui sum `timevar' /*if `touse'*/ local Tmax = r(max) local Tmin = r(min) clear qui set obs `=`N'*(`Tmax' - `Tmin' + 1)' qui gen long `ivar' = ceil(_n/(`Tmax' - `Tmin' + 1)) qui gen long `timevar' = `Tmin' + mod(_n-1, (`Tmax' - `Tmin' + 1)) qui merge 1:1 `ivar' `timevar' using `temp_data', nogen foreach var of varlist `tempvars' `zvars' `reg_unb' /// `V' `W' `obsfactors' `ft_unb' `Ti' { qui replace `var' = 0 if missing(`var') /*& `touse'*/ } // Hadarmad control foreach var of varlist `tempvars' `zvars' { qui replace `var' = `var'*`reg_unb' /*if `touse'*/ } foreach var of varlist `V' `W' `obsfactors' { qui replace `var' = `var'*`ft_unb' /*if `touse'*/ } } sort `ivar' `timevar' qui by `ivar': gen byte `tvar' = _n /*if `touse'*/ qui sum `tvar' /*if `touse'*/, mean local T = r(max) * - N, T, maxlag, k, exp, seed, onestep, robust get_maxlag, varlist("`varlist0'") local maxlag = r(maxlag) if `balance'==1 local obs = `T'*`N' else { qui sum `touse' /*if `touse'*/, mean local obs = r(sum) } if `T'<2 { di in red "xtgmmfa requires at least 2 periods for each group" exit 459 } local k1 : word count `tempvars' local k = `k1' - 1 local pow_max = `T'-1 local l_max = `lmax' if `method_i'==1 { if "`er'" != "" local stat_vl = 1 else { if `T'<3 { di in red "GR statistic requires at least 3 periods" _n /// "use ER statistic (option {bf:er}) if you only have 2" exit 459 } local stat_vl = 0 } } else local stat_vl = 2 if "`onestep'" != "" local step = 1 else local step = 2 if "`robust'" != "" local rob = 1 else local rob = 0 if `wmat' == 1 local iden = 1 else local iden = 0 * - cluster var local n_cl : word count `cluster' if `n_cl'>1 { di in red "cluster(`cluster') invalid." exit 198 } else if `n_cl'==1 { local clust = 1 // Check if clustervar time-variance qui xtsum `cluster' /*if `touse'*/ if r(sd_w) > 0 { di in red "cluster variable must be time-invariant within panel" exit 198 } // Check if panelvar nested within clustervar * (inspired by _xtreg_chk_cl2.ado) tempname temp1 temp2 * Mark the first obs in each group sort `cluster' qui by `cluster': gen long `temp1' = (_n==1) /*if `touse'*/ * Cummulative sum: g=1 --> temp1 = 1, g=2 --> temp1 = 2, ... qui replace `temp1' = sum(`temp1') * Sort id cluster sort `ivar' `touse' `cluster' * If panelvar nested within cluster var: first = last obs qui by `ivar' `touse' : gen long `temp2' = `temp1'[_n] - `temp1'[1] qui count if `temp2' != 0 //& `touse' //& `cluster' != . if r(N) > 0 { di in red "panels are not nested within clusters" exit 198 } qui replace `cluster' = 0 if `cluster'==. //& `touse' } else local clust = 0 * - Selector matrix selectorMatrix, t(`T') gmm(`zvars1') iv(`zvars2') m(`mlag') tempname S mat `S'=r(S) local zeta = rowsof(`S') // Number of instruments /*================================================================= 1.2. Reshape data and import to mata =================================================================*/ qui keep if `touse' qui keep `ivar' `tvar' `tempvars' `zvars' /// `V' `W' `obsfactors' `cluster' `Ti' qui ds `ivar' `tvar', not qui reshape wide `r(varlist)', /// i(`ivar') j(`tvar') /*================================================================= 1.3. Estimate =================================================================*/ mata: estimate(`small_vl',`balance',`T', `l_max', /* */ `pow_max', `power', `N', `seed', /* */ `stat_vl', `zeta', `iden', `rob', `step', /* */ `rho', `cons', `type', `method_i', `clust', "cluster", /* */ "tempvars", "zvars", "V", "W", "`S'", "obsfactors", /* */ "b", "Vb", "`theta'", "`Vtheta'", "`Fe_hat'", /* */ "`j'", "`df_m'", "`wald'", "`waldp'", "`bic'", /* */ "`j_df'", "`j_s'", "`j_p'", "`le'", "`d'", "`r_ga'", /* */ "`G'", "Ti") restore // small adjustment if "`small'" != "" { local df = scalar(`df_m') loc dof "dof(`df')" } // Rename rows/columns matrix mat colname b = `indepnames' mat colname Vb = `indepnames' mat rowname Vb = `indepnames' cap ereturn clear ereturn post b Vb, esample(`touse') dep(`depname') `dof' // Store in e() * - Matrix ereturn mat Fe_hat = `Fe_hat' ereturn mat S = `S' ereturn mat Vtheta = `Vtheta' ereturn mat theta = `theta' * - Scalar ereturn scalar N = `obs' ereturn scalar N_g = `N' ereturn scalar Tmax = `T_max' ereturn scalar Tmin = `T_min' ereturn scalar Tbar = `T_bar' ereturn scalar k = `k' ereturn scalar r_ga = `r_ga' ereturn scalar j = `j' ereturn scalar j_s = `j_s' ereturn scalar j_p = `j_p' ereturn scalar j_df = `j_df' ereturn scalar df_m = `df_m' if "`small'" == "" { ereturn scalar chi2 = `wald' ereturn scalar chi2p = `waldp' local waldp_r "Prob > chi2" } else { local df_r = `N' - `r_ga' ereturn scalar df_r = `df_r' ereturn scalar F = `wald' ereturn scalar F_p = `waldp' ereturn local small "`small'" local waldp_r "Prob > F" } ereturn scalar Le = `le' ereturn scalar d = `d' ereturn scalar bic = `bic' ereturn scalar type = `type' * - Macros if "`onestep'"=="" { if "`robust'"!="" & "`cluster'"=="" { ereturn local clustvar "`panelvar'" ereturn scalar N_clust = `N' ereturn local vcetype "WC-Robust" } else if "`cluster'"!="" { ereturn local clustvar "`cluster'" ereturn scalar N_clust = `G' ereturn local vcetype "WC-Robust" } ereturn local gmmstep "twostep" } else { if "`cluster'"!="" { ereturn local clustvar "`cluster'" ereturn scalar N_clust = `G' ereturn local vcetype "Robust" } else { ereturn local clustvar "`panelvar'" ereturn scalar N_clust = `N' ereturn local vcetype "Robust" } ereturn local gmmstep "onestep" } if "`method'"=="regu" { if "`er'" != "" ereturn local stat_note "Estimated Le (ER)" else ereturn local stat_note "Estimated Le (GR)" ereturn local method "Regularization" } else { ereturn local stat_note "Selected Le (BIC)" ereturn local method "Best-Subset Selection (BSS)" } if "`noconstant'"!="" ereturn local constant "noconstant" else ereturn local constant "hasconstant" ereturn local tvar "`timevar'" ereturn local ivar "`panelvar'" ereturn local cmdline "`cmdline'" ereturn local cmd "xtgmmfa" } // end replay-block /*================================================================= 1.4 Display =================================================================*/ if e(wald) > 999999 { local cfmt `"%10.0g"' } else local cfmt `"%10.3f"' if "`robust'"!="" | "`cluster'"!="" | "`onestep'"=="" { local overid "Hansen" } else local overid "Sargan" di di in gr "Fixed-T Factor-Augmented Panel Data Regression" _n di in gr "Estimator:" _col(15) in ye "Asymptotically linear `e(gmmstep)' GMM" di in gr "Method:" _col(15) in ye "`e(method)'" di in gr "Reference:" _col(15) in ye "Juodis & Sarafidis (2022)" _n di in gr "Number of instruments" /// _col(25) "= " in ye %10.0g e(j) /// _col(49) in gr "Number of obs" /// _col(67) "= " in ye %10.0g e(N) di in gr "Estimated coefficients" /// _col(25) "= " in ye %10.0g e(r_ga) /// _col(49) in gr "Number of groups" /// _col(67) "= " in ye %10.0g e(N_g) di di in gr "`e(stat_note)'" /// _col(25) "= " in ye %10.0g e(Le) /// _col(49) in gr "Time periods:" /// _col(63) "min" _col(67) "= " in ye %10.0g e(Tmin) di in gr "`overid' chi2(" /// in ye e(j_df) /// in gr ")" /// _col(25) "= " in ye %10.4f e(j_s) /// _col(63) in gr "avg" _col(67) "= " in ye %9.1f e(Tbar) di in gr "Prob > chi2" /// _col(25) "= " in ye %10.4f e(j_p) /// _col(63) in gr "max" _col(67) "= " in ye %10.0g e(Tmax) di if "`small'" == "" { di _col(49) in gr "Wald chi2(" /// in ye e(df_m) /// in gr ")" /// _col(67) "= " in ye `cfmt' `wald' } else { di _col(49) in gr "F(" /// in ye e(df_m) /// in gr ", " /// in ye e(df_r) /// in gr ")" /// _col(67) "= " in ye `cfmt' `wald' } di in gr "BIC" /// _col(25) "= " in ye %10.4f e(bic) /// _col(49) in gr "`waldp_r'" /// _col(67) "= " in ye %10.4f `waldp' di ereturn display, l(`level') noemptycells end // end program defines xtgmmfa /*============================================================================== Program define get_maxlag ==============================================================================*/ cap program drop get_maxlag program define get_maxlag, rclass syntax , VARLIST(string) [VAR(string)] local maxlag = 0 local foundvar = 0 foreach token of local varlist { local lag = 0 local vname "" // Use for l(1/3).x l2.x l.x x if regexm("`token'", "L\(([0-9]+)/([0-9]+)\)\.([A-Za-z0-9_]+)") { local vname = regexs(3) local lag = regexs(2) } else if regexm("`token'", "L([0-9]+)\.([A-Za-z0-9_]+)") { local vname = regexs(2) local lag = regexs(1) } else if regexm("`token'", "L\.([A-Za-z0-9_]+)") { local vname = regexs(1) local lag = 1 } else { local vname = "`token'" local lag = 0 } // If var() is specified, return maxlag of var if "`var'" != "" { if "`vname'" == "`var'" { if `lag' > `maxlag' local maxlag = `lag' local foundvar = 1 } } // If not, return maxlag of varlist else { if `lag' > `maxlag' local maxlag = `lag' } } if "`var'" != "" & `foundvar' == 0 { di as err "`var' is not in varlist." exit 198 } return scalar maxlag = `maxlag' end /*============================================================================== SELECTOR MATRIX GENERATOR ==============================================================================*/ cap program drop selectorMatrix program define selectorMatrix, rclass version 11 syntax, Tmax(integer) /// GMMvars(varlist) [IVvars(varlist) Maxlag(integer -1)] local k_gmm : word count `gmmvars' local k_iv : word count `ivvars' // 1. Create S_GMM // Set default maxlags if not specified if `maxlag' == -1 local maxlag = `tmax' * Step 1. Create S_var_t foreach var in `gmmvars' { if `maxlag' >= `tmax' { forvalues t = 1/`tmax' { tempname S_`var'_`t' mat `S_`var'_`t'' = J(`t', `tmax', 0) forvalues i = 1/`t' { mat `S_`var'_`t''[`i', `i'] = 1 } } } else { local inst_num = `maxlag' // While t <= inst_num forvalues t = 1/`inst_num' { tempname S_`var'_`t' mat `S_`var'_`t'' = J(`t', `tmax', 0) forvalues i = 1/`t' { mat `S_`var'_`t''[`i', `i'] = 1 } } // While t > inst_num (rolling window) local t_start = `inst_num' + 1 forvalues t = `t_start'/`tmax' { tempname S_`var'_`t' mat `S_`var'_`t'' = J(`inst_num', `tmax', 0) local col_start = `t' - `inst_num' + 1 forvalues i = 1/`inst_num' { local col = `col_start' + `i' - 1 mat `S_`var'_`t''[`i', `col'] = 1 } } } } * Step 2. Create S_t = blockdiag(S_var_t) forvalues t = 1/`tmax' { tempname S_`t' // First var = l.depvar gettoken first_var rest_vars : gmmvars matr `S_`t'' = `S_`first_var'_`t'' // Remain vars foreach var in `rest_vars' { mata: st_matrix("`S_`t''", /* */ blockdiag(st_matrix("`S_`t''"), /* */ st_matrix("`S_`var'_`t''"))) } // Add columns to S_`t': number of columns = k_iv*tmax if `k_iv'>0 { mat `S_`t'' = `S_`t'', J(rowsof(`S_`t''), `k_iv'*`tmax', 0) } } * Step 3. Create matrix S=blockdiag(S_t) tempname S_final mat `S_final' = `S_1' forvalues t = 2/`tmax' { mata: st_matrix("`S_final'", /* */ blockdiag(st_matrix("`S_final'"), /* */ st_matrix("`S_`t''"))) } // 2. Create S_IV if `k_iv'>0 { tempname S_iv S_iv_k local c_S = colsof(`S_final') mat `S_iv' = J(`k_iv', `c_S', 0) forvalues k=1/`k_iv' { forvalues t=1/`tmax' { mat `S_iv'[`k', `k_gmm'*`t'*`tmax'+(`t'-1)*`k_iv'*`tmax'+`t' + (`k'-1)*`tmax']=1 } } mat `S_final' = `S_final' \ `S_iv' } // Return matrix S return matrix S = `S_final' end /*============================================================================== DEFINE MATA FUNCTIONS 1) blockdiag() ==============================================================================*/ mata: mata clear real matrix blockdiag(real matrix A, real matrix B) { real matrix result real scalar ra, ca, rb, cb ra = rows(A) ca = cols(A) rb = rows(B) cb = cols(B) result = J(ra + rb, ca + cb, 0) result[1..ra, 1..ca] = A result[(ra+1)..(ra+rb), (ca+1)..(ca+cb)] = B return(result) } /*============================================================================== 2) data2MataMat() ==============================================================================*/ /*============================================================================== 2.1 data2MataMat() Input: rowvector : include varnames stored in local macro k : number of columns of rowvector T : number of time period Output: MataMat : Tx(kN) data matrix ==============================================================================*/ real matrix function data2MataMat(string rowvector M_vars, real scalar k, real scalar T) { // Create varlist in wide data string rowvector allvars allvars = J(1, k*T, "") for (j=1; j<=k; j++) { for (t=1; t<=T; t++) { allvars[(j-1)*T + t] = M_vars[j] + strofreal(t) } } // Read data from STATA real matrix M_data //st_view(M_data = ., ., allvars) M_data = st_data(., allvars) N = rows(M_data) // Create empty MataMat: T x (k*N) real matrix MataMat MataMat = J(T, k*N, .) // Fill data for (i=1; i<=N; i++) { Vi = J(T, k, .) for (j=1; j<=k; j++) { Vi[., j] = (M_data[i, (j-1)*T + 1 .. j*T])' } col1 = (i-1)*k + 1 col2 = i*k MataMat[., col1..col2] = Vi } return(MataMat) } /*============================================================================== 2.2 get_MataMat_i() ~ Take Mata matrix Txk for individual i, i=1,N ==============================================================================*/ real matrix function get_MataMat_i(real matrix MataMat, real scalar i, real scalar k) { col1 = (i-1)*k + 1 col2 = i*k return(MataMat[., col1..col2]) } /*============================================================================== 3) Wmaker() ==============================================================================*/ real matrix Wmaker(string rowvector Wvars, /* */ real scalar pow_max,/* */ real scalar w_pow, /* */ real scalar type) { string rowvector Wvars1 Wvars1 = Wvars + "1" // name + 1 = name1 // st_view(Wdata = ., ., W_t1vars) data = st_data(., Wvars1) N = rows(data) if (type==2) { W = data :^w_pow // W[data :== 0] = 0 } else { W = data :^ J(N, 1, 0..(pow_max-1)) } return(W) } /*============================================================================== 4) combs_maker ==============================================================================*/ function combs_maker(real scalar L, real scalar R) { real matrix result real scalar n_comb, i, j, k real rowvector current n_comb = comb(R, L) result = J(n_comb, L, .) // 1st combination: [1, 2, ..., L] current = J(1, L, .) for (j = 1; j <= L; j++) { current[j] = j } result[1, .] = current // other combinations k = 1 while (k < n_comb) { // Finding from right to left i = L while (i >= 1 && current[i] == R - L + i) { i-- } if (i >= 1) { current[i] = current[i] + 1 for (j = i + 1; j <= L; j++) { current[j] = current[j-1] + 1 } k++ result[k, .] = current } } return(result) } /*============================================================================== 5) Fe_selector ==============================================================================*/ transmorphic function Fe_selector(real scalar L, real matrix F_hat) { real scalar R, n_comb, p real matrix combs transmorphic Fe_sel R = cols(F_hat) n_comb = comb(R, L) // Store results in array Fe_sel = asarray_create("real", 1) combs = combs_maker(L, R) for (p = 1; p <= n_comb; p++) { asarray(Fe_sel, p, F_hat[., combs[p, .]]) } return(Fe_sel) } /*============================================================================== 6) estimate() ==============================================================================*/ real matrix estimate( /* input */ real scalar small, real scalar balance, real scalar T, real scalar l_max, real scalar pow_max, real scalar w_pow, real scalar N, real scalar seed, real scalar stat_vl, real scalar zeta, real scalar iden, real scalar rob, real scalar step, real scalar rho, real scalar cons, real scalar type, real scalar method, // regu = 1, bss = 2 real scalar clust, // clust = 0 | 1 string scalar stata_clust, string scalar stata_vars, // "local_name" , not "`local_name'" string scalar stata_zvars, string scalar stata_V, string scalar stata_M_W, string scalar stata_S, // "`local_name'" string scalar stata_H, /* ouput */ string scalar stata_b, // "`local_name'" string scalar stata_Vb, string scalar stata_theta, string scalar stata_Vtheta, string scalar stata_Fe_hat, string scalar stata_j, string scalar stata_df_m, string scalar stata_wald, string scalar stata_waldp, string scalar stata_bic, string scalar stata_j_df, string scalar stata_j_s, string scalar stata_j_p, string scalar stata_le, string scalar stata_d, string scalar stata_r_ga, string scalar stata_G, string scalar stata_Ti ) { // -- M_vars = M_depvar, M_indepvars vars = tokens(st_local(stata_vars)) k1 = length(vars) k = k1 - 1 M_vars = data2MataMat(vars, k1, T) // Truy xuất M_vars_i Tx(k+1) matrix for individual i //M_vars_i = get_MataMat_i(M_vars, i, k1) // -- M_zvars, Z_i, z_i ----------------------------------- zvars = tokens(st_local(stata_zvars)) k_z = length(zvars) M_zvars = data2MataMat(zvars, k_z, T) d=rows(vec(get_MataMat_i(M_zvars, 1, k_z))) S = st_matrix(stata_S) I = I(T) M_Z = asarray_create("real") for (i=1; i<=N; i++) { M_zvarsi = get_MataMat_i(M_zvars, i, k_z) // T x k_z zi = vec(M_zvarsi) Zi = (S * (I # zi))' // T x zeta asarray(M_Z, i, Zi) } // -- M_Zvars ----------------------------------- M_Zvars = J(zeta, k1, 0) for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) // T x k1 Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zvars = M_Zvars + M_Zvarsi } // M_Zvars = M_Zvars / N // zeta x k1 M_Zvars = M_Zvars // zeta x k1 M_Zy = M_Zvars[,1] // zeta x 1 M_ZX = M_Zvars[,2..k1] // zeta x k // -- cluster var ----------------------------------- if (clust==1) { clustvar = tokens(st_local(stata_clust)) clustvar = clustvar + "1" g_panel = st_data(., clustvar) N_G = max(g_panel) } // -- Ti var ----------------------------------- if (balance==0) { Tivar = tokens(st_local(stata_Ti)) Tivar = Tivar + "1" Ti = st_data(., Tivar) obs = sum(Ti) } // -- initial GMM weigth ----------------------------------- B = I(zeta) if (iden==1) { C = B } else { C = J(zeta, zeta, 0) for (i=1; i<=N; i++) { Zi = asarray(M_Z, i) // T x zeta ZiZi = Zi'*Zi // zeta x zeta C = C + ZiZi // Z'Z } // C = C / N C = invsym((C+C')/2) // (Z'Z)^-1 } C_int = C // -- M_V ----------------------------------- V = tokens(st_local(stata_V)) k_v = length(V) M_V = data2MataMat(V, k_v, T) // -- Observed factors --------------------------- H = tokens(st_local(stata_H)) k_h = length(H) if (k_h>0) { M_H = get_MataMat_i(data2MataMat(H, k_h, T), 1, k_h) // optimal needed } else { M_H=J(T,1,0) } if (balance==1) { M_H = M_H * N } else { M_H = M_H * obs } // -- M_W ----------------------------------- Wvars = tokens(st_local(stata_M_W)) M_W = Wmaker(Wvars, pow_max, w_pow, type) r_w = cols(M_W) F_hat = J(T, k_v*r_w, 0) if (balance==1) { for (i=1; i<=N; i++) { M_Vi = get_MataMat_i(M_V, i, k_v) // Txk_v M_Wi = M_W[i,] F_hat = F_hat + M_Vi # M_Wi } } else { for (i=1; i<=N; i++) { M_Vi = get_MataMat_i(M_V, i, k_v) // Txk_v M_Wi = M_W[i,] F_hat = F_hat + M_Vi # M_Wi * (Ti[i]/obs) // Ti/obs } } /*================================================================= 2. Estimate facto proxies =================================================================*/ if (method==1) { // F_hat = F_hat/N // rademach rseed(seed) rademach = (runiform(N, 1) :< 0.5)* -2 :+ 1 M_WT = M_W, rademach // l_max + 1 = T r_wT = cols(M_WT) F_hatT = J(T, k_v*r_wT, 0) if (balance==1) { for (i=1; i<=N; i++) { M_Vi = get_MataMat_i(M_V, i, k_v) // Txk_v M_WTi = M_WT[i,] F_hatT = F_hatT + M_Vi # M_WTi } } else { for (i=1; i<=N; i++) { M_Vi = get_MataMat_i(M_V, i, k_v) // Txk_v M_WTi = M_WT[i,] F_hatT = F_hatT + M_Vi # M_WTi *(Ti[i]/obs) } } // F_hatT = F_hatT/N A = F_hat*F_hat' A = (A + A')/2 B = F_hatT*F_hatT' B = (B + B')/2 symeigensystem(A, eigenvector_A=., eigenvalue_A=.) symeigensystem(B, eigenvector_ev=., eigenvalue_ev=.) eigenvalue_ev = eigenvalue_ev' eigenvalue_ev = sort(eigenvalue_ev, -1) eigenvalue_ev = eigenvalue_ev' if (stat_vl==1) { // ER statistic er = eigenvalue_ev[1..T-1] :/ eigenvalue_ev[2..T] er_max = er[1] le = 1 for (i = 2; i <= cols(er); i++) { if (er[i] > er_max) { er_max = er[i] le = i } } } else { // GR statistic G = J(1, T, .) for (r=0; r<=T-1; r++) { G[r+1] = rowsum(eigenvalue_ev[1,(r+1)..T]) } gr = J(1, T-2, .) for (r=1; r<=T-2; r++) { gr[r] = (ln(G[r] / G[r+1])) / (ln(G[r+1] / G[r+2])) } gr_max = gr[1] le = 1 n_gr = cols(gr) for (i = 2; i <= n_gr; i++) { if (gr[i] > gr_max) { gr_max = gr[i] le = i } } } if (balance==1) { Fe_hat = -sqrt(T) * eigenvector_A[,1..le] * N } else { Fe_hat = -sqrt(T) * eigenvector_A[,1..le] * obs } } else { // Best-Subset Selection: lowest BIC R = cols(F_hat) if (l_max>R) { // printf("\n{text}Lmax must be less than or equal T-1") // printf("\n{text}Let Lmax = %f", T-1) l_max = R } A_bic = asarray_create("real") A_Fe = asarray_create("real") idx = 0 for (L = 1; L <= l_max; L++) { n_comb = comb(R, L) Fe_L = Fe_selector(L, F_hat) for (m = 1; m <= n_comb; m++) { idx = idx + 1 Fe_L_m = asarray(Fe_L, m) if (k_h>0) { XX = S*(Fe_L_m # I(d)), S*(M_H # I(d)) } else { XX = S*(Fe_L_m # I(d)) } Zy = M_Zy ZX = M_ZX, XX ZXCZX = ZX'*C*ZX ZXCZX = (ZXCZX + ZXCZX')/2 // Vtheta1 = invsym(ZXCZX)/N Vtheta1 = invsym(ZXCZX) Vtheta1 = (Vtheta1 + Vtheta1')/2 // theta1 = N*Vtheta1*ZX'*C*Zy theta1 = Vtheta1*ZX'*C*Zy n_c = rows(theta1) r_ga = rank(ZX) if (zeta < r_ga) { BIC = 10^9 } else { b1 = theta1[1..k,1] g1 = theta1[k1..n_c,1] df_j = zeta - r_ga Delta = J(zeta, zeta, 0) if (balance==1) { XX1 = XX/N if (clust==1) { /* i g_panel 1 1 g_panel[1]=1 <-> g=1 2 2 g_panel[2]=2 <-> g=2 3 1 g_panel[3]=1 <-> g=1 4 2 g_panel[4]=2 <-> g=2 5 0 g_panel[5]=0 <-> missing */ Mg = J(N_G, zeta, 0) // G x zeta for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Zei = M_Zyi - M_ZXi*b1 - XX1*g1 // zeta x 1 gi = g_panel[i] if (gi > 0) { Mg[gi,] = Mg[gi,] + Zei' // 1 x zeta } } for (g=1; g<=N_G; g++) { Delta = Delta + Mg[g,]'*Mg[g,] } // Delta = Delta/N_G } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) M_Zvarsi = Zi'*M_varsi M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Zei = M_Zyi - M_ZXi*b1 - XX1*g1 Delta = Delta + Zei*Zei' } // Delta = Delta / N } } else { if (clust==1) { Mg = J(N_G, zeta, 0) // G x zeta for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX *(Ti[i]/obs) // Hadamard Zei = M_Zyi - M_ZXi*b1 - XX1*g1 // zeta x 1 gi = g_panel[i] if (gi > 0) { Mg[gi,] = Mg[gi,] + Zei' // 1 x zeta } } for (g=1; g<=N_G; g++) { Delta = Delta + Mg[g,]'*Mg[g,] } // Delta = Delta/N_G } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) M_Zvarsi = Zi'*M_varsi M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX * (Ti[i]/obs) // XX1 = XX/N Zei = M_Zyi - M_ZXi*b1 - XX1*g1 Delta = Delta + Zei*Zei' } // Delta = Delta / N } } Delta = (Delta + Delta')/2 if (step==1) { // =========== GMM 1 step =========== C = invsym(Delta) Ze1 = Zy-ZX*theta1 J_s = Ze1'*C*Ze1 BIC = J_s - (log(N)/T^0.3)*rho*df_j } else { // =========== GMM 2 step =========== C = invsym(Delta) XZCZX = ZX'*C*ZX XZCZX = (XZCZX + XZCZX')/2 Vtheta2 = invsym(XZCZX) Vtheta2 = (Vtheta2+ Vtheta2')/2 theta2 = Vtheta2*ZX'*C*Zy n_c = rows(theta2) b = theta2[1..k,1] Ze2 = Zy-ZX*theta2 J_s = Ze2'*C*Ze2 BIC = J_s - (log(N)/T^0.3)*rho*df_j } } // Store bic and Fe_sel asarray(A_bic, idx, BIC) asarray(A_Fe, idx, Fe_L_m) } } // Find BIC min and Fe_hat min_bic = asarray(A_bic, 1) best_idx = 1 n_models = 0 for (L = 1; L <= l_max; L++) { n_models = n_models + comb(R, L) } for (i = 2; i <= n_models; i++) { if (asarray(A_bic, i) < min_bic) { min_bic = asarray(A_bic, i) best_idx = i } } Fe_hat = asarray(A_Fe, best_idx) le = cols(Fe_hat) // balance==1: sum-F_hat's columns -> Fe_hat -> no need to divide by N if (balance==0) { Fe_hat = Fe_hat*obs } } /*================================================================= 3. Perform GMM =================================================================*/ C = C_int if (k_h>0) { XX = S*(Fe_hat # I(d)), S*(M_H # I(d)) } else { XX = S*(Fe_hat # I(d)) } Zy = M_Zy ZX = M_ZX, XX ZXCZX = ZX'*C*ZX ZXCZX = (ZXCZX + ZXCZX')/2 Vtheta1 = invsym(ZXCZX) Vtheta1 = (Vtheta1 + Vtheta1')/2 theta1 = Vtheta1*ZX'*C*Zy n_c = rows(theta1) r_ga = rank(ZX) if (zeta < r_ga) { printf("\n{err}Error: GMM under-identified!\n") _error(3498, "Number of instruments (" + strofreal(zeta) + ") < number of parameters (" + strofreal(r_ga) + ")") } b1 = theta1[1::k,1] g1 = theta1[k1::n_c,1] df_j = zeta - r_ga // Delta = Z'OmegaZ = Z'Block.diag(ei*ei')Z = sum_i (Ze_i*Ze_i') Delta = J(zeta, zeta, 0) // zeta x zeta = K x K if (balance==1) { XX1 = XX/N if (clust == 1) { /* i g_panel 1 1 g_panel[1]=1 <-> g=1 2 2 g_panel[2]=2 <-> g=2 3 1 g_panel[3]=1 <-> g=1 4 2 g_panel[4]=2 <-> g=2 */ Mg = J(N_G, zeta, 0) // N_G x zeta for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Zei = M_Zyi - M_ZXi*b1 - XX1*g1 // zeta x 1 gi = g_panel[i] if (gi > 0) { Mg[gi,] = Mg[gi,] + Zei' // 1 x zeta } } for (g=1; g<=N_G; g++) { Delta = Delta + Mg[g,]'*Mg[g,] } } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Zei = M_Zyi - M_ZXi*b1 - XX1*g1 Delta = Delta + Zei*Zei' } } } else { if (clust == 1) { Mg = J(N_G, zeta, 0) // N_G x zeta for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX * (Ti[i]/obs) // hadamard Zei = M_Zyi - M_ZXi*b1 - XX1*g1 // zeta x 1 gi = g_panel[i] if (gi > 0) { Mg[gi,] = Mg[gi,] + Zei' // 1 x zeta } } for (g=1; g<=N_G; g++) { Delta = Delta + Mg[g,]'*Mg[g,] } } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX * (Ti[i]/obs) // hadamard Zei = M_Zyi - M_ZXi*b1 - XX1*g1 Delta = Delta + Zei*Zei' } // Delta = Delta / N } } Delta = (Delta + Delta')/2 // GMM 1-step allaway using robust SE cause conventional SE can't be estimated Vtheta1r = Vtheta1*(ZX'*C*Delta*C*ZX)*Vtheta1 Vtheta1r = (Vtheta1r + Vtheta1r')/2 if (step==1) { // =========== GMM 1 step ============================ if (rob==1 | clust==1) { Vtheta = Vtheta1r V1 = Vtheta1r[1::k, 1::k] C = invsym(Delta) } else { /* sigma2 = mean(eit^2)/(NT-n_c) // <- can not be estimated Z'Z = sum_(i=1..N) (Zi'*Zi) Vtheta = sigma2*Vtheta1*ZX'*C*Z'Z*C*ZX*Vtheta1 V1 = Vtheta[1::k, 1::k] */ Vtheta = Vtheta1r V1 = Vtheta1r[1::k, 1::k] C = invsym(Delta) } Ze1 = Zy-ZX*theta1 // e1 = Z'e J_s = Ze1'*C*Ze1 J_p = 1 - chi2(df_j, J_s) BIC = J_s - (log(N)/T^0.3)*rho*df_j b = b1 V = V1 theta = theta1 } else { // =========== GMM 2 step ============================ C = invsym(Delta) // (Z'OmegaZ)^-1 XZCZX = ZX'*C*ZX XZCZX = (XZCZX + XZCZX')/2 Vtheta2 = invsym(XZCZX) Vtheta2 = (Vtheta2+ Vtheta2')/2 theta2 = Vtheta2*ZX'*C*Zy n_c = rows(theta2) b = theta2[1::k,1] Ze2 = Zy-ZX*theta2 if (rob==1 & clust==0) { /* Windmeijer (2005) corection D = -(ZX'*C*ZX)^-1*ZX'*C*P*C*ZE = -N*Vtheta2*ZX'*C*P*C*ZE C = (Z'e*e'Z)^-1 = (Ze*Ze')^-1 P*C*ZE = -sum (e1i'Zi*C*Ze2*ZXi + Zi'e1i*Ze2'*C*ZXi) = -sum (Ze1i'*C*Ze2*ZXi + Ze1i*Ze2'*C*ZXi) V_W = Vtheta2 + D*Vtheta2 + Vtheta2*D' + D*Vtheta1r*D' */ D = J(n_c, n_c, 0) PCZE2 = J(zeta, n_c, 0) H = J(n_c, n_c, 0) if (balance==1) { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi= Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Ze1i = M_Zyi - M_ZXi*b1 - XX1*g1 M_ZXi = M_ZXi, XX1 PCZE2 = PCZE2 + Ze1i'*C*Ze2*M_ZXi + Ze1i*Ze2'*C*M_ZXi } } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi= Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX * (Ti[i]/obs) // Hadamard Ze1i = M_Zyi - M_ZXi*b1 - XX1*g1 M_ZXi = M_ZXi, XX1 PCZE2 = PCZE2 + Ze1i'*C*Ze2*M_ZXi + Ze1i*Ze2'*C*M_ZXi } } // 20x20x(20x40)x(40x40)x(40x20) = 20x20 D = Vtheta2*ZX'*C*PCZE2 V_W = Vtheta2 + D*Vtheta2 + Vtheta2*D' + D*Vtheta1r*D' V_W = (V_W + V_W')/2 V = V_W[1::k,1::k] Vtheta = V_W } else if (clust==1) { Ze1g = J(N_G, zeta, 0) M_ZXg = J(1, N_G, NULL) g = . for (g=1; g<=N_G; g++) { M_ZXg[g] = &(J(zeta, n_c, 0)) } D = J(n_c, n_c, 0) PCZE2 = J(zeta, n_c, 0) if (balance==1) { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] Ze1i = M_Zyi - M_ZXi*b1 - XX1*g1 M_ZXi = M_ZXi, XX1 gi = g_panel[i] if (gi > 0) { // sum_(i in g) (e1i'*Zi) 1xzeta Ze1g[gi,] = Ze1g[gi,] + Ze1i' // sum_(i in g) (Zi'*Xi) zetaxk *M_ZXg[gi] = *M_ZXg[gi] + M_ZXi } } } else { for (i=1; i<=N; i++) { M_varsi = get_MataMat_i(M_vars, i, k1) Zi = asarray(M_Z, i) // T x zeta M_Zvarsi = Zi'*M_varsi // zeta x k1 M_Zyi = M_Zvarsi[, 1] M_ZXi = M_Zvarsi[, 2..k1] XX1 = XX * (Ti[i]/obs) // Hadamard Ze1i = M_Zyi - M_ZXi*b1 - XX1*g1 M_ZXi = M_ZXi, XX1 gi = g_panel[i] if (gi > 0) { Ze1g[gi,] = Ze1g[gi,] + Ze1i' *M_ZXg[gi] = *M_ZXg[gi] + M_ZXi } } } for (g=1; g<=N_G; g++) { ZXg = *M_ZXg[g] PCZE2 = PCZE2 + Ze1g[g,]*C*Ze2*ZXg + Ze1g[g,]'*Ze2'*C*ZXg } D = Vtheta2*ZX'*C*PCZE2 V_W = Vtheta2 + D*Vtheta2 + Vtheta2*D' + D*Vtheta1r*D' V_W = (V_W + V_W')/2 V = V_W[1::k,1::k] Vtheta = V_W } else { V = Vtheta2[1::k,1::k] Vtheta = Vtheta2 } theta = theta2 // J_s = N*Ze2'*C*Ze2 J_s = Ze2'*C*Ze2 J_p = 1 - chi2(df_j, J_s) BIC = J_s - (log(N)/T^0.3)*rho*df_j } // Small sample adjustment if (small == 1) { if (clust==1) { V = V * (N-1)/(N-r_ga) * (N_G/(N_G-1)) Vtheta = Vtheta * (N-1)/(N-r_ga) * (N_G/(N_G-1)) } else { V = V * (N-1)/(N-r_ga) * (N/(N-1)) Vtheta = Vtheta * (N-1)/(N-r_ga) * (N/(N-1)) } } // Wald test if (cons==1) { R = I(n_c) // R = ma trận đơn vị R[k, k]=0 // intercept q = J(n_c, 1, 0) // q = vector 0 df_m = r_ga - 1 wald = (R*theta - q)' * pinv(R*Vtheta*R') * (R*theta - q) if (small==1) { df2 = N-r_ga waldp = 1 - F(df_m, df2, wald) } else { waldp = 1 - chi2(df_m, wald) } } else { R = I(n_c) // R = ma trận đơn vị q = J(n_c, 1, 0) // q = vector 0 df_m = r_ga wald = (R*theta - q)' * invsym(R*Vtheta*R') * (R*theta - q) if (small==1) { df2 = N-r_ga waldp = 1 - F(df_m, df2, wald) } else { waldp = 1 - chi2(df_m, wald) } } /*================================================================= 4. Post and store results =================================================================*/ // Export to STATA b = b' if (balance==1) { Fe_hat = Fe_hat/N } else { Fe_hat = Fe_hat/obs } st_matrix(stata_b, b) st_matrix(stata_Vb, V) st_matrix(stata_theta, theta) st_matrix(stata_Vtheta, Vtheta) st_matrix(stata_Fe_hat, Fe_hat) st_numscalar(stata_j, zeta) st_numscalar(stata_df_m, df_m) st_numscalar(stata_wald, wald) st_numscalar(stata_waldp, waldp) st_numscalar(stata_bic, BIC) st_numscalar(stata_j_df, df_j) st_numscalar(stata_j_s, J_s) st_numscalar(stata_j_p, J_p) st_numscalar(stata_le, le) st_numscalar(stata_d, d) st_numscalar(stata_r_ga, r_ga) st_numscalar(stata_G, N_G) } end