{
 "approach": "Measurement only, no development and no code changes: frozen candidate simplify against current best combine-cash (B), paired on every seed 224000..224999, unmodified simulator commit b244530ee2a6247b5f930830eeca9dd950da0e7e, default ChallengeConfig() and ParameterVariance(), 2000 steps, Python 3.12.3, run_batch(factory, n_simulations=1, seed_start=s, workers=1) per seed, no --sandbox.",
 "tried": [
  "Fetched both artifacts; SHA-256 of each code field matched the brief before anything ran.",
  "Timed the first 20 seeds serially on an otherwise idle machine: candidate 0.775 s/sim, B 0.891 s/sim, so about 28 minutes of serial simulation for the whole block, under the 35 minute limit, and the full 1000 seeds were run.",
  "Ran both strategies in six OS processes on disjoint seed ranges (224000-224333, 224334-224666, 224667-224999). Contention raised this to about 2 s/sim, the first pass hit a 10 minute tool time limit and was killed, and the remaining seeds were resumed from the per-seed logs. Each seed appears exactly once for each strategy; none was dropped or rerun into the totals.",
  "Reproducibility: the 20 timing seeds, run in a separate process, matched the block run exactly on total, retail and arb edge and failed. Seeds 224333, 224512 and 224999 rerun alone in fresh processes matched exactly on total edge for both strategies, so the resume and process split did not change results.",
  "Result on this block: candidate lost by 2.50 (se 0.60, about 4.2 se). It gave back 5.33 of retail edge (se 0.50) and saved 2.83 of arbitrage loss (se 0.39). Candidate beat B on 450 seeds, lost on 548, tied on 2. No simulation failed."
 ],
 "next": "This block alone gives no reason to promote simplify over B: its arbitrage saving is real on these seeds but smaller than its retail loss. Pool this block with the other simplify blocks using sum_d and sum_d2. The arb and retail split suggests testing what simplify removed as a graft on B, measuring whether part of the arbitrage saving can be kept at less retail cost. That is a suggestion from this split, not something measured here.",
 "code": "\"\"\"Probe-informed market maker with one cheap-stock purchase rule.\n\nQuotes at the competitor inside tick, retaining priority where possible.\nThe remaining YES stock rule rests a bid at one cent before probability\nfalls through that tick, so low asks can be covered cheaply.\n\"\"\"\nimport math\nfrom statistics import NormalDist\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelOrder, PlaceOrder, Side\nSQ2 = math.sqrt(2.0)\nSQ2PI = math.sqrt(2.0 * math.pi)\n\ndef cdf(x):\n    return 0.5 * (1.0 + math.erf(x / SQ2))\n\ndef pdf(x):\n    return math.exp(-0.5 * x * x) / SQ2PI\n\n_normal = NormalDist()\n\ndef inv(p):\n    return _normal.inv_cdf(min(max(p, 1e-9), 1 - 1e-9))\n\ndef lpm(k):\n    return pdf(k) + k * cdf(k)\n\ndef fl(q):\n    return math.floor(q * 100 + 1e-09) / 100\nNODES = [(-2.2, 0.06), (-1.3, 0.17), (-0.6, 0.27), (0.6, 0.27), (1.3, 0.17), (2.2, 0.06)]\nPROBE = 0.01\n\nclass Strategy(BaseStrategy):\n\n    def __init__(self):\n        self.n = 0\n        self.ahead = set()\n        self.res = {}\n        self.bc = None\n        self.bw = None\n        self.st = 0.5\n        self.pcb = self.pca = None\n        self.pb = set()\n        self.pa = set()\n        self.tb = 0\n        self.s = None\n\n    def _oid(self, tag):\n        self.n += 1\n        return tag + str(self.n)\n\n    def on_step(self, state):\n        H = max(1, state.steps_remaining)\n        cb = state.competitor_best_bid_ticks or 0\n        ca = state.competitor_best_ask_ticks or 100\n        if self.s is None:\n            self.s = max(1, (ca - cb + 1) // 2)\n        # Surviving orders bracket the preceding fair probability.\n        lo, hi = (cb, ca)\n        for o in state.own_orders:\n            if o.side is Side.BUY:\n                lo = max(lo, o.price_ticks)\n            else:\n                hi = min(hi, o.price_ticks)\n        sb = {o.price_ticks for o in state.own_orders if o.side is Side.BUY and o.remaining_quantity <= PROBE + 1e-09}\n        sa = {o.price_ticks for o in state.own_orders if o.side is Side.SELL and o.remaining_quantity <= PROBE + 1e-09}\n        ea = self.pa - sa\n        eb = self.pb - sb\n        if sa and ea:\n            lo = max(lo, min(max(ea), hi))\n        if eb and (sb or min(eb) <= 1.0):\n            hi = min(hi, max(min(eb), lo))\n        if self.pcb is not None:\n            if ca > self.pca + 1:\n                lo = max(lo, ca - 1)\n            if cb < self.pcb - 1:\n                hi = min(hi, cb + 1)\n        self.pcb, self.pca = (cb, ca)\n        if lo > hi:\n            lo, hi = (hi, lo)\n        # Predict and truncate the belief inside the observed bracket.\n        wid = max(hi - lo, 1e-06)\n        nb = max(2, min(48, int(round(wid * 8.0))))\n        cs = [lo + (i + 0.5) * wid / nb for i in range(nb)]\n        if self.bc is None:\n            ws = [1.0 / nb] * nb\n        else:\n            sg = max(self.st, 0.6 * wid / nb)\n            k = -0.5 / (sg * sg)\n            ws = []\n            uni = 0.01 * sg\n            for c in cs:\n                t = uni\n                for ci, wi in zip(self.bc, self.bw):\n                    d = c - ci\n                    d2 = d * d * k\n                    if d2 > -12.5:\n                        t += wi * math.exp(d2)\n                ws.append(t)\n            tot = sum(ws)\n            ws = [w / tot for w in ws]\n        self.bc, self.bw = (cs, ws)\n        mean_t = sum((c * w for c, w in zip(cs, ws)))\n        var_t = max(sum((c * c * w for c, w in zip(cs, ws))) - mean_t * mean_t, 0.0)\n        phat = min(max(mean_t / 100.0, 0.002), 0.998)\n        var = 0.02 ** 2 + 0.0019 * 0.35 ** 2\n        sd = math.sqrt(H * var)\n        self.tb = self.tb + 1 if hi <= 1 else 0\n        if self.tb > 0:\n            phat = min(phat, max(0.0005, cdf(inv(0.01) - 1.0 * 0.02 * math.sqrt(self.tb) / sd)))\n        z = inv(phat)\n        Z = z * sd\n        sp = pdf(z) / sd * 0.02\n        self.st = sp * 100.0\n        s = math.sqrt(sp * sp + var_t / 10000.0 + 1e-08)\n        sd1 = math.sqrt(max(1.0, H - 1.0) * var)\n        jp = [(cdf((Z + n * 0.35) / sd1), w) for n, w in NODES]\n        lj = 0.0019\n\n        # Expected one-step stale-quote losses, including rare jumps.\n        def AB(x):\n            k = (x - phat) / s\n            a = s * lpm(k)\n            b = a - (x - phat)\n            ja = sum((w * max(0.0, x - p) for p, w in jp))\n            jb = sum((w * max(0.0, p - x) for p, w in jp))\n            return ((1 - lj) * a + lj * ja, (1 - lj) * b + lj * jb)\n        if H == 1:\n\n            def AB(x):\n                return ((1 - phat) * x, phat * (1 - x))\n        rho = 0.25 * 0.5\n        mu = math.log(5.0) - 0.5 * 1.2 ** 2\n        kA = 0.15 if phat < 0.05 else 0.9\n\n        # Quote until marginal retail edge no longer covers adverse selection.\n        def qsize(loss, gain, px):\n            loss *= kA\n            if gain <= 0:\n                return 0.0\n            tail = loss / (rho * gain)\n            if tail >= 1.0:\n                return 0.0\n            return min(3000.0, math.exp(mu + 1.2 * inv(1 - max(tail, 1e-06))) / px)\n\n        def qbid(t):\n            if not 1 <= t <= 99:\n                return 0.0\n            a, b = AB(t / 100.0)\n            if phat * 100 - t < 0.0:\n                return 0.0\n            if phat < 0.05:\n                a *= 0.08 / 0.15\n            return qsize(a, b, max(phat, 0.05))\n\n        def qask(t):\n            if not 1 <= t <= 99:\n                return 0.0\n            a, b = AB(t / 100.0)\n            if t - phat * 100 < 0.0:\n                return 0.0\n            return qsize(b, a, t / 100.0)\n        bids = [o for o in state.own_orders if o.side is Side.BUY and o.remaining_quantity > PROBE + 1e-09]\n        asks = [o for o in state.own_orders if o.side is Side.SELL and o.remaining_quantity > PROBE + 1e-09]\n\n        def top(orders, comp, step):\n            if sum((o.remaining_quantity for o in orders if o.price_ticks == comp and o.order_id in self.ahead)) >= 2.0:\n                return comp\n            return comp + step\n        bid_t = top(bids, cb, 1)\n        ask_t = top(asks, ca, -1)\n        qb = qbid(bid_t)\n        qa = qask(ask_t)\n        Y = state.yes_inventory\n        ptick = phat * 100\n        # The only inventory purchase rule: rest at one cent before crossing.\n        q1 = 0.0\n        if 1.0 < ptick and cb <= 1:\n            q1 = max(0.0, 0.6 * min(H, 2000.0) / (self.s / 100.0) - Y)\n        actions = []\n        free = state.free_cash - 2.0\n\n        def cancel(o):\n            nonlocal free\n            actions.append(CancelOrder(o.order_id))\n            x = o.price_ticks / 100.0\n            if o.side is Side.BUY:\n                free += x * o.remaining_quantity\n            else:\n                free += (1 - x) * min(self.res.get(o.order_id, 0.0), o.remaining_quantity)\n            self.ahead.discard(o.order_id)\n            self.res.pop(o.order_id, None)\n        for o in state.own_orders:\n            if o.remaining_quantity <= PROBE + 1e-09:\n                cancel(o)\n        kept_ids = set()\n\n        # Preserve price-time priority while sizes remain close to target.\n        def manage(orders, t, q):\n            kept = 0.0\n            for o in orders:\n                if o.price_ticks == t and q > 0 and (kept + o.remaining_quantity <= max(q * 1.5, 1.0)):\n                    kept += o.remaining_quantity\n                    kept_ids.add(o.order_id)\n                else:\n                    cancel(o)\n            return kept\n        kb = manage(bids, bid_t, qb)\n        ka = manage(asks, ask_t, qa)\n        add_b = qb - kb if kb < qb * 0.7 and bid_t != cb else 0.0\n        add_a = qa - ka if ka < qa * 0.7 and ask_t != ca else 0.0\n        budget = 0.9 * max(free, 0.0)\n        cost = add_b * bid_t / 100.0\n        if cost > budget:\n            f = budget / cost\n            add_b *= f\n            cost = budget\n        out = []\n        q1 = min(q1, 1.0 * max(budget - cost, 0.0) * 100.0)\n        if q1 >= 0.01:\n            out.append(PlaceOrder(side=Side.BUY, price_ticks=1, quantity=fl(q1)))\n            free -= fl(q1) / 100.0 + 1e-06\n        if bid_t >= 1 and add_b >= 0.01:\n            q = fl(add_b)\n            oid = self._oid('b')\n            out.append(PlaceOrder(side=Side.BUY, price_ticks=bid_t, quantity=q, client_order_id=oid))\n            free -= q * bid_t / 100.0 + 1e-06\n            if bid_t > cb:\n                self.ahead.add(oid)\n        if ask_t <= 99 and add_a >= 0.01:\n            x = ask_t / 100.0\n            covk = sum((o.remaining_quantity - min(self.res.get(o.order_id, 0.0), o.remaining_quantity) for o in asks if o.order_id in kept_ids))\n            cov = max(0.0, Y - covk - 0.1)\n            unc = max(0.0, add_a - cov)\n            if unc > 0:\n                ub = max(0.0, free - (1 - 0.7) * max(state.cash, 0.0)) if x >= 0.1 else 0.0\n                if H < 300.0 and phat < 0.05:\n                    ub = max(0.0, free * (1 - H / 300.0))\n                unc = min(unc, ub / (1 - x))\n            q = fl(min(add_a, cov + unc))\n            if q >= 0.01:\n                oid = self._oid('a')\n                out.append(PlaceOrder(side=Side.SELL, price_ticks=ask_t, quantity=q, client_order_id=oid))\n                r = max(0.0, q - cov)\n                self.res[oid] = r\n                free -= r * (1 - x) + 1e-06\n                if ask_t < ca:\n                    self.ahead.add(oid)\n        # Small two-sided probes reveal the next probability bracket.\n        f = int(math.floor(ptick + 1e-09))\n        r = max(int(2), int(math.ceil(2.0 * s * 100)))\n        self.pb = set()\n        self.pa = set()\n        if free > 1.0:\n            for t in range(f, f + r + 1):\n                if cb < t < ca and 1 <= t <= 99:\n                    out.append(PlaceOrder(side=Side.BUY, price_ticks=t, quantity=PROBE))\n                    self.pb.add(t)\n            for t in range(f + 1 - r, f + 2):\n                if cb < t < ca and 1 <= t <= 99:\n                    out.append(PlaceOrder(side=Side.SELL, price_ticks=t, quantity=PROBE))\n                    self.pa.add(t)\n        return actions + out\n",
 "code_sha256": "bd69d74807d70fc0acd7b35765b602bd05813b920c2ad706b10160baff45de22",
 "incumbent_code_sha256": "baef955ec10728839f7c3357016ec9eb0550e7ec689bbd5171b1cdd5c9e37273",
 "tuning": null,
 "paired": {
  "seeds": "224000..224999",
  "n": 1000,
  "complete": true,
  "mean_diff": -2.503093545271599,
  "se": 0.6012178793422059,
  "sum_d": -2503.0935452715994,
  "sum_d2": 367366.9527986788,
  "candidate_mean": 104.6621207553677,
  "incumbent_mean": 107.1652143006393,
  "retail_diff": -5.3321165790624,
  "retail_se": 0.5034993516478963,
  "arb_diff": 2.8290230337884,
  "arb_se": 0.39086677722625773,
  "nonzero_diff_seeds": 998,
  "failures": []
 },
 "seconds_per_simulation": 0.8331755518913269
}
