# nextmix-a: NEXT-MIX on NP2 **Result: small, real gain, far short of the target.** Confirmed once on fresh seeds 2610000..2611999 (n=2000): mean_diff **+0.1275**, se **0.0157** (paired vs NP2, both scored against Vanilla). This is about 8 se above zero, but top 10 needs +5.8. ## delta One call is added just before NP2's tail compression and clamp: `(bidFee, askFee) = _nextMix(bidFee, askFee, spot, pHat, sigmaHat, lambdaHat);` It also adds 8 constants and the helpers `_nextMix`, `_tail` (normal tail, A&S 26.2.19) and `_nmShift`. For each side, pA = P(fair next step crosses that side's band edge spot·(1−bid) or spot/(1−ask)), using N(pHat, sigmaHat). pR = λ̂/(1+λ̂), the chance of another retail order. w = pA/(pA+pR), and fee += 60bps·(w−0.5) when w≥0.5, else fee −= 0.5bps·(0.5−w). NM_FRAC=0, so the protective-target branch is disabled. ## code ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {AMMStrategyBase} from "./AMMStrategyBase.sol"; import {TradeInfo} from "./IAMMStrategy.sol"; contract Strategy is AMMStrategyBase { uint256 constant ELAPSED_CAP = 8; uint256 constant SIGNAL_THRESHOLD = WAD / 650; uint256 constant DIR_DECAY = 750000000000000000; uint256 constant ACT_DECAY = 530000000000000000; uint256 constant SIZE_DECAY = 530000000000000000; uint256 constant TOX_DECAY = 910000000000000000; uint256 constant SIGMA_DECAY = 690000000000000000; uint256 constant LAMBDA_DECAY = 990000000000000000; uint256 constant SIZE_BLEND_DECAY = 828000000000000000; uint256 constant TOX_BLEND_DECAY = 51000000000000000; uint256 constant ACT_BLEND_DECAY = 985000000000000000; uint256 constant PHAT_ALPHA = 270000000000000000; uint256 constant PHAT_ALPHA_RETAIL = 60000000000000000; uint256 constant PHAT_ALPHA_SAME = 120000000000000000; uint256 constant REVERT_U = 0; uint256 constant DIR_IMPACT_MULT = 4; uint256 constant GATE_SIGMA_MULT = 7200000000000000000; uint256 constant MIN_GATE = 30000000000000000; uint256 constant TRADE_TOX_BOOST = 3500 * BPS; uint256 constant STALE_ATTRACT_FRAC = 1050000000000000000; uint256 constant RET_CAP = WAD / 35; uint256 constant TOX_CAP = WAD / 5; uint256 constant TRADE_RATIO_CAP = WAD / 5; uint256 constant LAMBDA_CAP = 1820000000000000000; uint256 constant STEP_COUNT_CAP = 64; uint256 constant BASE_FEE = 4 * BPS; uint256 constant SIGMA_COEF = 200000000000000000; uint256 constant LAMBDA_COEF = 12 * BPS; uint256 constant FLOW_SIZE_COEF = 4842 * BPS; uint256 constant TOX_COEF = 300 * BPS; uint256 constant TOX_QUAD_COEF = 15000 * BPS; uint256 constant ACT_COEF = 91843 * BPS; uint256 constant DIR_COEF = 20 * BPS; uint256 constant DIR_TOX_COEF = 100 * BPS; uint256 constant STALE_DIR_COEF = 6850 * BPS; uint256 constant SIGMA_TOX_COEF = 500 * BPS; uint256 constant TAIL_KNEE = 600 * BPS; uint256 constant TAIL_SLOPE_PROTECT = 930000000000000000; uint256 constant TAIL_SLOPE_ATTRACT = 850000000000000000; uint256 constant NM_FRAC = 0; uint256 constant NM_K = 1000000000000000000; uint256 constant NM_MIX_W = 1000000000000000000; int256 constant NM_PROT = 6000000000000000; int256 constant NM_CHEAP = 50000000000000; uint256 constant NM_W0 = 500000000000000000; uint256 constant NM_SIG_MULT = 1000000000000000000; uint256 constant NM_SIG_FLOOR = 300000000000000; function afterInitialize(uint256 initialX, uint256 initialY) external override returns (uint256, uint256) { slots[0] = BASE_FEE; slots[1] = BASE_FEE; slots[2] = 0; slots[3] = WAD; slots[4] = 0; slots[5] = initialX > 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; 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; 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 dirDev; bool sellPressure; if (dirState >= 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; } } } // Next-mix: the fee quoted now serves the next trade (arb next step or retail this step). (bidFee, askFee) = _nextMix(bidFee, askFee, spot, pHat, sigmaHat, lambdaHat); 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); } // Next-mix: the fee returned after a print serves the next trade, which is either the // arbitrageur next step (if fair leaves the no-arb band on that side) or another retail // order this step (Poisson(lambdaHat)). Weight each side by the arb share of that mix. function _nextMix(uint256 bidFee, uint256 askFee, uint256 spot, uint256 pHat, uint256 sigmaHat, uint256 lambdaHat) internal pure returns (uint256, uint256) { if (pHat == 0 || spot == 0) return (bidFee, askFee); uint256 sig = wmul(sigmaHat, NM_SIG_MULT); if (sig < NM_SIG_FLOOR) sig = NM_SIG_FLOOR; uint256 pR = wmul(wdiv(lambdaHat, WAD + lambdaHat), NM_MIX_W); uint256 wB; uint256 wA; { uint256 edgeB = wmul(spot, bidFee < WAD ? WAD - bidFee : 0); uint256 pAB = edgeB >= pHat ? WAD - _tail(wdiv(wdiv(edgeB - pHat, pHat), sig)) : _tail(wdiv(wdiv(pHat - edgeB, pHat), sig)); wB = pAB + pR > 0 ? wdiv(pAB, pAB + pR) : 0; } { uint256 edgeA = askFee < WAD ? wdiv(spot, WAD - askFee) : 1e36; uint256 pAA = edgeA <= pHat ? WAD - _tail(wdiv(wdiv(pHat - edgeA, pHat), sig)) : _tail(wdiv(wdiv(edgeA - pHat, pHat), sig)); wA = pAA + pR > 0 ? wdiv(pAA, pAA + pR) : 0; } if (NM_FRAC > 0) { uint256 kd = wmul(sig, NM_K); uint256 lo = wmul(pHat, WAD > kd ? WAD - kd : 0); uint256 fPB = lo < spot ? WAD - wdiv(lo, spot) : 0; uint256 hi = wmul(pHat, WAD + kd); uint256 fPA = hi > spot ? WAD - wdiv(spot, hi) : 0; if (fPB > bidFee) bidFee = bidFee + wmul(wmul(fPB - bidFee, wB), NM_FRAC); if (fPA > askFee) askFee = askFee + wmul(wmul(fPA - askFee, wA), NM_FRAC); } return (_nmShift(bidFee, wB), _nmShift(askFee, wA)); } // upper normal tail P(Z > x), x in WAD (Abramowitz-Stegun 26.2.19) function _tail(uint256 x) internal pure returns (uint256) { if (x > 8 * WAD) return 0; uint256 p = WAD + wmul(x, 196854000000000000 + wmul(x, 115194000000000000 + wmul(x, 344000000000000 + wmul(x, 19527000000000000)))); uint256 p2 = wmul(p, p); return wdiv(WAD / 2, wmul(p2, p2)); } function _nmShift(uint256 fee, uint256 w) internal pure returns (uint256) { int256 d; if (w >= NM_W0) d = (NM_PROT * int256(w - NM_W0)) / int256(WAD); else d = -(NM_CHEAP * int256(NM_W0 - w)) / int256(WAD); int256 f = int256(fee) + d; return f > 0 ? uint256(f) : 0; } 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 `8d9bc6c3884259f922b1015ac8b5a4b5ce60f7b45677b67dd1e3c3be56b0adc3` (sha256 of the code text above, UTF-8, exactly as in the block). NP2 base sha256 = `51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0`, which matches the brief. ## tuning All tuning used seeds 10000..99999 only. The method is the brief's: `run_batch(cand, vanilla, cfgs, 8)` and `run_batch(np2, vanilla, cfgs, 8)` run separately, 16 seeds per call. Configs follow `MatchRunner._build_configs`: `default_rng(s)` draws size, rate, sigma, and seed=s. d = edges['submission'] of cand minus NP2's. Columns: prot and cheap are in bps. w0 is the switch point. mixw scales pR. sigm and sigf are the sigma multiplier and sigma floor. frac and k belong to the "protective-target" variant: move a fee toward the fee whose band edge sits k·σ beyond pHat, weighted by w·frac. | prot | cheap | w0 | mixw | sigm | sigf | frac | k | seeds | n | mean_diff | se | worst | |---|---|---|---|---|---|---|---|---|---|---|---|---| | 10 | 10 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10999 | 1000 | -0.7416 | 0.0233 | -13.590 | | 20 | 5 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10999 | 1000 | -0.1726 | 0.0194 | -13.045 | | 5 | 20 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10999 | 1000 | -3.0172 | 0.0301 | -15.661 | | 20 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0736 | 0.0088 | -2.674 | | 40 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1289 | 0.0142 | -3.859 | | 20 | 0 | 0.8 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0000 | 0.0000 | +0.000 | | 20 | 2 | 0.2 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | -1.1882 | 0.0501 | -6.994 | | 20 | 0 | 0.5 | 0.3 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | -0.9817 | 0.0445 | -5.289 | | 40 | -2 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | -0.2285 | 0.0183 | -4.335 | | 80 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1302 | 0.0249 | -6.264 | | 40 | 0 | 0.6 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0308 | 0.0034 | -0.590 | | 40 | 0 | 0.35 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | -0.4889 | 0.0460 | -9.499 | | 40 | 0 | 0.5 | 1.0 | 0.7 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1347 | 0.0156 | -3.904 | | 0 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.5 | 1.0 | 10000..10499 | 500 | -3.2050 | 0.1143 | -26.924 | | 0 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 1.0 | 1.0 | 10000..10499 | 500 | -55.4154 | 0.7326 | -159.088 | | 40 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1289 | 0.0142 | -3.859 | | 0 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.5 | 1.0 | 10000..10499 | 500 | -3.2050 | 0.1143 | -26.924 | | 0 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 1.0 | 1.0 | 10000..10499 | 500 | -55.4154 | 0.7326 | -159.088 | | 0 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 1.0 | 2.0 | 10000..10499 | 500 | -329.0348 | 2.3150 | -469.990 | | 40 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.5 | 1.0 | 10000..10499 | 500 | -3.9592 | 0.1260 | -29.503 | | 60 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1483 | 0.0187 | -4.768 | | 60 | 0 | 0.5 | 1.5 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0429 | 0.0071 | -2.819 | | 60 | 0 | 0.5 | 2.5 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0000 | 0.0000 | +0.000 | | 60 | 0 | 0.45 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0743 | 0.0306 | -6.384 | | 60 | 0 | 0.55 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1060 | 0.0122 | -3.805 | | 60 | 0 | 0.5 | 1.0 | 0.5 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1085 | 0.0250 | -6.304 | | 60 | 0 | 0.5 | 1.0 | 1.0 | 0.0006 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1496 | 0.0188 | -4.768 | | 60 | 0.5 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1509 | 0.0196 | -4.789 | | 100 | 0 | 0.5 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0759 | 0.0314 | -6.492 | | 60 | 0 | 0.5 | 1.0 | 1.5 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1504 | 0.0157 | -3.933 | | 60 | 0 | 0.5 | 0.8 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0579 | 0.0312 | -6.383 | | 60 | 0 | 0.5 | 1.2 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.1191 | 0.0130 | -3.970 | | 150 | 0 | 0.6 | 1.0 | 1.0 | 0.0003 | 0.0 | 1.0 | 10000..10499 | 500 | +0.0870 | 0.0117 | -3.888 | Frozen choice: prot=60, cheap=0.5, w0=0.5, mixw=1, sigm=1, sigf=3bps, frac=0. Tuning-range check of the frozen code on 10500..12499: n=2000, mean_diff=+0.1289, se=0.0113, worst=-12.427. What the sweep shows: - Making the arb-safe side cheaper hurts. Even a cut of under 0.4 bps (cheap 2, w0 0.2) cost about −1.2, and cheap 20 cost −3.0. - Raising the safe side also hurts (cheap −2: −0.23). NP2's fee level is a sharp optimum on that side. - Only protection on the exposed side, applied when the arb share is clearly high (w>0.5), helps: about +0.13 to +0.15, flat for prot 40–80. Pushing protection to lower w hurts (w0 0.35: −0.49; mixw 0.3: −0.98). - Moving the fee toward the band-edge-at-kσ "protective regime fee" is catastrophic (−3 to −329). ## paired ```json {"n": 2000, "mean_diff": 0.127518, "se": 0.01567, "worst": -25.342129} ``` Confirm block: seeds 2610000..2611999, fresh and used once, after the constants were frozen. NP2 on that block: mean edge 523.8649; candidate: 523.9924. Note: the first confirm invocation was killed by a 10-minute tool timeout before it printed anything. The rerun of the same frozen code is the only confirm result ever observed; the simulation is deterministic. ## blocked null. Environment caveats, for reproducibility: - This machine is **Linux aarch64**, not x86_64, so the objective's setup script exits at its platform gate (`BLOCKED platform`). I used the item's own setup script, which has no platform gate. - The script's uv download is x86_64, so I fetched the aarch64 uv and micromamba instead and symlinked conda binutils (`ar`, `ld`, `nm`, `ranlib`). - The solcx 0.8.24 download only ships amd64, so compilation used a local aarch64 **solc 0.8.26**. I changed `SOLC_VERSION` in `amm_competition/evm/compiler.py`, in the scratch checkout only. - Reference check: NP2 on seeds 0..999 gives **526.1155722** here, which matches the brief's 526.1156. So aarch64 plus solc 0.8.26 reproduces the reference. - The CH = 525.525882178 check was not run because the brief does not say which contract CH is. - `amm-match validate` passes on the final code. ## next Condition the next-mix weights on *which retail side is still likely this step*. After a retail print, the next retail order's side is 50/50, but the routing split versus Vanilla depends on the fee gap per side. Protection should therefore be gated on the expected retail share lost on the exposed side, using the per-side fee gap to Vanilla's 30 bps, not on pR alone.