Install any skill in seconds. Free to start, no credit card required.
Get Started Free →STATA code for empirical accounting and financial economics research
.claude/skills/brycewang-stanford-stata-accounting-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 173% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 15% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 84% | 0% |
Generate publication-ready Stata code for empirical accounting research. This skill covers the standard econometric models, variable constructions, and estimation procedures used in top accounting journals (TAR, JAR, JAE, RAS, CAR).
Empirical accounting research has developed a distinctive set of analytical conventions that differ from general econometrics. Researchers work with financial statement data from databases like Compustat and CRSP, construct standardized proxies for earnings quality, accruals, and discretionary behavior, and employ estimation techniques that address the particular endogeneity concerns in archival accounting studies.
This skill provides the Stata implementation for the most commonly used models in accounting research: accrual models (Jones, Modified Jones, performance-matched), earnings management detection, value relevance studies, audit quality analyses, and corporate governance research. Each model includes the variable construction from raw Compustat items, the estimation procedure, and the table formatting expected by accounting journal reviewers.
The code follows the conventions established in influential methodological papers by Dechow, Sloan, and Sweeney (1995), Kothari, Leone, and Wasley (2005), and Ecker, Francis, Kim, Olsson, and Schipper (2006), ensuring alignment with reviewer expectations at major accounting journals.
stata* ============================================ * Standard Compustat Variable Construction * ============================================ * Load Compustat annual data use "raw/compustat_annual.dta", clear * Fiscal year identifier gen fyear = year(datadate) * Key financial variables (Compustat mnemonics) * Total accruals (balance sheet approach) gen total_accruals_bs = (dch_act - dch_che) - (dch_lct - dch_dlc - dch_txp) - dp replace total_accruals_bs = total_accruals_bs / l.at // Scale by lagged assets * Total accruals (cash flow approach, preferred) gen total_accruals_cf = (ib - oancf) / l.at * Key ratios gen roa = ib / l.at // Return on assets gen leverage = (dltt + dlc) / at // Financial leverage gen size = ln(at) // Firm size (log assets) gen mb = (prcc_f * csho) / ceq // Market-to-book gen sales_growth = (sale - l.sale) / l.sale // Revenue growth gen cfo = oancf / l.at // Cash flow from operations gen loss = (ib < 0) // Loss indicator * Industry classification (Fama-French 48) merge m:1 sic using "reference/ff48_sic.dta", nogen keep(master match)
stata* Standard sample restrictions drop if at <= 0 // Positive assets drop if sale < 0 // Non-negative sales drop if missing(ib, at, sale) // Key variables non-missing drop if inlist(sic, 6000, 6999) // Exclude financials (SIC 6000-6999) drop if inlist(sic, 4900, 4999) // Exclude utilities (SIC 4900-4999) * Require minimum observations per industry-year bysort ff48 fyear: gen n_iy = _N drop if n_iy < 20 * Winsorize continuous variables at 1st/99th percentile foreach var of varlist roa leverage mb sales_growth cfo total_accruals_cf { winsor2 `var', cuts(1 99) replace }
stata* ============================================ * Modified Jones Model - Industry-Year Estimation * ============================================ * Construct regressors gen inv_at = 1 / l.at gen d_rev_rec = ((sale - l.sale) - (rect - l.rect)) / l.at gen ppe_scaled = ppegt / l.at * Estimate by industry-year cross-sections gen da_mj = . levelsof ff48, local(industries) levelsof fyear, local(years) foreach ind of local industries { foreach yr of local years { capture { reg total_accruals_cf inv_at d_rev_rec ppe_scaled /// if ff48 == `ind' & fyear == `yr', robust predict resid if e(sample), resid replace da_mj = resid if ff48 == `ind' & fyear == `yr' & !missing(resid) drop resid } } } label variable da_mj "Discretionary accruals (Modified Jones)"
stata* Add ROA as control for performance matching gen da_kothari = . foreach ind of local industries { foreach yr of local years { capture { reg total_accruals_cf inv_at d_rev_rec ppe_scaled roa /// if ff48 == `ind' & fyear == `yr', robust predict resid if e(sample), resid replace da_kothari = resid if ff48 == `ind' & fyear == `yr' & !missing(resid) drop resid } } } label variable da_kothari "Discretionary accruals (Kothari)" * Alternative: performance matching by ROA decile xtile roa_decile = roa, nq(10) bysort ff48 fyear roa_decile: egen da_pm = mean(da_mj) gen da_performance_matched = da_mj - da_pm
stata* ============================================ * Earnings Distribution Discontinuity Test * ============================================ * Scaled earnings (earnings per share / price) gen earn_scaled = ib / (prcc_f * csho) * Histogram around zero twoway (histogram earn_scaled if inrange(earn_scaled, -0.10, 0.10), /// width(0.005) color(navy%50)), /// xline(0, lcolor(red)) /// title("Distribution of Scaled Earnings Around Zero") /// xtitle("Earnings / Market Cap") ytitle("Frequency") /// graphregion(color(white)) graph export "figures/earnings_discontinuity.pdf", replace * Burgstahler & Dichev (1997) test gen earn_bin = round(earn_scaled, 0.005) tab earn_bin if inrange(earn_scaled, -0.025, 0.025) * Test for discontinuity at zero gen just_above = (earn_scaled >= 0 & earn_scaled < 0.005) gen just_below = (earn_scaled >= -0.005 & earn_scaled < 0) prtest just_above == just_below
stata* Abnormal cash flow from operations gen da_cfo = . foreach ind of local industries { foreach yr of local years { capture { reg cfo inv_at sale_scaled d_sale_scaled /// if ff48 == `ind' & fyear == `yr', robust predict resid if e(sample), resid replace da_cfo = resid if ff48 == `ind' & fyear == `yr' & !missing(resid) drop resid } } } * Abnormal production costs gen prod_costs = cogs + (xinv - l.xinv) gen prod_scaled = prod_costs / l.at gen da_prod = . foreach ind of local industries { foreach yr of local years { capture { reg prod_scaled inv_at sale_scaled d_sale_scaled l.d_sale_scaled /// if ff48 == `ind' & fyear == `yr', robust predict resid if e(sample), resid replace da_prod = resid if ff48 == `ind' & fyear == `yr' & !missing(resid) drop resid } } }
stata* Main regression: Discretionary accruals on governance reg abs_da_mj board_independence ceo_duality audit_committee_size /// big4 size leverage mb loss i.fyear, cluster(gvkey) estimates store gov1 reg abs_da_mj board_independence ceo_duality audit_committee_size /// big4 inst_ownership analyst_following /// size leverage mb loss i.fyear, cluster(gvkey) estimates store gov2 * Publication table esttab gov1 gov2 using "tables/governance_regression.tex", /// b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) /// label title("Corporate Governance and Earnings Quality") /// mtitles("Baseline" "Extended") /// drop(*.fyear) indicate("Year FE = *.fyear") /// stats(N r2_a, labels("Observations" "Adj. R-squared") fmt(0 3)) /// addnotes("Standard errors clustered by firm in parentheses.") /// replace
stata* Instrumental variable regression ivregress 2sls earnings_quality (board_independence = /// state_governance_index peer_board_independence) /// size leverage mb loss i.fyear, cluster(gvkey) first * First-stage diagnostics estat firststage estat endogenous * Weak instrument test estat firststage, forcenonrobust
stata* PSM for treatment effect of Big 4 auditor logit big4 size leverage mb roa loss i.ff48, robust predict pscore, pr * Nearest-neighbor matching psmatch2 big4, pscore(pscore) outcome(abs_da_mj) /// neighbor(3) caliper(0.01) common
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 26,744 | 27,094 | +1% | 1 | 1 | 0% | 5,216 | 8,249 | +58% | 0 | 0 | — |
case-04 | pass→pass | 24,542 | 28,723 | +17% | 1 | 1 | 0% | 4,642 | 8,156 | +76% | 0 | 0 | — |
case-01 | fail→fail | 40,146 | 32,608 | -19% | 1 | 1 | 0% | 8,060 | 6,931 | -14% | 0 | 0 | — |
case-02 | fail→fail | 24,661 | 28,349 | +15% | 1 | 1 | 0% | 4,892 | 8,269 | +69% | 0 | 0 | — |
case-05 | pass→pass | 24,191 | 31,251 | +29% | 1 | 1 | 0% | 4,545 | 8,202 | +80% | 0 | 0 | — |
case-06 | fail→pass | 46,027 | 20,286 | -56% | 1 | 1 | 0% | 2,572 | 6,234 | +142% | 0 | 0 | — |
case-07 | fail→pass | 17,855 | 15,491 | -13% | 1 | 1 | 0% | 3,370 | 5,421 | +61% | 0 | 0 | — |
case-08 | fail→pass | 19,867 | 34,341 | +73% | 1 | 1 | 0% | 3,527 | 9,614 | +173% | 0 | 0 | — |
case-09 | pass→pass | 11,116 | 7,195 | -35% | 1 | 1 | 0% | 1,908 | 3,714 | +95% | 0 | 0 | — |
case-10 | pass→pass | 14,411 | 16,719 | +16% | 1 | 1 | 0% | 2,804 | 5,947 | +112% | 0 | 0 | — |
case-11 | fail→pass | 39,237 | 29,977 | -24% | 1 | 1 | 0% | 7,398 | 8,488 | +15% | 0 | 0 | — |
case-12 | fail→fail | 30,777 | 21,657 | -30% | 1 | 1 | 0% | 6,155 | 6,865 | +12% | 0 | 0 | — |
case-13 | pass→pass | 21,214 | 20,311 | -4% | 1 | 1 | 0% | 4,228 | 6,511 | +54% | 0 | 0 | — |
case-14 | fail→fail | 19,901 | 18,259 | -8% | 1 | 1 | 0% | 3,891 | 6,154 | +58% | 0 | 0 | — |
case-15 | fail→fail | 19,344 | 15,856 | -18% | 1 | 1 | 0% | 3,011 | 5,382 | +79% | 0 | 0 | — |
case-16 | pass→pass | 14,241 | 14,403 | +1% | 1 | 1 | 0% | 2,686 | 5,279 | +97% | 0 | 0 | — |
case-17 | fail→fail | 18,650 | 18,846 | +1% | 1 | 1 | 0% | 3,233 | 6,047 | +87% | 0 | 0 | — |
case-18 | fail→fail | 16,968 | 37,486 | +121% | 1 | 1 | 0% | 3,009 | 10,811 | +259% | 0 | 0 | — |
case-19 | fail→pass | 16,674 | 17,196 | +3% | 1 | 1 | 0% | 3,210 | 5,893 | +84% | 0 | 0 | — |
case-20 | fail→pass | 12,083 | 8,102 | -33% | 1 | 1 | 0% | 2,192 | 3,936 | +80% | 0 | 0 | — |
case-21 | fail→fail | 17,234 | 18,067 | +5% | 1 | 1 | 0% | 3,024 | 5,822 | +93% | 0 | 0 | — |
case-22 | fail→fail | 15,850 | 20,300 | +28% | 1 | 1 | 0% | 2,656 | 6,059 | +128% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +27 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.