Balance-first tuning on Credit Markets

Native balnet regularization paths, reference-fit pooling, and matched pre-treatment RMSE

Matched comparison

The selected fits use the same 723 units, 194 never-treated donors, 10,226 pre-treatment observations, and outcome-SD scale as augsynth. ATTs average the same 17,811 treated unit-years. The main comparison shows the estimates, bootstrap intervals, and event studies.

Intervals use matched unit and calendar-time residualization. The bootstrap correction changes uncertainty only; tuning, weights, ATTs and pre-treatment RMSEs are unchanged.

Weights Method ν λ ATT 95% lower 95% upper Pre RMSE
cohort Augsynth 0.6051 0.0000 -0.4733 -0.7055 -0.2514 0.0222
cohort Entropy 0.5751 5.4772 -0.4575 -0.6906 -0.2318 0.0255
individual Augsynth 0.1516 0.0000 -0.3574 -0.6508 -0.0838 0.1752
individual Entropy 0.1412 0.5477 -0.4749 -0.7373 -0.2536 0.2307

The selected entropy fits have pre-treatment RMSE 0.0255 / 0.2307 SD (cohort / individual), compared with 0.0222 / 0.1752 for augsynth. The final λ values apply to the normalized balance loss. The separate reference paths and fully pooled diagnostics use an unnormalized loss.

Pre RMSE compares cohort-mean gaps for cohort fits and unit-level gaps for individual fits, on identical observations within each mode. Pooled pre RMSE averages gaps by event time first, then weights squared means by event-time support. It measures pooled balance, not individual fit quality.

Fully pooled endpoint

Both fully pooled reference paths reach the grid minimum, λ=0.000001. Their pooled balance is shown separately because these are not the selected partially pooled estimators.

Weights Lambda Pooled_pre_RMSE
cohort 1e-06 0.00000141
individual 1e-06 0.00113517

Selection procedure

  1. Fit a decreasing positive λ sequence for separate balance (ν=0) and fully pooled balance (ν=1). Retain the smallest penalty that passes independent optimality, simplex, and missingness-constraint checks.
  2. Compute ν and the loss normalizers from the selected separate fit. This is the augsynth heuristic; it does not use the minimum pooled loss as a denominator. The pooled endpoint measures attainable pooled balance.
  3. Hold that ν and those normalizers fixed along the final partially pooled λ path. Select the smallest certified penalty on the supplied grid. At a failed next penalty, try a geometric midpoint; keep failed attempts visible. The acceptance tolerance is never relaxed. Block paths stop after an unsuccessful boundary retry; smaller unattempted grid values remain identifiable from the requested grid.

This selects for balance subject to numerical convergence. It is not cross-validation, and the smallest tested convergent penalty is not a proof of a universal numerical lower limit. The Credit run uses 100, 30, 10, 3, 1, 0.3, 0.1, …, 0.000001, one boundary refinement, up to 10,000 coordinate-descent iterations, 500 native IRLS iterations, and 500 block sweeps per penalty. The original-scale stationarity and feasibility tolerance is 0.00001.

How ν is calculated

For group k, let n_k be its treated count and \delta_{ke} its pre-treatment mean gap at event time e. Define the vector E_k=n_k\delta_k, padded by zero where a group has no balancing moment. With K groups and L event lags:

\nu=\frac{\|K^{-1}\sum_k E_k\|_2}{K^{-1}\sum_k\|E_k\|_2},\qquad s_{\mathrm{sep}}=K^{-1}\sum_k\frac{\|E_k\|_2^2}{m_k},\qquad s_{\mathrm{pool}}=L^{-1}\|K^{-1}\sum_k E_k\|_2^2.

All three are evaluated at the separate reference fit; m_k counts its observed pre-period balancing moments. This avoids upstream’s residual != 0 denominator becoming undefined at exact zero residuals. A numerically zero reference loss causes an explicit normalization error rather than an arbitrary floor. The final balance loss is (1-\nu)L_{\mathrm{sep}}/s_{\mathrm{sep}}+\nu L_{\mathrm{pool}}/s_{\mathrm{pool}}, plus the relative-entropy penalty (with the usual one-half on squared loss). Entropy reference fits can yield a different ν from augsynth’s unpenalized quadratic-program reference. The objective’s loss definitions now match its cohort-total, zero-padded form for this complete, full-pre-window panel; the regularizer remains different. For truncated or missing pre-windows, normalizers use the actual fitted lag grid and observed moment counts.

