{
 "key": "f-retail-reach",
 "approach": "Overlay on N (blind). Online Bayesian estimate of retail arrival rate and mean notional on an 8x8 grid over the ParameterVariance ranges (lambda 0.154..0.352, mean 2.64..6.336, sigma 1.2), from per-level diffs of own resting quantity at levels strictly inside the competitor: steps with no fill, and steps whose deepest touched level is partly filled (retail only, because the arb takes whole orders). Steps that consume the whole own quote are dropped and the likelihood is conditioned on that. The H-step compound-Poisson tail of retail notional is computed from a Monte Carlo table of k-fold sums of unit-mean lognormals (k<=60, fixed seed) mixed with Poisson weights. Its 95% quantile s* is recomputed every 50 steps. For N's new orders at levels at or behind the competitor best (not strictly inside), total own quantity at a level is capped at max(0, s* - A0*ticks_behind)/price; extra placements are cut down or dropped, and cancels of dropped ids are filtered out. Inside levels and resting orders are never touched. Frozen: H=12, A0=24, acting only at spread 3.",
 "tried": [
  "N verified: sha256 bf0d179f...ffae, seed 310000 total edge 17.1160017503 (expected 17.116002, matches).",
  "Static counterfactual on N over tuning seeds 310000..310199 (queue position of each fill vs. a per-level cap, in units of E1 = lambda*m/(2*price)): capping at levels strictly inside the competitor always loses (e.g. s=2 cap 20*E1: -7.5/run), because deep queue units still earn retail over several steps. Capping at the competitor's level or behind it gains about +1.1 (s=1, cap 80 E1 at level 0), +0.9 at level 0 and +1.5 at level -1 (s=2), and +0.3 (s=3,4). This assumes static dynamics and counts resting orders.",
  "Variant A (H=25, A0=12, all spreads) tuning: -0.310 +/- 0.274 (s1 -1.13, s2 -0.13, s3 -0.015, s4 -0.013).",
  "Variant B (H=12, A0=24, all spreads) tuning: -0.333 +/- 0.295 (s1 -0.97, s2 -0.36, s3 +0.031 +/- 0.049, s4 -0.048). B was frozen with spread set {3}, the only cell with a non-negative tuning mean.",
  "The first estimator version, which treated full-consumption events as retail plus 0.02 arb noise, drove lambda to the top of the grid (arb sweeps of N's 0.01 probes). It was replaced by the conditional likelihood before tuning. Lambda is still biased upward (e.g. true 0.21 -> 0.31, true 0.18 -> 0.27); the mean notional is closer (2.92 -> 3.15, 4.34 -> 4.13).",
  "Holdout: S1 changes N's edge on 25 of 500 seeds, all at spread 3. Net -0.104 +/- 0.072, mostly extra arb loss (-0.33/run at s=3): the trimmed orders were mainly retail-safe, and N re-quotes into the gap.",
  "Blind-rule note: before the work, the 3 import lines of n.py were grepped once to check dependencies. Nothing else of N's source was read; N's behaviour was seen only through its actions."
 ],
 "next": "The static gains came mostly from resting orders that drift to or behind the competitor best after the competitor book moves, plus N's very large deep bids. This overlay only trims new placements. Next: cancel or trim resting quantity behind the competitor beyond the reach quantile (watch for N re-placing). Fix the upward lambda bias (multiple arrivals, arb and retail mixed in one step) before trusting tight caps. Treat this item as no gain: do not promote.",
 "spreads_acted": [
  3
 ],
 "off_equals_n": true,
 "code": "import random as _rnd\nfrom orderbook_pm_challenge.types import CancelOrder as _CO, PlaceOrder as _PO, Side as _Sd\n\n_SPREADS = (3,)\n_H = 12\n_Q = 0.95\n_A0 = 24.0\n_SIG = 1.2\n_LG = [0.154 + 0.198 * i / 7 for i in range(8)]\n_MG = [2.64 + 3.696 * i / 7 for i in range(8)]\n_SUMS = None\n\n\ndef _sums():\n    global _SUMS\n    if _SUMS is None:\n        r = _rnd.Random(7)\n        mu = -0.5 * _SIG * _SIG\n        acc = [0.0] * 1500\n        out = [[0.0]]\n        for _k in range(60):\n            acc = [a + r.lognormvariate(mu, _SIG) for a in acc]\n            out.append(sorted(acc))\n        _SUMS = out\n    return _SUMS\n\n\ndef _tail(s, lam, m):\n    # P(S > s), S compound Poisson(lam) of lognormal(mean m, sigma 1.2)\n    t = _sums()\n    w = _mexp(-lam)\n    p = 0.0\n    x = s / m\n    for k in range(1, len(t)):\n        w *= lam / k\n        a = t[k]\n        lo, hi = 0, len(a)\n        while lo < hi:\n            md = (lo + hi) // 2\n            if a[md] <= x:\n                lo = md + 1\n            else:\n                hi = md\n        p += w * (len(a) - lo) / len(a)\n    return p\n\n\ndef _mexp(v):\n    import math\n    return math.exp(v)\n\n\ndef _lnpdf(x, m):\n    import math\n    mu = math.log(m) - 0.5 * _SIG * _SIG\n    z = (math.log(x) - mu) / _SIG\n    return math.exp(-0.5 * z * z) / (x * _SIG * 2.5066282746)\n\n\ndef _lnsf(x, m):\n    import math\n    mu = math.log(m) - 0.5 * _SIG * _SIG\n    return 0.5 * math.erfc((math.log(max(x, 1e-9)) - mu) / (_SIG * 1.41421356))\n\n\nclass Strategy:\n    def __init__(self):\n        self._n = _N()\n        self._on = None\n        self._ll = [[0.0] * 8 for _ in range(8)]\n        self._exp = None\n        self._sstar = None\n        self._t = 0\n\n    def _upd(self, st):\n        import math\n        if self._exp is None:\n            return\n        cur = {}\n        for o in st.own_orders:\n            if o.submitted_step < st.step:\n                k = (o.side, o.price_ticks)\n                cur[k] = cur.get(k, 0.0) + o.remaining_quantity\n        for side in (_Sd.BUY, _Sd.SELL):\n            lv = self._exp.get(side)\n            if not lv:\n                continue\n            levels = sorted(lv.items(), reverse=(side is _Sd.BUY))\n            F = 0.0\n            K = 0.0\n            part = False\n            for px, q in levels:\n                f = max(0.0, q - cur.get((side, px), 0.0))\n                F += f * px / 100.0\n                K += q * px / 100.0\n                if 1e-6 < f < q - 1e-6:\n                    part = True\n            if F >= K - 1e-6:\n                continue\n            ll = self._ll\n            for i, lam in enumerate(_LG):\n                h = lam / 2\n                for j, m in enumerate(_MG):\n                    z = math.log(1.0 + h * (1.0 - _lnsf(K, m)))\n                    if F <= 1e-9:\n                        ll[i][j] -= z\n                    elif part:\n                        ll[i][j] += math.log(h) + math.log(_lnpdf(F, m) + 1e-12) - z\n\n    def _est(self):\n        import math\n        ll = self._ll\n        mx = max(max(r) for r in ll)\n        z = sl = sm = 0.0\n        for i in range(8):\n            for j in range(8):\n                w = math.exp(ll[i][j] - mx)\n                z += w\n                sl += w * _LG[i]\n                sm += w * _MG[j]\n        return sl / z, sm / z\n\n    def _cap_notional(self):\n        lam, m = self._est()\n        L = lam / 2 * _H\n        lo, hi = 0.0, 50.0 * m * max(1.0, L)\n        for _ in range(30):\n            md = 0.5 * (lo + hi)\n            if _tail(md, L, m) > 1 - _Q:\n                lo = md\n            else:\n                hi = md\n        return hi\n\n    def on_step(self, st):\n        acts = self._n.on_step(st)\n        if self._on is None:\n            b, a = st.competitor_best_bid_ticks, st.competitor_best_ask_ticks\n            s = max(1, (a - b + 1) // 2) if (a is not None and b is not None) else 0\n            self._on = s in _SPREADS\n        if not self._on:\n            return acts\n        self._upd(st)\n        if self._sstar is None or st.step - self._t >= 50:\n            self._sstar = self._cap_notional()\n            self._t = st.step\n        cb = st.competitor_best_bid_ticks\n        ca = st.competitor_best_ask_ticks\n        live = {o.order_id: o for o in st.own_orders}\n        canc = set()\n        for x in acts:\n            if isinstance(x, _CO):\n                canc.add(x.order_id)\n            elif not isinstance(x, _PO):\n                canc.update(live)\n        lvl = {}\n        for o in st.own_orders:\n            if o.order_id not in canc:\n                k = (o.side, o.price_ticks)\n                lvl[k] = lvl.get(k, 0.0) + o.remaining_quantity\n\n        def cap(side, px):\n            if side is _Sd.BUY:\n                if cb is None or px > cb:\n                    return None\n                ahead = cb - px\n            else:\n                if ca is None or px < ca:\n                    return None\n                ahead = px - ca\n            r = self._sstar - _A0 * ahead\n            return max(0.0, r) / (px / 100.0)\n\n        out = []\n        placed = set()\n        for x in acts:\n            if isinstance(x, _CO):\n                if x.order_id in live or x.order_id in placed:\n                    out.append(x)\n                continue\n            if isinstance(x, _PO):\n                k = (x.side, x.price_ticks)\n                c = cap(x.side, x.price_ticks)\n                have = lvl.get(k, 0.0)\n                q = float(x.quantity)\n                if c is not None and have + q > c:\n                    q = int(max(0.0, c - have) * 100 + 1e-9) / 100.0\n                    if q < 0.01:\n                        continue\n                    x = _PO(side=x.side, price_ticks=x.price_ticks, quantity=q, client_order_id=x.client_order_id)\n                lvl[k] = have + q\n                if x.client_order_id:\n                    placed.add(x.client_order_id)\n            out.append(x)\n        exp = {}\n        if cb is not None and ca is not None:\n            for (side, px), q in lvl.items():\n                if q > 0 and ((side is _Sd.BUY and px > cb) or (side is _Sd.SELL and px < ca)):\n                    exp.setdefault(side, {})[px] = q\n        self._exp = exp\n        return out\n",
 "code_sha256": "1b2361fa0566e3f25083f9cfd44b430da624d5ce321ae4bda582504dad6a5316",
 "assembled_sha256": "43c611444e9194efdf64fafba88b095574dfdd6efdee370d47d183051d6afe8c",
 "tuning": {
  "n": 200,
  "mean_diff": 0.008152,
  "se": 0.012858
 },
 "paired": {
  "first_seed": 410000,
  "last_seed": 410499,
  "n": 500,
  "complete": true,
  "incumbent_mean": 104.392176,
  "mean_diff": -0.104299,
  "se": 0.07199,
  "sum_d": -52.149546,
  "sum_d2": 1298.49414,
  "retail_diff": -0.014461,
  "arb_diff": -0.089838,
  "failures": 0
 },
 "by_spread": {
  "1": {
   "runs": 115,
   "incumbent_mean": 28.495165,
   "mean_diff": 0.0,
   "se": 0.0,
   "sum_d": 0.0,
   "sum_d2": 0.0,
   "retail_diff": 0.0,
   "arb_diff": 0.0
  },
  "2": {
   "runs": 116,
   "incumbent_mean": 97.766287,
   "mean_diff": 0.0,
   "se": 0.0,
   "sum_d": 0.0,
   "sum_d2": 0.0,
   "retail_diff": 0.0,
   "arb_diff": 0.0
  },
  "3": {
   "runs": 138,
   "incumbent_mean": 128.405656,
   "mean_diff": -0.377895,
   "se": 0.260075,
   "sum_d": -52.149546,
   "sum_d2": 1298.49414,
   "retail_diff": -0.052394,
   "arb_diff": -0.325501
  },
  "4": {
   "runs": 131,
   "incumbent_mean": 151.589879,
   "mean_diff": 0.0,
   "se": 0.0,
   "sum_d": 0.0,
   "sum_d2": 0.0,
   "retail_diff": 0.0,
   "arb_diff": 0.0
  }
 },
 "seconds_per_simulation": 0.3758
}