-
Notifications
You must be signed in to change notification settings - Fork 3
/
mtefe_gendata.ado
255 lines (233 loc) · 7.34 KB
/
mtefe_gendata.ado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
*! mtefe_gendata v1.82 28may2018
* Author: Martin Eckhoff Andresen
* This program is part of the mtefe package.
cap program drop mtefe_gendata
{
program define mtefe_gendata, rclass
version 13.0
syntax , [parameters(namelist min=4 max=5) fixedeffects(namelist min=3 max=3) /*
*/ obs(integer 5000) POLynomial(integer 0) link(string) districts(integer 0)]
qui {
clear
//Check input
if "`link'"!="" {
if !inlist("`link'","lpm","probit") {
noi di in red "Link() must be probit or lpm."
exit 301
}
}
else loc link probit
tempname U0 U1 V index gamma beta0 beta1 pi pi0 pi1
if "`parameters'"!="" {
gettoken gammaname rest: parameters
confirm matrix `gammaname'
mat `gamma'=`gammaname'
gettoken beta0name rest: rest
confirm matrix `beta0name'
mat `beta0'=`beta0name'
gettoken beta1name rest: rest
confirm matrix `beta1name'
mat `beta1'=`beta1name'
if colsof(`gamma')!=colsof(`beta1')+1|colsof(`beta1')!=colsof(`beta0')|colsof(`beta1')<`=`numX'+1' {
noi di in red "Matrix beta0, beta1 or gamma of wrong dimensions - should be 1 x K for betas and 1 x K+1 for gamma."
exit 301
}
local numpi: word count `rest'
if `numpi'==1&`polynomial'!=0|`numpi'==2&`polynomial'<=0 {
noi di in red "Specify either variance-covariance matrix for joint normal errors or two matrices for the pi-parameters if using the polynomial model."
exit 301
}
if `polynomial'==0 {
confirm matrix `rest'
mat `pi'=`rest'
if colsof(`pi')!=3|rowsof(`pi')!=3 {
noi di in red "When using joint normal errors, matrix pi must be 3 x 3."
exit 301
}
}
if `polynomial'!=0 {
tempname pi0name pi1name
gettoken pi0name pi1name: rest
confirm matrix `pi0name' `pi1name'
mat `pi0'=`pi0name'
mat `pi1'=`pi1name'
if colsof(`pi1')!=`polynomial'|colsof(`pi0')!=`polynomial' {
noi di in red "Columns of pi1 and pi0 must match degree of polynomial."
exit 301
}
}
}
else {
if !inlist(`polynomial',0,2) {
noi di in red "When using default parameters, use polynomial of degree 0 (normal) or 2."
exit 301
}
if "`link'"=="lpm" mat `gamma'=[ 0.015 , -0.01 , 0.00025 , `=0.5-0.015*40+0.01*15-0.00025*305']
else mat `gamma'=[ -0.125 , -0.08 , 0.002 , `=0.125*40+0.08*15-0.002*305']
mat `beta0'=[ 0.025 , -0.0004 , 3.2]
mat `beta1'=[ 0.01 , 0 , 3.6 ]
mat `pi'= [ 0.5 , 0.3 , -0.1 \ 0.3 , 0.5, -0.5 \ -0.1 , -0.5 , 1 ]
mat `pi1'= [ 0.5 , -0.1 ]
mat `pi0'= [ 2 , -1 ]
}
if "`fixedeffects'"!="" {
tempname fix0 fix1 avgDist
gettoken fix0name rest: fixedeffects
confirm matrix `fix0name'
mat `fix0'=`fix0name'
loc districts=colsof(`fix0')
gettoken fix1name rest: rest
confirm matrix `fix1name'
mat `fix1'=`fix1name'
if colsof(`fix1')!=`districts' {
noi di in red "Fixed effects matrices must be same dimensions - 1 x G."
exit 301
}
confirm matrix `rest'
mat `avgDist'=`rest'
if colsof(`avgDist')!=`districts' {
noi di in red "Fixed effects matrices must be same dimensions - 1 x G."
exit 301
}
}
else if `districts'>0 {
set obs `districts'
tempname fix0 fix1 avgDist cov means
mat `cov'= [ 0.1 , 0.05 , -0.05 \ 0.05 , 0.1 , -0.1 \ -0.05 , -0.1 , 10 ]
drawnorm `fix0' `fix1' `avgDist', cov(`cov')
foreach state in fix0 fix1 avgDist {
replace ``state''=0 in 1
mkmat ``state'', matrix(``state'')
mat ``state''=``state'''
}
}
//Generate X, Z
clear
set obs `obs'
if `districts'>0 {
tempname fix
gen district=ceil(`districts'*runiform())
fvexpand i.district
loc districtlist `r(varlist)'
foreach state in fix0 fix1 avgDist {
mat colnames ``state''=`districtlist'
}
mat score `avgDist'=`avgDist'
gen distCol=`avgDist'+rnormal(40,10)
}
else gen distCol=rnormal(0,10)+40
gen exp=floor(31*runiform())
gen exp2=exp^2
//Combine coefs, include fixed effects
if `districts'>0 {
foreach state in 0 1 {
mat `beta`state''=`beta`state''[1,1..colsof(`beta`state'')-1],`fix`state'',`beta`state''[1,colsof(`beta`state'')]
}
}
mat colnames `gamma'=distCol exp exp2 _cons
mat colnames `beta0'=exp exp2 `districtlist' _cons
mat colnames `beta1'=exp exp2 `districtlist' _cons
//Create errors
tempname U0 U1 V Ud
if `polynomial'==0 {
drawnorm `U0' `U1' `V', cov(`pi')
gen `Ud'=normal(`V')
}
if `polynomial'>0 {
gen `V'=rnormal()
gen `Ud'=normal(`V')
loc cons1=0
loc cons0=0
forvalues p=1/`polynomial' {
tempname p`p'
loc names `names' `p`p''
loc cons1=`cons1'-`pi1'[1,`p']*(1/(`p'+1))
loc cons0=`cons0'-`pi0'[1,`p']*(1/(`p'+1))
gen `p`p''=`Ud'^`p'
}
mat `pi1'=`pi1',`cons1'
mat `pi0'=`pi0',`cons0'
mat colnames `pi1'=`names' _cons
mat colnames `pi0'=`names' _cons
mat score `U1'=`pi1'
mat score `U0'=`pi0'
replace `U1'=`U1'+rnormal(0,0.2)
replace `U0'=`U0'+rnormal(0,0.2)
}
//determine first stage
tempname index
mat score `index'=`gamma'
if "`link'"=="probit" gen col=`index'>`V'
if "`link'"=="lpm" gen col=`index'>`Ud'
//Determine outomes
tempname lwage0 lwage1
mat score `lwage0'=`beta0'
mat score `lwage1'=`beta1'
replace `lwage0'=`lwage0'+`U0'
replace `lwage1'=`lwage1'+`U1'
gen lwage=col*`lwage1'+(1-col)*`lwage0'
//generate MTE
tempname support temp mtexs beta10pi mte
forvalues i=1/99 {
mat `support'=[nullmat(`support'),`=round(`i'/100,0.01)' ]
loc mtenames `mtenames' u`i'
}
mat `mtexs'=[ 15 \ 305 ]
if `districts'>0 {
forvalues i=1/`districts' {
mat `mtexs'=[nullmat(`mtexs') \ `=1/`districts'' ]
}
}
mat `mtexs'=[nullmat(`mtexs') \ 1]
if `polynomial'==0 {
mat `beta10pi'=`beta1'-`beta0',`pi'[3,2]-`pi'[3,1]
mata: mtefecalc_small(st_matrix("`beta10pi'"),invnormal(st_matrix("`support'")),st_matrix("`mtexs'"),"`mte'")
}
else {
tempname S tempsup
forvalues k=1/`polynomial' {
if `k'==1 mat `tempsup'=`support'
else mat `tempsup'=hadamard(`tempsup',`support')
mat `S'=[nullmat(`S') \ `tempsup']
}
mat `beta10pi'=`beta1'[1,1..`=colsof(`beta1')-1']-`beta0'[1,1..`=colsof(`beta0')-1'],`beta1'[1,`=colsof(`beta1')']-`beta0'[1,`=colsof(`beta0')']+`pi1'[1,`=`polynomial'+1']-`pi0'[1,`=`polynomial'+1'],`pi1'[1,1..`polynomial']-`pi0'[1,1..`polynomial']
mata: mtefecalc_small(st_matrix("`beta10pi'"),st_matrix("`S'"),st_matrix("`mtexs'"),"`mte'")
}
mat colnames `mte'=`mtenames'
//post parameters
return matrix gamma=`gamma'
return matrix beta1=`beta1'
return matrix beta0=`beta0'
return matrix mte=`mte'
if `polynomial'>0 {
forvalues state=0/1 {
tempname retpi`state'
mat `retpi`state''=`pi`state''[1,1..`polynomial']
return matrix pi`state'=`retpi`state''
}
}
else return matrix pi=`pi'
/*gen lwage0=`lwage0'
gen lwage1=`lwage1'
gen U1=`U1'
gen U0=`U0'
gen Ud=`Ud'
*/
}
end
}
mata:
mata clear
void mtefecalc_small(real matrix beta10pi, real matrix S, real matrix mtexs, ///
string scalar mtename)
{
real matrix fullS
real scalar i
real vector mte
fullS=J(rows(mtexs),cols(S),.)
for (i=1;i<=cols(S);i++) fullS[.,i]=mtexs
fullS=fullS \ S
mte=beta10pi*fullS
st_matrix(mtename,mte)
}
end