Native path reuse

bal_multisynth_path() passes the entire decreasing λ vector to balnet() with one fixed, exactly equivalent preconditioning transformation. Balnet owns the within-path warm starts. The transformation includes an orthogonal rotation of all soft moments to improve conditioning; no directions are discarded, and acceptance is evaluated in the original coordinates. Separate groups each need only one native path. Large partially pooled fits carry primal weights between λ values; conditional subproblems use native decreasing-prefix paths. Balnet does not expose arbitrary initial dual coefficients, so conditional dual states are not claimed to persist between different subproblems.

For a complete fully pooled individual fit, an exact cohort reduction avoids repeated block sweeps. Convexity of relative entropy makes equal within-cohort weights optimal; the pooled loss is rescaled to preserve the original individual objective. The expanded individual solution is independently checked.

Log-domain weights preserve stationarity checks when tiny weights round to zero in floating-point arithmetic. No positive weight floor is inserted. Tighter solver precision can be retried, but acceptance thresholds stay fixed.

Complete path diagnostics

cohort — separate

Total path fitting time: 2.00 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
1.0000e+02 certified 0.08583 0.04352 169.73 0.0211 0.0e+00
3.0000e+01 certified 0.06602 0.02994 130.50 0.0356 7.0e-07
1.0000e+01 certified 0.05172 0.02181 98.73 0.0323 3.4e-06
3.0000e+00 certified 0.03812 0.01538 50.67 0.0760 1.7e-06
1.0000e+00 certified 0.02813 0.01091 23.70 0.1391 5.5e-06
3.0000e-01 certified 0.02146 0.00841 13.21 0.1973 5.3e-06
1.0000e-01 certified 0.01860 0.00776 10.07 0.2286 5.3e-06
3.0000e-02 certified 0.01741 0.00764 9.03 0.2567 7.8e-06
1.0000e-02 certified 0.01715 0.00765 8.74 0.2727 5.5e-06
5.4772e-03 failed NA NA NA NA NA
3.0000e-03 failed NA NA NA NA NA
1.0000e-03 failed NA NA NA NA NA
3.0000e-04 failed NA NA NA NA NA
1.0000e-04 failed NA NA NA NA NA
3.0000e-05 failed NA NA NA NA NA
1.0000e-05 failed NA NA NA NA NA
3.0000e-06 failed NA NA NA NA NA
1.0000e-06 failed NA NA NA NA NA

cohort — pooled

Total path fitting time: 6.92 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
1e+02 certified 0.11610 0.06360 193.74 0.0063 1.5e-06
3e+01 certified 0.11144 0.05847 191.90 0.0090 1.3e-06
1e+01 certified 0.10301 0.04866 182.72 0.0166 1.5e-06
3e+00 certified 0.09201 0.03353 142.07 0.0396 1.9e-06
1e+00 certified 0.08678 0.02228 93.66 0.0677 3.4e-06
3e-01 certified 0.08531 0.01460 77.27 0.0717 4.4e-06
1e-01 certified 0.08470 0.00976 56.12 0.0887 4.5e-06
3e-02 certified 0.08454 0.00601 36.58 0.1359 4.1e-06
1e-02 certified 0.08504 0.00372 20.72 0.1724 3.3e-06
3e-03 certified 0.08590 0.00202 7.40 0.3274 2.4e-06
1e-03 certified 0.08695 0.00097 4.16 0.4613 2.2e-06
3e-04 certified 0.08780 0.00036 3.20 0.5353 2.1e-06
1e-04 certified 0.08815 0.00013 2.95 0.5597 2.1e-06
3e-05 certified 0.08829 0.00004 2.87 0.5684 2.1e-06
1e-05 certified 0.08833 0.00001 2.84 0.5708 2.1e-06
3e-06 certified 0.08835 0.00000 2.83 0.5717 2.1e-06
1e-06 certified 0.08835 0.00000 2.83 0.5720 2.1e-06

cohort — partial

