program define arc9 version 9.10 /* ** by Jean Roth , jroth@nber.org This program uses the NBER TAXSIM model to calculate US and state income tax liabilities. It calls an external program nc send data (in ASCII) to the NBER server and obtain the calculated liabilities. net from http://www.nber.org/stata net describe taxsim9 net install taxsim9 */ display "begin arc9.ado on $S_DATE (version 9.10)" syntax [, Full Secondary Wages Interest Long Output(string) Debug X51 PLAN(integer 0) PLANVal(real 0) Replace local version(string)] if `"`replace'"' == `"replace"' { display "TAXSIM results will be merged to original file" } ** If state doesn't exist, add to original dataset for later merging. capture confirm variable state if _rc { display "Variable state not found in dataset." display "Generating state = 0 to return federal taxes only." generate state = 0 } if `"`x51'"' == `"x51"' { display "Setting state identifier to -1 for confidentiality" display "Returning 51 records for every record received" capture drop statet generate statet = state replace state = -1 } *preserve if `"`debug'"' != `"debug"' { tempfile outfile infile ftp msg } else { display "Saving input to FORTRAN TAXSIM as txpydata.raw " local outfile txpydata.raw display "Saving output from FORTRAN TAXSIM as results.raw " local infile results.raw capture erase txpydata.raw capture erase results.raw } capture { rm `outfile' } capture { rm `infile' } capture { rm ftp.txt } capture ( rm msg.txt } if length(`"`output'"') == 0 { local output taxsim_out } display "TAXSIM results will be saved in `output'.dta" capture drop taxsimid if _rc==0 { display "Dropping taxsim id." } preserve capture generate taxsimid = _n ** mtr is marginal is tax rate. local mtr 85 ** idtl is output. 0 is basic local idtl 0 #delimit ; ** marginal tax rate options ; if `"`secondary'"' == `"secondary"' { ; local mtr 86 ; display "Marginal rate with respect to secondary earner"; } ; if `"`wages'"' == `"wages"' { ; local mtr 11 ; display "Marginal rate with respect to overall earnings"; } ; if `"`interest'"' == `"interest"' { ; local mtr 14 ; display "Marginal rate with respect to interest income"; } ; if `"`long'"' == `"long"' { ; local mtr 70 ; display "Marginal rate with respect to long term gains"; } ; if `"`full'"' == `"full"' { ; local idtl 2 ; local addvars v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31 v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 ; display "Full Intermediate Calculations Requested"; } ; if "`mtr'" == "85" { ; display "Marginal rate with respect to primary earner"; } ; if "`idtl'" == "0" { ; display "Basic output"; } ; if `plan' != 0 {; display "Tax law modified according to TAXSIM plan " `plan'; }; if `planval' != 0 {; display "Modified tax parameter is " `planval'; }; #delimit cr ** Checking data sent to taxsim for validity ** Checking for observations prior to variables for better error message. if _N==0 { display "Aborting: No observations in data set" exit } local must_exist year mstat foreach X of local must_exist { capture confirm var `X' if _rc > 0 { display "Aborting: Variable `X' not found in data file" exit } capture assert missing(`X') if _rc == 0 { display "Aborting: All values of variable `X' are missing." exit } } #delimit ; local invars year state mstat depx agex pwages swages dividends otherprop pensions gssi transfers rentpaid proptax otheritem childcare ui depchild mortgage ltcg stcg; #delimit cr foreach X of local invars { capture confirm var `X' if _rc > 0 { display "Variable `X' is not in the dataset. Generating `X' = 0 " generate `X' = 0 } capture assert missing(`X') if _rc == 0 { display "All values of variable `X' are missing. Replacing `X' = 0 " replace `X' = 0 } } *display "Checking variables are numeric" foreach X of local invars { capture confirm numeric variable `X' if _rc > 0 { display "Aborting: Variable `X' is not numeric. See help tostring." exit } } scalar startobs = _N scalar obs0=_N quietly drop if year<1960 | year>2023 | year==. drop_message obs0-_N year quietly drop if state<-1 | state > 51 | missing(state) drop_message obs0-_N state ** The maximum value of year will need updating annually quietly drop if (year<1977|year>2016) & state !=0 drop_message obs0-_N state-and-year-combination quietly drop if depx<0 | depx>999 drop_message obs0-_N depx quietly drop if mstat<1 | ( mstat>4 & mstat<7 ) | mstat>8 drop_message obs0-_N mstat quietly drop if agex<0 | agex>12000 drop_message obs0-_N agex quietly drop if depchild<0|depchild>999999 drop_message obs0-_N depchild ** Replacing spouses wage=0 if not filing jointly quietly replace swages=0 if mstat!=2 #delimit ; local positive_items dividends pensions gssi transfers rentpaid proptax otheritem childcare ui mortgage; #delimit cr scalar obs0=_N foreach X in `positive_items' swage pwage { quietly drop if `X'<0 | `X' >=99999999 | `X'==. if (obs0>_N) { display obs0-_N " records droped for out of range `X' } scalar obs0=_N } ** display "Checking there is at least 1 observation is left after the final drop" if _N==0 { display "Aborting: No observations in data set" exit } /* *display "Eliminating scientific notation format in outfile" foreach X of local invars { format %15.2f `X' }*/ if `"`debug'"' == `"debug"' { display "Here are the variable counts and means after cleaning:" summarize `invars' } capture describe di _N " records out of " startobs " are left for taxsim to process" local sent=_N ** Handling the case of state=-1 local sent51=`sent'*51 quietly tostring taxsimid,replace quietly replace taxsimid ="9 `mtr' `idtl' `plan' `planval' /" + char(10) + taxsimid in 1 local obs=r(N) outfile taxsimid `invars' using `outfile',noquote nolabel if `"`local'"' == `"local"' { ! taxsim9 <`outfile' >`infile' } else { local servername= "`version'" di "server filename is `servername'" di " infile is `infile'" di " outfile is `outfile'" file open out using ftp.txt, write replace local slashck "/C" if `"`debug'"' == `"debug"' { local slashck "/K" di "Type EXIT in DOS window to return to stata." file write out "debug" _n } file write out "open taxsimftp.nber.org" _char(10) file write out "user taxsim 02138" _char(10) file write out "cd tmp" _char(10) file write out "type ascii" _char(10) file write out "put `outfile' `servername'" _char(10) file write out "get `servername'.arc9 `infile'" _char(10) file write out "get `servername'.msg msg.txt" _char(10) if _n > 10000 { file write out "del `servername'" _char(10) } file write out "quit" _char(10) file close out capture { rm msg.txt } di "`c(os)`" if "`c(os)'" == "Windows" { ! cmd `slashck' ftp -n -s:ftp.txt -w:12888 } else { ! ftp -n 1 & `r(N)'-`sent51'>=1 ) { display "This machine may have had trouble communicating with our server" display "Check the size and content of the result file (results.raw, by default)" display "If processing stopped midway, the results file may be large" display "but if not, the top of the file may include a message from our webserver" display "that would be helpful for debugging" display "Consult the Notes and Support section of the help file for troubleshooting info" display "http://www.nber.org/taxsim/stata/ " display "`r(N)'!=`sent' & `r(N)'!=`sent51'" exit } label variable state "state id" label variable fiitax "Federal Income Tax" label variable siitax "State Income Tax" label variable fica "OASDI and HI Payroll Tax" label variable frate "IIT marginal rate" label variable srate "state marginal rate" label variable ficar "SS marginal rate" if `"`full'"' == `"full"' { label variable v10 "Federal AGI" label variable v11 "UI in AGI" label variable v12 "Social Security in AGI" label variable v13 "Zero Bracket Amount" label variable v14 "Personal Exemptions" label variable v15 "Exemption Phaseout" label variable v16 "Deduction Phaseout" label variable v17 "Deductions allowed" label variable v18 "Federal Taxable Income" label variable v19 "Federal Regular Tax" label variable v20 "Exemption Surtax" label variable v21 "General Tax Credit" label variable v22 "Child Tax Credit (as adjusted)" label variable v23 "Refundable Part of Child Tax Credit" label variable v24 "Child Care Credit" label variable v25 "Earned Income Credit" label variable v26 "Income for the Alternative Minimum Tax" label variable v27 "AMT Liability (addition to regular tax)" label variable v28 "Income Tax before Credits" label variable v29 "FICA" label variable v30 "State Household Income" label variable v31 "State Rent Payments" label variable v32 "State AGI" label variable v33 "State Exemption amount" label variable v34 "State Standard Deduction" label variable v35 "State Itemized Deductions" label variable v36 "State Taxable Income" label variable v37 "State Property Tax Credit" label variable v38 "State Child Care Credit" label variable v39 "State EITC " label variable v40 "State Total Credits" label variable v41 "State Bracket Rate" } sort taxsimid state capture save `output', replace restore display " " if `"`replace'"' != `"replace"' { display "TAXSIM results are saved in `output'" display " " display "To merge the TAXSIM results to the current dataset, run the commands below." display " " if `"`x51'"' == `"x51"' { display "generate taxsimid = _n" display "replace state=statet" display "sort taxsimid state" display "merge taxsimid state using `output', nokeep replace update" display "drop statet _merge" } else { display "generate taxsimid = _n" display "sort taxsimid" display "merge taxsimid using `output',replace update" } display " " display "To avoid merging by hand, rerun with the replace option " display "to automatically merge the datasets." } else { capture drop taxsimid _merge capture generate taxsimid = _n if `"`x51'"' == `"x51"' { display "TAXSIM results are being merged with workspace by taxsimid state" replace state = statet sort taxsimid state merge taxsimid state using `output',replace update display "Keeping only matching state data" drop if statet==. drop statet _merge } else { display "TAXSIM results are being merged with workspace by taxsimid" sort taxsimid merge taxsimid using `output',replace update drop _merge } } display " " end program define drop_message, rclass version 8.0 args dropped varname if (`dropped'>0) { display `dropped' %8.0g " records dropped for out of range `varname'" } scalar obs0 =_N end