## delta Slow-flow damping (tuning n=1024): slope 1.0994; low-third Δ -0.0321 bps; score Δ -0.09293 ± 0.01371 SE. Added lines in source order: ```diff + slots[13] = wmul(LAMBDA_COEF,slots[7])+wmul(FLOW_SIZE_COEF,wmul(slots[7],slots[8])); + uint256 flowDecay = _powWad(995*WAD/1000,elapsed); + uint256 lastFlow = wmul(LAMBDA_COEF,lambdaHat)+wmul(FLOW_SIZE_COEF,wmul(lambdaHat,sizeHat))+wmul(ACT_COEF,actEma); + slots[13] = wmul(slots[13],flowDecay)+wmul(lastFlow,WAD-flowDecay); + uint256 flowFee = wmul(LAMBDA_COEF,lambdaHat)+wmul(FLOW_SIZE_COEF,flowSize)+wmul(ACT_COEF,actEma); + uint256 reduction = slots[13]>1585*BPS/100 ? wmul(slots[13]-1585*BPS/100,575*WAD/1000) : 0; + fMid -= reduction 0 ? wdiv(initialY, initialX) : 100 * WAD; slots[6] = 950000000000000; slots[7] = 800000000000000000; slots[8] = 2000000000000000; slots[9] = 0; slots[10] = 0; slots[11] = 0; slots[12] = 0; slots[13] = wmul(LAMBDA_COEF,slots[7])+wmul(FLOW_SIZE_COEF,wmul(slots[7],slots[8])); return (BASE_FEE, BASE_FEE); } function afterSwap(TradeInfo calldata trade) external override returns (uint256, uint256) { uint256 prevBidFee = slots[0]; uint256 prevAskFee = slots[1]; uint256 lastTs = slots[2]; uint256 dirState = slots[3]; uint256 actEma = slots[4]; uint256 pHat = slots[5]; uint256 sigmaHat = slots[6]; uint256 lambdaHat = slots[7]; uint256 sizeHat = slots[8]; uint256 toxEma = slots[9]; uint256 stepTradeCount = slots[10]; bool isNewStep = trade.timestamp > lastTs; if (isNewStep) { uint256 elapsedRaw = trade.timestamp - lastTs; uint256 elapsed = elapsedRaw > ELAPSED_CAP ? ELAPSED_CAP : elapsedRaw; uint256 flowDecay = _powWad(995*WAD/1000,elapsed); uint256 lastFlow = wmul(LAMBDA_COEF,lambdaHat)+wmul(FLOW_SIZE_COEF,wmul(lambdaHat,sizeHat))+wmul(ACT_COEF,actEma); slots[13] = wmul(slots[13],flowDecay)+wmul(lastFlow,WAD-flowDecay); dirState = _decayCentered(dirState, DIR_DECAY, elapsed); actEma = wmul(actEma, _powWad(ACT_DECAY, elapsed)); sizeHat = wmul(sizeHat, _powWad(SIZE_DECAY, elapsed)); toxEma = wmul(toxEma, _powWad(TOX_DECAY, elapsed)); if (stepTradeCount > 0 && elapsedRaw > 0) { uint256 lambdaInst = (stepTradeCount * WAD) / elapsedRaw; if (lambdaInst > LAMBDA_CAP) lambdaInst = LAMBDA_CAP; lambdaHat = wmul(lambdaHat, LAMBDA_DECAY) + wmul(lambdaInst, WAD - LAMBDA_DECAY); } stepTradeCount = 0; } bool firstInStep = stepTradeCount == 0; uint256 spot = trade.reserveX > 0 ? wdiv(trade.reserveY, trade.reserveX) : pHat; if (pHat == 0) pHat = spot; uint256 feeUsed = trade.isBuy ? prevBidFee : prevAskFee; uint256 gamma = feeUsed < WAD ? WAD - feeUsed : 0; uint256 pImplied; if (gamma == 0) { pImplied = spot; } else { pImplied = trade.isBuy ? wmul(spot, gamma) : wdiv(spot, gamma); } { uint256 ret = pHat > 0 ? wdiv(absDiff(pImplied, pHat), pHat) : 0; uint256 alpha = firstInStep ? PHAT_ALPHA : PHAT_ALPHA_RETAIL; uint256 prePhat = pHat; bool secondPrint = !firstInStep && stepTradeCount == 1; bool sameDir = false; bool oppDir = false; if (secondPrint) { bool up2 = pImplied >= pHat; uint256 d1 = slots[12]; if (d1 != 0) { sameDir = (d1 == 1) == up2; oppDir = !sameDir; } if (sameDir) alpha = PHAT_ALPHA_SAME; } if (firstInStep) { slots[11] = pHat; slots[12] = pImplied >= pHat ? 1 : 2; } uint256 adaptiveGate = wmul(sigmaHat, GATE_SIGMA_MULT); if (adaptiveGate < MIN_GATE) adaptiveGate = MIN_GATE; if (ret <= adaptiveGate) { pHat = wmul(pHat, WAD - alpha) + wmul(pImplied, alpha); } if (oppDir && REVERT_U > 0) { uint256 pre = slots[11]; if (pre > pHat) pHat = pHat + wmul(pre - pHat, REVERT_U); else pHat = pHat - wmul(pHat - pre, REVERT_U); } if (firstInStep) { if (ret > RET_CAP) ret = RET_CAP; sigmaHat = wmul(sigmaHat, SIGMA_DECAY) + wmul(ret, WAD - SIGMA_DECAY); } } // Interior retail routing equalizes fee-adjusted marginal prices. // Subsequent trades in a step cannot be the initial arbitrage trade. if (!firstInStep && feeUsed > 30 * BPS && gamma > 0) { uint256 normalSpot = trade.isBuy ? wdiv(wmul(spot, gamma), WAD - 30 * BPS) : wdiv(wmul(spot, WAD - 30 * BPS), gamma); pHat = wmul(pHat, 90 * WAD / 100) + wmul(normalSpot, 10 * WAD / 100); } uint256 tradeRatio = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0; if (tradeRatio > TRADE_RATIO_CAP) tradeRatio = TRADE_RATIO_CAP; if (tradeRatio > SIGNAL_THRESHOLD) { uint256 push = tradeRatio * DIR_IMPACT_MULT; if (push > WAD / 4) push = WAD / 4; if (trade.isBuy) { dirState = dirState + push; if (dirState > 2 * WAD) dirState = 2 * WAD; } else { dirState = dirState > push ? dirState - push : 0; } actEma = wmul(actEma, ACT_BLEND_DECAY) + wmul(tradeRatio, WAD - ACT_BLEND_DECAY); sizeHat = wmul(sizeHat, SIZE_BLEND_DECAY) + wmul(tradeRatio, WAD - SIZE_BLEND_DECAY); if (sizeHat > WAD) sizeHat = WAD; } uint256 tox = pHat > 0 ? wdiv(absDiff(spot, pHat), pHat) : 0; if (tox > TOX_CAP) tox = TOX_CAP; toxEma = wmul(toxEma, TOX_BLEND_DECAY) + wmul(tox, WAD - TOX_BLEND_DECAY); uint256 toxSignal = toxEma; stepTradeCount = stepTradeCount + 1; if (stepTradeCount > STEP_COUNT_CAP) stepTradeCount = STEP_COUNT_CAP; uint256 flowSize = wmul(lambdaHat, sizeHat); uint256 fBase = BASE_FEE + wmul(SIGMA_COEF, sigmaHat) + wmul(LAMBDA_COEF, lambdaHat) + wmul(FLOW_SIZE_COEF, flowSize); uint256 fMid = fBase + wmul(TOX_COEF, toxSignal) + wmul(TOX_QUAD_COEF, wmul(toxSignal, toxSignal)) + wmul(ACT_COEF, actEma); fMid = fMid + wmul(SIGMA_TOX_COEF, wmul(sigmaHat, toxSignal)); uint256 flowFee = wmul(LAMBDA_COEF,lambdaHat)+wmul(FLOW_SIZE_COEF,flowSize)+wmul(ACT_COEF,actEma); uint256 reduction = slots[13]>1585*BPS/100 ? wmul(slots[13]-1585*BPS/100,575*WAD/1000) : 0; fMid -= reduction= WAD) { dirDev = dirState - WAD; sellPressure = true; } else { dirDev = WAD - dirState; sellPressure = false; } uint256 skew = wmul(DIR_COEF, dirDev) + wmul(DIR_TOX_COEF, wmul(dirDev, toxSignal)); uint256 bidFee; uint256 askFee; if (sellPressure) { bidFee = fMid + skew; askFee = fMid > skew ? fMid - skew : 0; } else { askFee = fMid + skew; bidFee = fMid > skew ? fMid - skew : 0; } { uint256 staleShift = wmul(STALE_DIR_COEF, toxSignal); uint256 attractShift = wmul(staleShift, STALE_ATTRACT_FRAC); if (spot >= pHat) { bidFee = bidFee + staleShift; askFee = askFee > attractShift ? askFee - attractShift : 0; } else { askFee = askFee + staleShift; bidFee = bidFee > attractShift ? bidFee - attractShift : 0; } } { bool tradeAligned = (trade.isBuy && spot >= pHat) || (!trade.isBuy && spot < pHat); if (tradeAligned) { uint256 tradeBoost = wmul(TRADE_TOX_BOOST, tradeRatio); if (trade.isBuy) { bidFee = bidFee + tradeBoost; } else { askFee = askFee + tradeBoost; } } } if (sellPressure) { bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_PROTECT)); askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_ATTRACT)); } else { askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_PROTECT)); bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_ATTRACT)); } slots[0] = bidFee; slots[1] = askFee; slots[2] = trade.timestamp; slots[3] = dirState; slots[4] = actEma; slots[5] = pHat; slots[6] = sigmaHat; slots[7] = lambdaHat; slots[8] = sizeHat; slots[9] = toxEma; slots[10] = stepTradeCount; return (bidFee, askFee); } function _compressTailWithSlope(uint256 fee, uint256 slope) internal pure returns (uint256) { if (fee <= TAIL_KNEE) return fee; return TAIL_KNEE + wmul(fee - TAIL_KNEE, slope); } function _powWad(uint256 factor, uint256 exp) internal pure returns (uint256 result) { result = WAD; while (exp > 0) { if (exp & 1 == 1) result = wmul(result, factor); factor = wmul(factor, factor); exp >>= 1; } } function _decayCentered(uint256 centered, uint256 decayFactor, uint256 elapsed) internal pure returns (uint256) { uint256 mul = _powWad(decayFactor, elapsed); if (centered >= WAD) { return WAD + wmul(centered - WAD, mul); } uint256 below = wmul(WAD - centered, mul); return below < WAD ? WAD - below : 0; } function getName() external pure override returns (string memory) { return "no_cubic"; } } ``` ## sha256 `fe79daf75824212680a8178d8c00d14c011a277dc4fa9006625624267cb8d880` SHA-256 covers the Solidity block exactly, including its final LF. ## tuning The selected shape changes normalizer-based tuning score by -0.092928 ± 0.013705 SE. Its direct-match gain below must not be read as that score gain. NP2 was reconstructed from [TWO](https://api.imdnotdead.fun/artifacts/528a6da78583c6142644a552c86670f9d25c20e39e92f4de44deae05ddc8cecd) plus the specified [NP routing block](https://api.imdnotdead.fun/artifacts/da313379a2e69e9286668865e06b18dfcae25732c82b934b0fd9c2ef0d8c2ff5). Its SHA-256 is `51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0`. Calibration against the 30 bps normalizer on seeds 0–999: [CH](https://raw.githubusercontent.com/ChengHua926/amm-challenge/d34a5199c59a4c44d5336a25f1436b4ae1f21104/contracts/src/Strategy.sol) **525.5258821780834** (required 525.525882178); NP2 **526.1155722459862** (brief 526.1156). These seeds were used only to check reproduction. Simulator commit: `6b6921f8d463314aa7c96234e1be25a25245f704`. Every simulation has 10,000 steps, price 100, reserves X=100/Y=10,000, mu=0, dt=1, retail buy probability 0.5, retail size sigma=1.2. Per seed, `numpy.random.default_rng(seed)` draws size U(19,21), then rate U(0.6,1.0), then price sigma U(0.000882,0.001008), and sets `cfg.seed=seed`; Rust uses price seed and retail seed+1. See [configuration](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/config.py), [draw order](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/match.py), and [engine](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/simulation/engine.rs). Batch chunks contain at most 16 configs with eight workers. Direct difference is exactly `run_batch(candidate, NP2, configs)` submission edge minus normalizer edge. The [batch API](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/lib.rs) names the second argument baseline; here it contains NP2. The additional score comparison separately runs each strategy against the [30 bps normalizer](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/VanillaStrategy.sol) and subtracts their submission edges for the same seeds. Thus its reference market matches the calibration market. All table means and standard errors are local measurements; SE uses sample SD (ddof=1) / sqrt(n). Let `F = LAMBDA_COEF*lambdaHat + FLOW_SIZE_COEF*(lambdaHat*sizeHat) + ACT_COEF*actEma`, with WAD products as in NP2. `M` is the slow EMA of the preceding step's F, updated before NP2's state decays, using decay `d^elapsed` and NP2's elapsed cap. Its initializer equals NP2's initial lambda/size contribution, 17.3472 bps. For the selected additive form in a stationary regime (M approximately F), the long-run flow component becomes `(1-w)*F+w*A`; transient flow increments retain NP2's coefficient above the zero floor. Completed grid points are listed below. Variant names encode these new shape parameters; original NP2 constants are identical throughout: - `hK sS`: instant concave hinge `F' = min(F,K) + (S/100)*max(F-K,0)`, K in bps. - `mK rR dD`: slow hinge `F' = F - min(F,(R/100)*max(M-K,0))`, decay D/1000. - `aA wW dD`: additive baseline normalization `F' = F + (W/100)*(A-M)`, with reductions capped at F; A in bps and decay D/1000. The instantaneous flow coefficient is retained above the zero floor. - `nA wW dD`: normalized flow `F' = F + (W/100)*(F*A/M-F)`, A in bps, decay D/1000. Integer implementation branches on the sign. If M=0, F is retained. Finalist aliases: `finalist_n = n15.85w56d995`; `finalist_a = a15.85w57.5d995`. Their inserted numeric literals use exact integer WAD/BPS fractions. `Score Δ` is candidate-versus-normalizer minus NP2-versus-normalizer. Slope and low-third change use those normalizer runs. `Direct Δ` follows the requested shared candidate/NP2 match. All tuning seeds fall in 10000–99999. | Variant | Tuning seeds | n | Direct Δ ± SE | Score Δ ± SE | Mid slope | Low-third mid Δ (bps) | |---|---|---:|---:|---:|---:|---:| | a16.2w55d995 | 10000–10127 | 128 | +9.855609 ± 0.762697 | -0.018768 ± 0.031515 | 1.144908 | +0.230248 | | a16w55d995 | 10000–10127 | 128 | +11.008642 ± 0.780991 | -0.050301 ± 0.034484 | 1.144419 | +0.117716 | | finalist_a | 20000–21023 | 1024 | +12.964474 ± 0.296754 | -0.092928 ± 0.013705 | 1.099419 | -0.032050 | | finalist_n | 20000–21023 | 1024 | +16.084498 ± 0.369422 | -0.096741 ± 0.014812 | 1.080383 | -0.025790 | | h12s25 | 10000–10127 | 128 | +55.659264 ± 1.729285 | -4.863837 ± 0.133342 | 0.894677 | -3.949298 | | h12s50 | 10000–10127 | 128 | +43.131131 ± 1.355164 | -2.191222 ± 0.091144 | 1.216919 | -2.660566 | | h12s75 | 10000–10127 | 128 | +24.973661 ± 0.793069 | -0.634035 ± 0.051310 | 1.492639 | -1.294279 | | h16s25 | 10000–10127 | 128 | +37.122072 ± 1.363995 | -3.140322 ± 0.109797 | 1.295253 | -1.914884 | | h16s50 | 10000–10127 | 128 | +28.851809 ± 1.106442 | -1.531249 ± 0.073156 | 1.497461 | -1.365684 | | h16s75 | 10000–10127 | 128 | +16.379641 ± 0.606859 | -0.518083 ± 0.041905 | 1.635372 | -0.666923 | | h20s25 | 10000–10127 | 128 | +26.760689 ± 1.080826 | -2.367477 ± 0.089940 | 1.532700 | -1.145828 | | h20s50 | 10000–10127 | 128 | +20.696707 ± 0.861871 | -1.198469 ± 0.060873 | 1.651457 | -0.860386 | | m15.5r100d995 | 10000–10127 | 128 | +23.891312 ± 1.332598 | -0.611537 ± 0.075635 | 0.738651 | -0.741620 | | m15.5r50d995 | 10000–10127 | 128 | +12.669532 ± 0.735805 | -0.133067 ± 0.037705 | 1.246390 | -0.248769 | | m15.5r75d995 | 10000–10127 | 128 | +18.113263 ± 1.023467 | -0.332595 ± 0.050750 | 0.958394 | -0.390353 | | m18r100d995 | 10000–10127 | 128 | +6.139716 ± 0.668563 | -0.001746 ± 0.012531 | 1.613629 | -0.009979 | | m18r50d995 | 10000–10127 | 128 | +3.070689 ± 0.323059 | +0.009610 ± 0.008523 | 1.718037 | -0.004676 | | m18r75d995 | 10000–10127 | 128 | +4.645398 ± 0.499359 | +0.000680 ± 0.009579 | 1.672123 | -0.008067 | | m20r50d995 | 10000–10127 | 128 | +0.297721 ± 0.053276 | -0.003262 ± 0.002620 | 1.814308 | -0.001660 | | n15.5w50d995 | 10000–10127 | 128 | +15.860322 ± 0.956230 | -0.123026 ± 0.036834 | 1.163736 | -0.154391 | | n15.7w55d990 | 10000–10127 | 128 | +16.588506 ± 1.041563 | -0.119911 ± 0.035945 | 1.088845 | -0.045692 | | n15.7w55d995 | 10000–10127 | 128 | +15.831487 ± 1.005072 | -0.119316 ± 0.037605 | 1.101963 | -0.049824 | | n15.7w55d995 | 20000–20511 | 512 | +16.879722 ± 0.524002 | -0.117154 ± 0.022043 | 1.111775 | -0.127196 | | n15.7w55d999.5 | 10000–10127 | 128 | +14.663505 ± 0.864348 | -0.136875 ± 0.034265 | 1.228108 | -0.219466 | | n15.7w55d999 | 10000–10127 | 128 | +15.132670 ± 0.935825 | -0.145254 ± 0.035106 | 1.156845 | -0.125640 | | n15w100d995 | 10000–10127 | 128 | +34.905631 ± 1.677497 | -1.000339 ± 0.079355 | 0.540883 | -1.039835 | | n15w50d995 | 10000–10127 | 128 | +18.802357 ± 0.950229 | -0.217002 ± 0.040928 | 1.194998 | -0.517857 | | n15w75d995 | 10000–10127 | 128 | +27.218510 ± 1.366888 | -0.507398 ± 0.055891 | 0.866992 | -0.772119 | | n16w60d995 | 20000–20511 | 512 | +16.029631 ± 0.548178 | -0.081824 ± 0.022043 | 1.052163 | +0.072046 | Partial screening runs were discarded: h20s75 (64/128 direct seeds), m16r50d995 (16/128 direct seeds), m20r75d995 (112/128 direct seeds), n15.5w75d995 (48/128 direct seeds). A completed direct row with an incomplete normalizer comparison is labeled explicitly. Chosen: **finalist_a**, anchor 15.85 bps, weight 0.575, EMA decay 0.995. Both finalists were formed by interpolation on the allowed tuning grid. Selection used the highest normalizer-market paired mean on the common 1,024-seed block among finalists with absolute low-third drift <=0.1 bps and slope in [1.0,1.2]. Final tuning aggregation uses 1024 matched seeds: 20000–21023. Normalizer score Δ **-0.092928**, SE **0.013705**; low-third mid Δ **-0.032050 bps**; mid slope **1.099419** versus NP2 **1.783543**. Compilation/validation: [solc 0.8.24 compiler](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/evm/compiler.py), optimizer 200, viaIR, Paris EVM. `amm-match validate` passed on the exact delivered source. NP2 lines were retained verbatim; the delta consists only of the eight added lines above. The [base contract](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/AMMStrategyBase.sol) supplies 32 slots; the candidate adds only slot 13 and uses the existing [trade interface](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/IAMMStrategy.sol). Actual pyrevm execution checked 5000 randomized constant-product swap hooks, both sides, multiple trades per step, and gaps up to 100 timestamps: all calls succeeded with fees in [0,0.1]. Initialization used 212050 gas; maximum swap hook used 110631 gas, below the [250,000 gas limit](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/evm/strategy.rs). These are actual `evm.result.gas_used` values, not the executor's estimate. ## paired One confirmation pass, candidate frozen before using seeds **2460000–2461999**, no retuning or second pass on these seeds. This is the requested direct `run_batch(candidate, NP2, configs)` comparison. Worst lists the five lowest per-seed edge differences. ```json { "n": 2000, "mean_a": 577.9153323858484, "mean_b": 564.9050288805701, "mean_diff": 13.010303505278236, "se": 0.20123277562008987, "worst": [ { "seed": 2460144, "diff": -3.7800643850748656 }, { "seed": 2461157, "diff": -3.142839287755578 }, { "seed": 2461770, "diff": -3.0500295978105783 }, { "seed": 2460789, "diff": -3.0216734607600984 }, { "seed": 2461302, "diff": -2.995820472163473 } ] } ``` ## fee_stats Fees below are arithmetic means of step-end quotes, including steps without trades, using the engine's [average fee fields](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/types/result.rs). Mid=(bid+ask)/2. Slope is OLS with intercept across runs: mean mid in bps versus the strategy's own executed retail Y divided by 10,000. Each strategy's low/middle/high thirds are formed by sorting its own per-run retail Y. Bid-minus-ask is signed. Counts labeled mean bid use each run's 10,000-step mean. Confirmation direct match, n=2000; NP2 is the opponent in the same market: | Statistic | NP2 | Candidate | |---|---:|---:| | Mean step-end bid (bps) | 36.182405 | 35.290295 | | Mean step-end ask (bps) | 35.390930 | 34.496342 | | Mean bid − ask (bps) | 0.791475 | 0.793954 | | Mean mid (bps) | 35.786668 | 34.893318 | | Mid slope / 10k own retail Y (bps) | 1.801517 | 1.057175 | | Runs with mean bid > 40 bps | 159 | 44 | | Low own-retail third mid (bps) | 33.624701 | 33.337816 | | Middle own-retail third mid (bps) | 35.822228 | 34.897965 | | High own-retail third mid (bps) | 37.916267 | 36.446502 | Runs with **any** step-end bid above 40 bps: NP2 2000/2000, candidate 2000/2000. This differs from the mean-bid count above. Direct confirmation low-third mid change is **-0.286884 bps**. Thus the unchanged-low-third objective is unmet in that market. The normalizer-market preservation below is tuning evidence. Board-comparable tuning markets, each strategy versus the 30 bps normalizer, n=1024 matched seeds: | Statistic | NP2 | Candidate | |---|---:|---:| | Mean step-end bid (bps) | 36.410779 | 35.660032 | | Mean step-end ask (bps) | 35.295846 | 34.620098 | | Mean bid − ask (bps) | 1.114933 | 1.039934 | | Mean mid (bps) | 35.853313 | 35.140065 | | Mid slope / 10k own retail Y (bps) | 1.783543 | 1.099419 | | Runs with mean bid > 40 bps | 95 | 36 | | Low own-retail third mid (bps) | 33.791891 | 33.759840 | | Middle own-retail third mid (bps) | 35.914562 | 35.177027 | | High own-retail third mid (bps) | 37.859531 | 36.487375 | Holding NP2's retail-volume thirds fixed on those same tuning seeds, candidate-minus-NP2 mid changes are **-0.035567, -0.732760, -1.373403 bps** (low/middle/high). The confirmation opponent changes the market and retail allocations, so its slopes and fee levels need not equal the normalizer-market tuning statistics. The [NP routing block](https://api.imdnotdead.fun/artifacts/da313379a2e69e9286668865e06b18dfcae25732c82b934b0fd9c2ef0d8c2ff5) hardcodes a 30 bps counterpart; interpreting it against an NP2 opponent changes that model assumption. The direct gain does not establish a +5.8 or +9.6 normalizer-market improvement. ## blocked `null` ## next Do not promote this delta alone: its normalizer-market tuning result does not establish the brief’s +5.8/+9.6 gains. Keep it as a flow-shape ablation for testing interactions with other mechanisms.