Total path fitting time: 174.84 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
100.000000 certified 0.04726 0.01319 66.18 0.0705 7.9e-06
30.000000 certified 0.03567 0.00834 28.99 0.1378 6.3e-06
10.000000 certified 0.02804 0.00579 15.82 0.1916 4.1e-06
5.477226 certified 0.02546 0.00511 12.53 0.2138 3.1e-06
3.000000 failed NA NA NA NA NA
1.000000 failed NA NA NA NA NA
0.300000 failed NA NA NA NA NA
0.100000 failed NA NA NA NA NA
0.030000 failed NA NA NA NA NA
0.010000 failed NA NA NA NA NA
0.003000 failed NA NA NA NA NA
0.001000 failed NA NA NA NA NA
0.000300 failed NA NA NA NA NA
0.000100 failed NA NA NA NA NA
0.000030 failed NA NA NA NA NA
0.000010 failed NA NA NA NA NA
0.000003 failed NA NA NA NA NA
0.000001 failed NA NA NA NA NA

individual — separate

Total path fitting time: 49.14 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
100.0000000 failed NA NA NA NA NA
30.0000000 certified 0.41933 0.06627 193.97 0.0055 0
10.0000000 certified 0.41758 0.06585 193.71 0.0061 0
3.0000000 certified 0.41166 0.06444 190.74 0.0089 0
1.0000000 certified 0.39601 0.06090 160.09 0.0213 0
0.3000000 certified 0.35304 0.05261 33.19 0.1534 0
0.1000000 certified 0.29156 0.04356 2.98 0.5442 0
0.0300000 certified 0.23463 0.03453 1.66 0.7758 0
0.0173205 certified 0.21557 0.03067 1.37 0.8531 0
0.0100000 failed NA NA NA NA NA
0.0030000 failed NA NA NA NA NA
0.0010000 failed NA NA NA NA NA
0.0003000 failed NA NA NA NA NA
0.0001000 failed NA NA NA NA NA
0.0000300 failed NA NA NA NA NA
0.0000100 failed NA NA NA NA NA
0.0000030 failed NA NA NA NA NA
0.0000010 failed NA NA NA NA NA

individual — pooled

Total path fitting time: 26.07 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
1e+02 failed NA NA NA NA NA
3e+01 failed NA NA NA NA NA
1e+01 certified 0.42020 0.06646 194.00 0.0052 0
3e+00 certified 0.42019 0.06640 194.00 0.0052 0
1e+00 certified 0.42014 0.06622 194.00 0.0053 0
3e-01 certified 0.41999 0.06564 193.98 0.0055 0
1e-01 certified 0.41960 0.06411 193.82 0.0061 0
3e-02 certified 0.41851 0.05977 192.53 0.0082 0
1e-02 certified 0.41653 0.05105 185.90 0.0143 0
3e-03 certified 0.41384 0.03627 152.43 0.0341 0
1e-03 certified 0.41244 0.02413 101.01 0.0631 0
3e-04 certified 0.41204 0.01575 77.94 0.0740 0
1e-04 certified 0.41190 0.01061 62.45 0.0800 0
3e-05 certified 0.41184 0.00658 38.38 0.1266 0
1e-05 certified 0.41193 0.00411 25.42 0.1666 0
3e-06 certified 0.41209 0.00228 8.69 0.2957 0
1e-06 certified 0.41231 0.00114 4.52 0.4397 0

individual — partial

Total path fitting time: 487.09 seconds.

lambda status comparison_rmse comparison_pooled_rmse minimum_effective_donors maximum_weight kkt
100.0000000 certified 0.41469 0.06370 192.53 0.0078 4.9e-06
30.0000000 certified 0.40289 0.05846 179.05 0.0171 1.5e-06
10.0000000 certified 0.37447 0.04838 88.63 0.0641 4.9e-06
3.0000000 certified 0.31382 0.03420 5.72 0.3935 6.3e-06
1.0000000 certified 0.25543 0.02403 1.86 0.7013 9.2e-06
0.3000000 failed NA NA NA NA NA
0.5477226 certified 0.23071 0.01975 1.52 0.8106 8.8e-06
0.3000000 failed NA NA NA NA NA

Native balnet exposes total path time, not reliable per-λ timing. Block paths also record elapsed time per attempted penalty. These are uncached fitting runs, excluding design construction, post-fit predictions, rendering, and the old augsynth fits. They are not an identical-objective speed benchmark.

Pre-treatment figure: PNG · PDF · Summary CSV · Full path CSV, including failures · Results and numerical provenance · Runnable experiment · ATTs and event studies with intervals