{
 "item": "r03",
 "batch": "ep8-sweep-f22",
 "np2_check": {
  "seeds": "0..999",
  "n": 1000,
  "mean_edge": 526.115572,
  "expected": 526.1156,
  "sha256": "51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0",
  "match": true
 },
 "np2_mean_10000_11999": 523.801274,
 "np2_sha256": "51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0",
 "cells": [
  {
   "retail": 0.03,
   "same": 0.09,
   "first": 0.22,
   "n": 2000,
   "mean_diff": -0.20542,
   "se": 0.019436,
   "worst": [
    {
     "seed": 10014,
     "diff": -16.881334,
     "cand_edge": 566.831356,
     "np2_edge": 583.712691
    },
    {
     "seed": 10870,
     "diff": -12.090122,
     "cand_edge": 464.496609,
     "np2_edge": 476.586731
    },
    {
     "seed": 10846,
     "diff": -5.695571,
     "cand_edge": 672.321722,
     "np2_edge": 678.017293
    },
    {
     "seed": 10227,
     "diff": -4.940484,
     "cand_edge": 420.570922,
     "np2_edge": 425.511405
    },
    {
     "seed": 10609,
     "diff": -3.845459,
     "cand_edge": 660.502554,
     "np2_edge": 664.348013
    }
   ],
   "sha256": "9e5974fd817eedd55436fff8be58f64dbd3879660bd1bf7752ce4b8d8c6f086e",
   "cand_mean_10000_11999": 523.595854,
   "wins": 760,
   "losses": 1240,
   "ties": 0
  },
  {
   "retail": 0.03,
   "same": 0.12,
   "first": 0.22,
   "n": 2000,
   "mean_diff": -0.087061,
   "se": 0.016407,
   "worst": [
    {
     "seed": 10870,
     "diff": -12.072042,
     "cand_edge": 464.514689,
     "np2_edge": 476.586731
    },
    {
     "seed": 10846,
     "diff": -5.048421,
     "cand_edge": 672.968872,
     "np2_edge": 678.017293
    },
    {
     "seed": 10227,
     "diff": -4.409843,
     "cand_edge": 421.101562,
     "np2_edge": 425.511405
    },
    {
     "seed": 10014,
     "diff": -3.785762,
     "cand_edge": 579.926929,
     "np2_edge": 583.712691
    },
    {
     "seed": 10609,
     "diff": -3.566878,
     "cand_edge": 660.781135,
     "np2_edge": 664.348013
    }
   ],
   "sha256": "21ade8885622ffbd41d45e3b8baa80e8c75fcc49961c5229de872cc910b31f98",
   "cand_mean_10000_11999": 523.714213,
   "wins": 895,
   "losses": 1105,
   "ties": 0
  },
  {
   "retail": 0.03,
   "same": 0.16,
   "first": 0.22,
   "n": 2000,
   "mean_diff": -0.124174,
   "se": 0.016097,
   "worst": [
    {
     "seed": 10870,
     "diff": -12.082971,
     "cand_edge": 464.503759,
     "np2_edge": 476.586731
    },
    {
     "seed": 10846,
     "diff": -5.65487,
     "cand_edge": 672.362423,
     "np2_edge": 678.017293
    },
    {
     "seed": 10227,
     "diff": -4.692281,
     "cand_edge": 420.819125,
     "np2_edge": 425.511405
    },
    {
     "seed": 10014,
     "diff": -4.593911,
     "cand_edge": 579.11878,
     "np2_edge": 583.712691
    },
    {
     "seed": 10609,
     "diff": -3.076966,
     "cand_edge": 661.271047,
     "np2_edge": 664.348013
    }
   ],
   "sha256": "3ba0a6dd116a102fe47fec00d9470b6ff6a0c18562e7a75c78cbc43536b563f8",
   "cand_mean_10000_11999": 523.6771,
   "wins": 845,
   "losses": 1155,
   "ties": 0
  }
 ],
 "best_cell": {
  "retail": 0.03,
  "same": 0.12,
  "first": 0.22,
  "mean_diff": -0.087061,
  "se": 0.016407,
  "sha256": "21ade8885622ffbd41d45e3b8baa80e8c75fcc49961c5229de872cc910b31f98"
 },
 "code": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {AMMStrategyBase} from \"./AMMStrategyBase.sol\";\nimport {TradeInfo} from \"./IAMMStrategy.sol\";\n\ncontract Strategy is AMMStrategyBase {\n    uint256 constant ELAPSED_CAP = 8;\n    uint256 constant SIGNAL_THRESHOLD = WAD / 650;\n    uint256 constant DIR_DECAY = 750000000000000000;\n    uint256 constant ACT_DECAY = 530000000000000000;\n    uint256 constant SIZE_DECAY = 530000000000000000;\n    uint256 constant TOX_DECAY = 910000000000000000;\n    uint256 constant SIGMA_DECAY = 690000000000000000;\n    uint256 constant LAMBDA_DECAY = 990000000000000000;\n    uint256 constant SIZE_BLEND_DECAY = 828000000000000000;\n    uint256 constant TOX_BLEND_DECAY = 51000000000000000;\n    uint256 constant ACT_BLEND_DECAY = 985000000000000000;\n    uint256 constant PHAT_ALPHA = 220000000000000000;\n    uint256 constant PHAT_ALPHA_RETAIL = 30000000000000000;\n    uint256 constant PHAT_ALPHA_SAME = 120000000000000000;\n    uint256 constant REVERT_U = 0;\n    uint256 constant DIR_IMPACT_MULT = 4;\n    uint256 constant GATE_SIGMA_MULT = 7200000000000000000;\n    uint256 constant MIN_GATE = 30000000000000000;\n    uint256 constant TRADE_TOX_BOOST = 3500 * BPS;\n    uint256 constant STALE_ATTRACT_FRAC = 1050000000000000000;\n    uint256 constant RET_CAP = WAD / 35;\n    uint256 constant TOX_CAP = WAD / 5;\n    uint256 constant TRADE_RATIO_CAP = WAD / 5;\n    uint256 constant LAMBDA_CAP = 1820000000000000000;\n    uint256 constant STEP_COUNT_CAP = 64;\n    uint256 constant BASE_FEE = 4 * BPS;\n    uint256 constant SIGMA_COEF = 200000000000000000;\n    uint256 constant LAMBDA_COEF = 12 * BPS;\n    uint256 constant FLOW_SIZE_COEF = 4842 * BPS;\n    uint256 constant TOX_COEF = 300 * BPS;\n    uint256 constant TOX_QUAD_COEF = 15000 * BPS;\n    uint256 constant ACT_COEF = 91843 * BPS;\n    uint256 constant DIR_COEF = 20 * BPS;\n    uint256 constant DIR_TOX_COEF = 100 * BPS;\n    uint256 constant STALE_DIR_COEF = 6850 * BPS;\n    uint256 constant SIGMA_TOX_COEF = 500 * BPS;\n    uint256 constant TAIL_KNEE = 600 * BPS;\n    uint256 constant TAIL_SLOPE_PROTECT = 930000000000000000;\n    uint256 constant TAIL_SLOPE_ATTRACT = 850000000000000000;\n\n    function afterInitialize(uint256 initialX, uint256 initialY) external override returns (uint256, uint256) {\n        slots[0] = BASE_FEE; slots[1] = BASE_FEE; slots[2] = 0; slots[3] = WAD; slots[4] = 0;\n        slots[5] = initialX > 0 ? wdiv(initialY, initialX) : 100 * WAD;\n        slots[6] = 950000000000000; slots[7] = 800000000000000000; slots[8] = 2000000000000000;\n        slots[9] = 0; slots[10] = 0; slots[11] = 0; slots[12] = 0;\n        return (BASE_FEE, BASE_FEE);\n    }\n\n    function afterSwap(TradeInfo calldata trade) external override returns (uint256, uint256) {\n        uint256 prevBidFee = slots[0]; uint256 prevAskFee = slots[1]; uint256 lastTs = slots[2];\n        uint256 dirState = slots[3]; uint256 actEma = slots[4]; uint256 pHat = slots[5];\n        uint256 sigmaHat = slots[6]; uint256 lambdaHat = slots[7]; uint256 sizeHat = slots[8];\n        uint256 toxEma = slots[9]; uint256 stepTradeCount = slots[10];\n\n        bool isNewStep = trade.timestamp > lastTs;\n        if (isNewStep) {\n            uint256 elapsedRaw = trade.timestamp - lastTs;\n            uint256 elapsed = elapsedRaw > ELAPSED_CAP ? ELAPSED_CAP : elapsedRaw;\n            dirState = _decayCentered(dirState, DIR_DECAY, elapsed);\n            actEma = wmul(actEma, _powWad(ACT_DECAY, elapsed));\n            sizeHat = wmul(sizeHat, _powWad(SIZE_DECAY, elapsed));\n            toxEma = wmul(toxEma, _powWad(TOX_DECAY, elapsed));\n            if (stepTradeCount > 0 && elapsedRaw > 0) {\n                uint256 lambdaInst = (stepTradeCount * WAD) / elapsedRaw;\n                if (lambdaInst > LAMBDA_CAP) lambdaInst = LAMBDA_CAP;\n                lambdaHat = wmul(lambdaHat, LAMBDA_DECAY) + wmul(lambdaInst, WAD - LAMBDA_DECAY);\n            }\n            stepTradeCount = 0;\n        }\n\n        bool firstInStep = stepTradeCount == 0;\n        uint256 spot = trade.reserveX > 0 ? wdiv(trade.reserveY, trade.reserveX) : pHat;\n        if (pHat == 0) pHat = spot;\n\n        uint256 feeUsed = trade.isBuy ? prevBidFee : prevAskFee;\n        uint256 gamma = feeUsed < WAD ? WAD - feeUsed : 0;\n        uint256 pImplied;\n        if (gamma == 0) { pImplied = spot; }\n        else { pImplied = trade.isBuy ? wmul(spot, gamma) : wdiv(spot, gamma); }\n\n        {\n            uint256 ret = pHat > 0 ? wdiv(absDiff(pImplied, pHat), pHat) : 0;\n            uint256 alpha = firstInStep ? PHAT_ALPHA : PHAT_ALPHA_RETAIL;\n            uint256 prePhat = pHat;\n            bool secondPrint = !firstInStep && stepTradeCount == 1;\n            bool sameDir = false; bool oppDir = false;\n            if (secondPrint) {\n                bool up2 = pImplied >= pHat;\n                uint256 d1 = slots[12];\n                if (d1 != 0) { sameDir = (d1 == 1) == up2; oppDir = !sameDir; }\n                if (sameDir) alpha = PHAT_ALPHA_SAME;\n            }\n            if (firstInStep) { slots[11] = pHat; slots[12] = pImplied >= pHat ? 1 : 2; }\n            uint256 adaptiveGate = wmul(sigmaHat, GATE_SIGMA_MULT);\n            if (adaptiveGate < MIN_GATE) adaptiveGate = MIN_GATE;\n            if (ret <= adaptiveGate) { pHat = wmul(pHat, WAD - alpha) + wmul(pImplied, alpha); }\n            if (oppDir && REVERT_U > 0) {\n                uint256 pre = slots[11];\n                if (pre > pHat) pHat = pHat + wmul(pre - pHat, REVERT_U);\n                else pHat = pHat - wmul(pHat - pre, REVERT_U);\n            }\n            if (firstInStep) {\n                if (ret > RET_CAP) ret = RET_CAP;\n                sigmaHat = wmul(sigmaHat, SIGMA_DECAY) + wmul(ret, WAD - SIGMA_DECAY);\n            }\n        }\n\n        // Interior retail routing equalizes fee-adjusted marginal prices.\n        // Subsequent trades in a step cannot be the initial arbitrage trade.\n        if (!firstInStep && feeUsed > 30 * BPS && gamma > 0) {\n            uint256 normalSpot = trade.isBuy\n                ? wdiv(wmul(spot, gamma), WAD - 30 * BPS)\n                : wdiv(wmul(spot, WAD - 30 * BPS), gamma);\n            pHat = wmul(pHat, 90 * WAD / 100) + wmul(normalSpot, 10 * WAD / 100);\n        }\n\n        uint256 tradeRatio = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0;\n        if (tradeRatio > TRADE_RATIO_CAP) tradeRatio = TRADE_RATIO_CAP;\n\n        if (tradeRatio > SIGNAL_THRESHOLD) {\n            uint256 push = tradeRatio * DIR_IMPACT_MULT;\n            if (push > WAD / 4) push = WAD / 4;\n            if (trade.isBuy) {\n                dirState = dirState + push;\n                if (dirState > 2 * WAD) dirState = 2 * WAD;\n            } else {\n                dirState = dirState > push ? dirState - push : 0;\n            }\n            actEma = wmul(actEma, ACT_BLEND_DECAY) + wmul(tradeRatio, WAD - ACT_BLEND_DECAY);\n            sizeHat = wmul(sizeHat, SIZE_BLEND_DECAY) + wmul(tradeRatio, WAD - SIZE_BLEND_DECAY);\n            if (sizeHat > WAD) sizeHat = WAD;\n        }\n\n        uint256 tox = pHat > 0 ? wdiv(absDiff(spot, pHat), pHat) : 0;\n        if (tox > TOX_CAP) tox = TOX_CAP;\n        toxEma = wmul(toxEma, TOX_BLEND_DECAY) + wmul(tox, WAD - TOX_BLEND_DECAY);\n        uint256 toxSignal = toxEma;\n\n        stepTradeCount = stepTradeCount + 1;\n        if (stepTradeCount > STEP_COUNT_CAP) stepTradeCount = STEP_COUNT_CAP;\n\n        uint256 flowSize = wmul(lambdaHat, sizeHat);\n        uint256 fBase = BASE_FEE + wmul(SIGMA_COEF, sigmaHat) + wmul(LAMBDA_COEF, lambdaHat) + wmul(FLOW_SIZE_COEF, flowSize);\n        uint256 fMid = fBase + wmul(TOX_COEF, toxSignal) + wmul(TOX_QUAD_COEF, wmul(toxSignal, toxSignal)) + wmul(ACT_COEF, actEma);\n        fMid = fMid + wmul(SIGMA_TOX_COEF, wmul(sigmaHat, toxSignal));\n\n        uint256 dirDev; bool sellPressure;\n        if (dirState >= WAD) { dirDev = dirState - WAD; sellPressure = true; }\n        else { dirDev = WAD - dirState; sellPressure = false; }\n\n        uint256 skew = wmul(DIR_COEF, dirDev) + wmul(DIR_TOX_COEF, wmul(dirDev, toxSignal));\n        uint256 bidFee; uint256 askFee;\n        if (sellPressure) {\n            bidFee = fMid + skew;\n            askFee = fMid > skew ? fMid - skew : 0;\n        } else {\n            askFee = fMid + skew;\n            bidFee = fMid > skew ? fMid - skew : 0;\n        }\n\n        {\n            uint256 staleShift = wmul(STALE_DIR_COEF, toxSignal);\n            uint256 attractShift = wmul(staleShift, STALE_ATTRACT_FRAC);\n            if (spot >= pHat) {\n                bidFee = bidFee + staleShift;\n                askFee = askFee > attractShift ? askFee - attractShift : 0;\n            } else {\n                askFee = askFee + staleShift;\n                bidFee = bidFee > attractShift ? bidFee - attractShift : 0;\n            }\n        }\n\n        {\n            bool tradeAligned = (trade.isBuy && spot >= pHat) || (!trade.isBuy && spot < pHat);\n            if (tradeAligned) {\n                uint256 tradeBoost = wmul(TRADE_TOX_BOOST, tradeRatio);\n                if (trade.isBuy) { bidFee = bidFee + tradeBoost; }\n                else { askFee = askFee + tradeBoost; }\n            }\n        }\n\n        if (sellPressure) {\n            bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_PROTECT));\n            askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_ATTRACT));\n        } else {\n            askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_PROTECT));\n            bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_ATTRACT));\n        }\n\n        slots[0] = bidFee; slots[1] = askFee; slots[2] = trade.timestamp;\n        slots[3] = dirState; slots[4] = actEma; slots[5] = pHat;\n        slots[6] = sigmaHat; slots[7] = lambdaHat; slots[8] = sizeHat;\n        slots[9] = toxEma; slots[10] = stepTradeCount;\n\n        return (bidFee, askFee);\n    }\n\n    function _compressTailWithSlope(uint256 fee, uint256 slope) internal pure returns (uint256) {\n        if (fee <= TAIL_KNEE) return fee;\n        return TAIL_KNEE + wmul(fee - TAIL_KNEE, slope);\n    }\n\n    function _powWad(uint256 factor, uint256 exp) internal pure returns (uint256 result) {\n        result = WAD;\n        while (exp > 0) {\n            if (exp & 1 == 1) result = wmul(result, factor);\n            factor = wmul(factor, factor);\n            exp >>= 1;\n        }\n    }\n\n    function _decayCentered(uint256 centered, uint256 decayFactor, uint256 elapsed) internal pure returns (uint256) {\n        uint256 mul = _powWad(decayFactor, elapsed);\n        if (centered >= WAD) { return WAD + wmul(centered - WAD, mul); }\n        uint256 below = wmul(WAD - centered, mul);\n        return below < WAD ? WAD - below : 0;\n    }\n\n    function getName() external pure override returns (string memory) { return \"no_cubic\"; }\n}\n",
 "blocked": null,
 "method": {
  "simulator": "github.com/benedictbrady/amm-challenge @ 6b6921f8d463314aa7c96234e1be25a25245f704, built with the item's setup script (uv/python 3.12, maturin --release); amm-match validate passed for NP2 and all three cells (contract name 'Strategy', strategy name 'no_cubic').",
  "np2_assembly": "TWO code (artifact 528a6da7...) with NP code (artifact da313379...) from '// Interior retail routing' to (excl.) 'uint256 tradeRatio =' inserted before TWO's 'uint256 tradeRatio ='; sha256 51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0.",
  "candidates": "NP2 with only three constants changed: PHAT_ALPHA_RETAIL=30000000000000000 (0.03), PHAT_ALPHA=220000000000000000 (0.22), PHAT_ALPHA_SAME in {90000000000000000, 120000000000000000, 160000000000000000}. The SAME=0.12 cell therefore differs from NP2 only in RETAIL and PHAT_ALPHA.",
  "measurement": "Per seed s: g=default_rng(s); size=g.uniform(19,21); rate=g.uniform(.6,1); sigma=g.uniform(.000882,.001008); build_config(seed=s,gbm_sigma=sigma,retail_arrival_rate=rate,retail_mean_size=size). run_batch(cand, vanilla, cfgs, 8) in chunks of 20 seeds, candidate and NP2 run separately against VanillaStrategy (never against each other). d = cand edge - NP2 edge per seed; se = std(d, ddof=1)/sqrt(n). One NP2 run on 10000..11999 shared by all three cells. No confirm block, as the brief specifies.",
  "sec_per_sim_8_workers": 0.268
 },
 "findings": [
  "NP2 check reproduced exactly: 526.115572 on seeds 0..999 (brief: 526.1156).",
  "All three cells are below NP2 on seeds 10000..11999: SAME=0.09 -0.205 (se 0.019), SAME=0.12 -0.087 (se 0.016), SAME=0.16 -0.124 (se 0.016). Each deficit is more than 5 se, so none of these cells is a gain.",
  "SAME=0.12 is NP2's own SAME value, so that cell isolates RETAIL 0.03 + FIRST 0.22 together: -0.087 +/- 0.016. The brief reports RETAIL 0.03 alone at +0.105 (se 0.0096) on fresh seeds; combined with FIRST 0.22 the pair is negative, which implies lowering PHAT_ALPHA from 0.27 to 0.22 costs roughly -0.19 at RETAIL 0.03 (inferred, not directly measured here).",
  "Moving SAME away from 0.12 in either direction hurts further (0.09 worse than 0.16), consistent with TWO's own finding that 0.12 was the best same-direction alpha.",
  "Worst seeds are dominated by seed 10870 (about -12.1 in all three cells, so it comes from the RETAIL/FIRST change, not SAME) and, for SAME=0.09 only, seed 10014 (-16.9)."
 ],
 "next": "Do not stack FIRST=0.22 with RETAIL=0.03: this grid row is negative in every SAME cell. The stack step should keep PHAT_ALPHA at 0.27 (or test 0.25/0.30) with RETAIL 0.03 and SAME 0.12, and if a FIRST sweep is wanted, measure FIRST in {0.25, 0.27, 0.30} at RETAIL 0.03/SAME 0.12 on a fresh block. Seed 10870 (-12 vs NP2) is worth inspecting to see what the lower retail alpha / first-print alpha does there."
}