Credit Markets: simple MTGP and TROP-lite

This separate experiment uses two minimal implementations from mtgpax. It does not replace or modify the established estimator comparison.

Sample and point estimates

The balanced Credit Markets sample has 723 stock–country units × 53 years (1960–2012): 529 treated units in 15 adoption cohorts and 194 never-treated units. The 21 initially treated units are excluded, exactly as in the established comparison. The outcome is divided by the original source-sample SD, 1.3291711872, without centering. Both scalar estimates average the same 17,811 observed treated unit-years. Neither model changes the sample or uses additional covariates.

estimates()
Estimator ATT (outcome SDs) Aggregation Inference
MTGP MAP -0.516322 17,811 treated unit-years Point estimate only
TROP lite -0.347674 17,811 treated unit-years Point estimate only

These are point estimates, without bootstrap intervals or posterior uncertainty. The common sample, scale and scalar weighting match the established all-treated-cell comparisons; CS-DID’s separately reported equal-event-time aggregate uses different weights.

Rank-one MTGP MAP

mtgpax.gp.map.MTGPCausalEstimator fits a Gaussian outcome model with a unit intercept and one latent time factor governed by a Gaussian process, with unit-specific factor loadings. It is fitted jointly to untreated observations from all units: never-treated histories and each treated unit’s pre-adoption history. Every treated outcome is masked from the likelihood.

Settings are rank 1, 1,500 Adam steps, learning rate 0.03, seed 0, scalar_effect=False, and additive_fixed_effects=False. Other numerical settings retain the package defaults. This is a fixed-budget MAP fit, not full Bayesian posterior sampling. The JSON records its loss trace; finite losses are verified, without claiming that the optimizer reached a global optimum. Post-treatment effects are observed outcomes minus predicted untreated outcomes.

Rank-one TROP-lite

mtgpax.trop.lite.TROPLiteEstimator is the repository’s simplified TROP-style residual-augmentation estimator, not the paper’s full nuclear-norm estimator or its full tuning procedure.

The current API takes one treated series. For each adoption cohort, this adapter supplies the cohort’s mean outcome as that series, plus the same 194 never-treated donor units. It fits 15 models independently. Other adoption cohorts are not donors and there is no cross-cohort pooling parameter.

A rank-one iterative-SVD imputer estimates the untreated low-rank surface. For each post-treatment cell, TROP-lite adds the treated pre-residual average and the donor contemporaneous residual average, then subtracts the donor pre-residual average. Unit and time residual averages use exponential-distance weights.

The rank is fixed at 1, with 35 SVD iterations. The time-localization grid is [0, 0.05, 0.15, 0.4, 1]; the unit-localization grid is [0, 0.5, 1, 2, 4]. Each cohort selects the pair minimizing held-out pre-treatment prediction error over the last min(10, floor(pre_periods/2)) pre-periods. The low-rank surface is refitted with each validation outcome masked. These are the repository’s default localization grids and validation rule; only the rank is restricted to the simplest nonzero choice.

Cohort paths are aggregated using cohort sizes at each event time, and scalar ATTs use cohort size × number of observed post periods. Unlike the nuclear-norm scalar adapter, TROP-lite produces genuinely time-varying post-treatment effects.

Post-treatment event studies

No pre-treatment effect curve or period −1 recentering is constructed. These plots show only out-of-treatment-sample predictions and observed post-treatment outcomes. No uncertainty bands were computed. Longer event times are supported by fewer cohorts; support is shown below.

events()

TROP-lite cohort tuning

tuning()
Cohort Units ATT rank lambda_time lambda_unit Validation MSE
1967 11 0.88363 1 0.15 1 0.017285
1969 2 0.946747 1 1 2 0.0374917
1971 1 0.672845 1 0.4 0 0.171571
1976 10 0.251164 1 0 0 0.00592978
1977 255 -0.49894 1 1 4 0.001641
1978 81 -0.241073 1 0.15 0 0.00126996
1979 46 0.0783032 1 0 0 0.00414701
1980 7 0.12394 1 1 0 0.00970994
1982 4 0.0154642 1 1 2 0.0161095
1983 82 -0.667186 1 1 0.5 0.00379965
1984 1 0.0289117 1 1 1 0.000722496
1995 15 -0.237559 1 0.15 2 0.00233632
2000 1 -0.214024 1 1 2 0.00866529
2005 12 -0.263377 1 1 4 0.00102243
2010 1 -0.233736 1 1 1 0.0028965

Verification and reproduction

On a separate deterministic panel, adding 3 to all treated post outcomes leaves both models’ counterfactual predictions unchanged and shifts their effects by exactly 3. TROP-lite’s output also matches an independent reconstruction of its four-term residual-augmentation identity. For the Credit fits, post-effect counts and weighted event-path averages reproduce the scalar ATTs. The JSON includes those checks, package versions, source hashes and the mtgpax commit.

Results JSON · Quarto source · Executable helpers and settings

Run prepare.py from the replication environment to rebuild the eligible panel locally. Run mtgpax_worker.py with the separate mtgpax Python environment and the supplied parameter JSONs; render this QMD with the replication environment. The archive microdata are not included. The README in the bundle gives the exact commands. The existing comparison files and environment are unchanged.

Source