{
 "approach": "Own baseline S0 (143 lines): probability read from the competitor ladder (the arbitrageur leaves best ask >= p >= best bid, so the side that moved pins p within a tick; a fully filled own quote pushes the estimate past that quote). For each side it picks the tick strictly inside the competitor spread and the size that maximise expected retail edge (lognormal retail size, prior rate 0.25/step, notional 4.5) minus the expected pick-off cost E[(move-edge)+] under a diffusion-plus-jump mixture in probability space (probit density times score move / sqrt(H*sigma^2+lam*H*sj^2)), with fixed prior lam=0.0019 and sj=0.40. S1 is S0 plus the mechanism: causal online estimation of the jump intensity and jump sd. Each step the change in probit(p_hat) times the current horizon scale gives an implied score move; a move above 4*0.02 counts as a jump. lam_hat=(5+n_jumps)/(5/0.0019+t) and sj_hat^2=(5*0.4^2+sum J^2)/(5+n_jumps) feed both the pick-off cost and the horizon scale.",
 "tried": [
  {
   "variant": "S0 UNC=0.006 AS_MULT=1.0",
   "tuning_mean": 23.378
  },
  {
   "variant": "S0 UNC=0.010 AS_MULT=1.0",
   "tuning_mean": 24.302
  },
  {
   "variant": "S0 UNC=0.014 AS_MULT=1.0",
   "tuning_mean": 24.182
  },
  {
   "variant": "S0 UNC=0.010 AS_MULT=1.5 (frozen)",
   "tuning_mean": 24.632
  },
  {
   "variant": "S1 (S0 frozen params) PRIOR_N=2 JUMP_K=4",
   "tuning_mean": 24.942
  },
  {
   "variant": "S1 PRIOR_N=5 JUMP_K=4 (frozen)",
   "tuning_mean": 24.955
  },
  {
   "variant": "S1 PRIOR_N=2 JUMP_K=6",
   "tuning_mean": 24.833
  },
  {
   "variant": "S1 PRIOR_N=1 JUMP_K=5",
   "tuning_mean": 24.932
  }
 ],
 "next": "The mechanism is small but consistently positive (+0.26, about 7 SE): it trades some retail edge (-0.77) for less arbitrage loss (+1.03), so per-simulation jump inference widens or shrinks quotes in the right direction. My own baseline is far below B (25.8 vs 99.7), mostly because it never quotes when the competitor spread is 1 tick (248 of 1000 seeds score 0) and because its probability estimate is coarse, so the absolute gap says nothing about the mechanism. Next step: graft the online lam/sj estimate into B's pick-off or width model and measure it paired against B. Also worth trying: detecting jumps from B's own probability estimate, and estimating the jump mean online.",
 "code": "\"\"\"S1: passive quoter on a book-implied probability; quotes maximise expected retail edge minus\narbitrage pick-off cost, with jump intensity and jump size inferred online (causally) from observed moves.\"\"\"\nfrom __future__ import annotations\n\nimport math\n\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelAll, PlaceOrder, Side, StepState\n\nSQ2 = math.sqrt(2.0)\nSIGMA = 0.02  # diffusion sigma (not randomized by ParameterVariance)\n\n\ndef ncdf(x):\n    return 0.5 * (1.0 + math.erf(x / SQ2))\n\n\ndef npdf(x):\n    return math.exp(-0.5 * x * x) / 2.5066282746310002\n\n\ndef nppf(p):\n    lo, hi = -8.0, 8.0\n    for _ in range(40):\n        mid = 0.5 * (lo + hi)\n        if ncdf(mid) < p:\n            lo = mid\n        else:\n            hi = mid\n    return 0.5 * (lo + hi)\n\n\ndef pos_part(m, v):\n    \"\"\"E[max(X, 0)] for X ~ N(m, v^2).\"\"\"\n    if v <= 1e-12:\n        return max(m, 0.0)\n    z = m / v\n    return m * ncdf(z) + v * npdf(z)\n\n\nclass Strategy(BaseStrategy):\n    LAM0 = 0.0019        # prior jump intensity per step\n    SJ0 = 0.40           # prior jump sigma (score units)\n    PRIOR_N = 5.0        # prior pseudo-jumps\n    JUMP_K = 4.0         # jump threshold in diffusion sds\n    RATE = 0.25          # prior retail arrivals per step\n    NOTIONAL = 4.5       # prior retail mean notional\n    RSIG = 1.2\n    UNC = 0.010          # p-estimate uncertainty (prob units)\n    AS_MULT = 1.5\n    SIZES = (1.0, 2.0, 4.0, 7.0, 11.0, 16.0, 24.0, 35.0)\n\n    def __init__(self):\n        self.p = None\n        self.pb = None\n        self.pa = None\n        self.t = 0\n        self.nj = 0.0\n        self.sj2 = 0.0\n        self.last = {}\n\n    def lam(self):\n        return (self.PRIOR_N + self.nj) / (self.PRIOR_N / self.LAM0 + self.t)\n\n    def sj(self):\n        return math.sqrt((self.PRIOR_N * self.SJ0 ** 2 + self.sj2) / (self.PRIOR_N + self.nj))\n\n    def scale(self, h):\n        return math.sqrt(max(h, 1) * SIGMA * SIGMA + self.lam() * max(h, 1) * self.sj() ** 2)\n\n    def estimate(self, b, a, h, bf, sf):\n        p_old = self.p\n        lb, la = self.last.get(Side.BUY), self.last.get(Side.SELL)\n        if self.p is None:\n            p = 0.5 * (b + a) / 100.0\n        elif a > self.pa and b >= self.pb:\n            p = (a - 0.5) / 100.0\n        elif b < self.pb and a <= self.pa:\n            p = (b + 0.5) / 100.0\n        else:\n            p = self.p\n            if la is not None and sf >= la[1] - 1e-9:\n                p = max(p, (la[0] + 0.5) / 100.0)\n            if lb is not None and bf >= lb[1] - 1e-9:\n                p = min(p, (lb[0] - 0.5) / 100.0)\n            p = min(max(p, (b + 0.5) / 100.0), (a - 0.5) / 100.0)\n        self.pb, self.pa = b, a\n        self.p = p\n        if p_old is not None:\n            self.t += 1\n            if 0.03 < p < 0.97 and 0.03 < p_old < 0.97:\n                s = self.scale(h)\n                j = (nppf(p) - nppf(p_old)) * s\n                if abs(j) > self.JUMP_K * SIGMA:\n                    self.nj += 1.0\n                    self.sj2 += j * j\n        return p\n\n    def emin(self, s, price):\n        sig = self.RSIG\n        mu = math.log(self.NOTIONAL) - 0.5 * sig * sig - math.log(price)\n        if s <= 0:\n            return 0.0\n        ls = math.log(s)\n        part = math.exp(mu + 0.5 * sig * sig) * ncdf((ls - mu - sig * sig) / sig)\n        return part + s * (1.0 - ncdf((ls - mu) / sig))\n\n    def best(self, p, h, b, a, side):\n        x = nppf(min(max(p, 0.005), 0.995))\n        s = self.scale(h)\n        dens = npdf(x) / s\n        vd = (dens * SIGMA) ** 2 + self.UNC ** 2\n        lam = self.lam()\n        vj = vd + (dens * self.sj()) ** 2\n        best = (0.0, None, 0.0)\n        for tick in range(b + 1, a):\n            price = tick / 100.0\n            edge = (p - price) if side is Side.BUY else (price - p)\n            if edge <= 0:\n                continue\n            m = -edge\n            pick = (1 - lam) * pos_part(m, math.sqrt(vd)) + lam * pos_part(m, math.sqrt(vj))\n            cprice = max(p, 0.05) if side is Side.BUY else price\n            for q in self.SIZES:\n                ev = 0.5 * self.RATE * edge * self.emin(q, cprice) - self.AS_MULT * q * pick\n                if ev > best[0]:\n                    best = (ev, tick, q)\n        return best\n\n    def on_step(self, state: StepState):\n        b = state.competitor_best_bid_ticks or 0\n        a = state.competitor_best_ask_ticks or 100\n        h = state.steps_remaining\n        p = self.estimate(b, a, h, state.buy_filled_quantity, state.sell_filled_quantity)\n        self.last = {}\n        acts = [CancelAll()]\n        free = state.free_cash\n        ev, tick, q = self.best(p, h, b, a, Side.BUY)\n        if tick is not None:\n            q = min(q, math.floor(free / (tick / 100.0) * 0.9 * 100) / 100.0)\n            if q >= 0.01:\n                acts.append(PlaceOrder(side=Side.BUY, price_ticks=tick, quantity=q))\n                self.last[Side.BUY] = (tick, q)\n                free -= q * tick / 100.0\n        ev, tick, q = self.best(p, h, b, a, Side.SELL)\n        if tick is not None:\n            cover = state.yes_inventory\n            unc = max(0.0, q - cover)\n            if unc > 0:\n                room = free * 0.9 / (1.0 - tick / 100.0)\n                q = min(q, cover + room)\n            q = math.floor(q * 100) / 100.0\n            if q >= 0.01:\n                acts.append(PlaceOrder(side=Side.SELL, price_ticks=tick, quantity=q))\n                self.last[Side.SELL] = (tick, q)\n        return acts\n",
 "code_sha256": "b1b93018ea12584b12f3d71ca1978e8376cd2f0b538b426c7b019403aa2a337d",
 "code_s0": "\"\"\"S0: passive quoter on a book-implied probability; quotes maximise expected retail edge minus\narbitrage pick-off cost, using fixed prior jump intensity and jump size.\"\"\"\nfrom __future__ import annotations\n\nimport math\n\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelAll, PlaceOrder, Side, StepState\n\nSQ2 = math.sqrt(2.0)\nSIGMA = 0.02  # diffusion sigma (not randomized by ParameterVariance)\n\n\ndef ncdf(x):\n    return 0.5 * (1.0 + math.erf(x / SQ2))\n\n\ndef npdf(x):\n    return math.exp(-0.5 * x * x) / 2.5066282746310002\n\n\ndef nppf(p):\n    lo, hi = -8.0, 8.0\n    for _ in range(40):\n        mid = 0.5 * (lo + hi)\n        if ncdf(mid) < p:\n            lo = mid\n        else:\n            hi = mid\n    return 0.5 * (lo + hi)\n\n\ndef pos_part(m, v):\n    \"\"\"E[max(X, 0)] for X ~ N(m, v^2).\"\"\"\n    if v <= 1e-12:\n        return max(m, 0.0)\n    z = m / v\n    return m * ncdf(z) + v * npdf(z)\n\n\nclass Strategy(BaseStrategy):\n    LAM0 = 0.0019        # prior jump intensity per step\n    SJ0 = 0.40           # prior jump sigma (score units)\n    RATE = 0.25          # prior retail arrivals per step\n    NOTIONAL = 4.5       # prior retail mean notional\n    RSIG = 1.2\n    UNC = 0.010          # p-estimate uncertainty (prob units)\n    AS_MULT = 1.5\n    SIZES = (1.0, 2.0, 4.0, 7.0, 11.0, 16.0, 24.0, 35.0)\n\n    def __init__(self):\n        self.p = None\n        self.pb = None\n        self.pa = None\n        self.last = {}\n\n    def lam(self):\n        return self.LAM0\n\n    def sj(self):\n        return self.SJ0\n\n    def scale(self, h):\n        return math.sqrt(max(h, 1) * SIGMA * SIGMA + self.lam() * max(h, 1) * self.sj() ** 2)\n\n    def estimate(self, b, a, h, bf, sf):\n        p_old = self.p\n        lb, la = self.last.get(Side.BUY), self.last.get(Side.SELL)\n        if self.p is None:\n            p = 0.5 * (b + a) / 100.0\n        elif a > self.pa and b >= self.pb:\n            p = (a - 0.5) / 100.0\n        elif b < self.pb and a <= self.pa:\n            p = (b + 0.5) / 100.0\n        else:\n            p = self.p\n            if la is not None and sf >= la[1] - 1e-9:\n                p = max(p, (la[0] + 0.5) / 100.0)\n            if lb is not None and bf >= lb[1] - 1e-9:\n                p = min(p, (lb[0] - 0.5) / 100.0)\n            p = min(max(p, (b + 0.5) / 100.0), (a - 0.5) / 100.0)\n        self.pb, self.pa = b, a\n        self.p = p\n        return p\n\n    def emin(self, s, price):\n        sig = self.RSIG\n        mu = math.log(self.NOTIONAL) - 0.5 * sig * sig - math.log(price)\n        if s <= 0:\n            return 0.0\n        ls = math.log(s)\n        part = math.exp(mu + 0.5 * sig * sig) * ncdf((ls - mu - sig * sig) / sig)\n        return part + s * (1.0 - ncdf((ls - mu) / sig))\n\n    def best(self, p, h, b, a, side):\n        x = nppf(min(max(p, 0.005), 0.995))\n        s = self.scale(h)\n        dens = npdf(x) / s\n        vd = (dens * SIGMA) ** 2 + self.UNC ** 2\n        lam = self.lam()\n        vj = vd + (dens * self.sj()) ** 2\n        best = (0.0, None, 0.0)\n        for tick in range(b + 1, a):\n            price = tick / 100.0\n            edge = (p - price) if side is Side.BUY else (price - p)\n            if edge <= 0:\n                continue\n            m = -edge\n            pick = (1 - lam) * pos_part(m, math.sqrt(vd)) + lam * pos_part(m, math.sqrt(vj))\n            cprice = max(p, 0.05) if side is Side.BUY else price\n            for q in self.SIZES:\n                ev = 0.5 * self.RATE * edge * self.emin(q, cprice) - self.AS_MULT * q * pick\n                if ev > best[0]:\n                    best = (ev, tick, q)\n        return best\n\n    def on_step(self, state: StepState):\n        b = state.competitor_best_bid_ticks or 0\n        a = state.competitor_best_ask_ticks or 100\n        h = state.steps_remaining\n        p = self.estimate(b, a, h, state.buy_filled_quantity, state.sell_filled_quantity)\n        self.last = {}\n        acts = [CancelAll()]\n        free = state.free_cash\n        ev, tick, q = self.best(p, h, b, a, Side.BUY)\n        if tick is not None:\n            q = min(q, math.floor(free / (tick / 100.0) * 0.9 * 100) / 100.0)\n            if q >= 0.01:\n                acts.append(PlaceOrder(side=Side.BUY, price_ticks=tick, quantity=q))\n                self.last[Side.BUY] = (tick, q)\n                free -= q * tick / 100.0\n        ev, tick, q = self.best(p, h, b, a, Side.SELL)\n        if tick is not None:\n            cover = state.yes_inventory\n            unc = max(0.0, q - cover)\n            if unc > 0:\n                room = free * 0.9 / (1.0 - tick / 100.0)\n                q = min(q, cover + room)\n            q = math.floor(q * 100) / 100.0\n            if q >= 0.01:\n                acts.append(PlaceOrder(side=Side.SELL, price_ticks=tick, quantity=q))\n                self.last[Side.SELL] = (tick, q)\n        return acts\n",
 "tuning_score": {
  "seeds": "115000..115499",
  "n": 500,
  "s1_mean": 24.955,
  "s0_mean": 24.632
 },
 "paired": {
  "seeds": "200000..200999",
  "n": 1000,
  "complete": true,
  "mechanism_diff": 0.26,
  "mechanism_se": 0.0351,
  "mechanism_retail_diff": -0.7705,
  "mechanism_retail_se": 0.0362,
  "mechanism_arb_diff": 1.0305,
  "mechanism_arb_se": 0.0495,
  "reference_diff": -73.9135,
  "reference_se": 4.9088,
  "s1_mean": 25.7824,
  "s0_mean": 25.5224,
  "b_mean": 99.6959,
  "failures": []
 },
 "graft": "Keep the previous probability estimate p_prev. Each step: t+=1; J=(probit(p)-probit(p_prev))*sqrt(H*0.02^2+lam*H*sj^2); if |J|>0.08 (and 0.03<p<0.97): n+=1, S+=J^2. Then lam=(5+n)/(5/0.0019+t) and sj=sqrt((5*0.16+S)/(5+n)). Use lam and sj wherever the strategy assumes jump parameters: its pick-off cost E[(dp-edge)+] for jump moves dp=pdf(probit p)*J/scale, its quote width, and its horizon scale.",
 "seconds_per_simulation": 0.348,
 "notes": "Single process per seed range (4 OS processes on disjoint ranges), default ChallengeConfig/ParameterVariance, run_batch(..., n_simulations=1, seed_start=seed, workers=1) per seed, no sandbox. No failures. B reference values decoded from fixture.H, sha256 verified. Seeds 900000..903999 not used."
}