{"approach": "Keeps the base (0.01-share probes, sub-tick grid filter, quotes one tick inside the competitor sized by the marginal retail-against-arbitrage rule, resting orders for queue priority, YES ammunition at low prices) and changes how the pinned-near-zero stretch is supplied. A diagnostic split of edge by steps remaining and p band showed the late game's money is retail buys at p under 1c in runs settling at 0, and that nearly all the missed notional there was runs with a one-tick spread standing aside at tick 1, not cash or quote size. So a large trap bid now rests just under p whenever p is below 4c: the arbitrageur fills it when p falls through that tick, at a loss of only the last step's overshoot, instead of the up-to-a-tick paid by buying at the tick above p. Its size is 0.5 * min(H, 500) / x shares, less YES held, with x the larger of the run's competitor spread (read from the first step's book) and the trap tick, capped at 20000 shares. Once 500 YES are held, tick 1 is quoted instead of left to the competitor. The direction's exact backward reasoning was built (a Poisson-mixture map from p to score, Gauss-Hermite one-step law of the next p, used for arbitrage loss and the filter step) and measured, but it lost or did nothing against the base's approximation, so it is not in the final code; the last step keeps the base's exact two-point rule. No full multi-step dynamic programme of value was built: only that one-step law, applied at each step remaining. Tuning used seeds 0-599 only, in practice mostly seeds 0-299, and paired differences carry heavy tails from single runs.", "blocked": null, "python_version": "3.12.3", "base_mean_edge": 78.85441957511699, "score": {"mean_edge": 96.216768103807, "retail_edge": 125.75381357123699, "arb_edge": -29.53704546743383, "simulations": 600, "seed_start": 0, "failures": 0}, "holdout": {"mean_edge": 91.56426545709166, "simulations": 600, "seed_start": 20000, "failures": 0}, "code": "\"\"\"Stale-quote defence with tick probes, a sub-tick belief and YES ammunition.\n\nEvery step the arbitrageur removes any order on the wrong side of p, so tiny\ntwo-sided probes around the estimate locate p to a tick; a grid filter narrows\nthat further.  Quotes sit one tick inside the competitor and are sized by the\nmarginal rule: one more share is worth quoting while the chance a retail order\nreaches it, times its edge, exceeds the expected arbitrage loss.  That rule pulls\nquotes by itself when a move would hurt most.  Near p=0 a retail buy pays almost\nits whole notional as edge, so YES is held to cover low asks.\n\nAdded for the late game: below 4c a large \"trap\" bid rests just under p.  When p\nfalls through that tick the arbitrageur fills it almost at p, so the YES cover\nfor the pinned-near-zero stretch costs about a tenth of a tick a share rather\nthan up to a tick.  Its size follows the remaining retail demand in shares at\nthe larger of the spread and the tick.  Once YES is held, tick 1 is quoted\nrather than left to the competitor.\n\"\"\"\nimport math\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelOrder, PlaceOrder, Side\n\nP = dict(lam_r=0.25, m=5.0, sig_n=1.2, lam_j=0.0019, sig_j=0.35, sig=0.02,\n         qmax=3000.0, rmin=2, kA=0.7, kL=0.15, pL=0.05,\n         ammo=1.0, ydem=0.4, W=200.0, fy=0.6, ammo_q=60.0, ammo_pmax=0.05, ammo_maxpay=0.02,\n         fb=0.9, fu=0.5, xu=0.1, sticky=1.0, min_ahead=2.0, keep_hi=1.5, keep_lo=0.7, Hu=300.0, bins=8.0, filt=1.0, uni=0.01, jumpinfo=1.0, dmin=0.0, kLb=0.08, kLf=0.08, pinf=1.0, pre=1500.0, H1=100.0,\n         trap=1.0, trap_pmax=0.04, trap_c=0.5, trap_W=500.0, trap_m=0.1, trap_q=20000.0, h1y=500.0)\nSQ2 = math.sqrt(2.0)\nSQ2PI = math.sqrt(2.0 * math.pi)\ndef cdf(x): return 0.5 * (1.0 + math.erf(x / SQ2))\ndef pdf(x): return math.exp(-0.5 * x * x) / SQ2PI\ndef inv(p):\n    p = min(max(p, 1e-9), 1 - 1e-9)\n    t = math.sqrt(-2.0 * math.log(min(p, 1 - p)))\n    x = t - (2.515517 + 0.802853 * t + 0.010328 * t * t) / (1 + 1.432788 * t + 0.189269 * t * t + 0.001308 * t ** 3)\n    x = -x if p < 0.5 else x\n    for _ in range(2):\n        d = pdf(x)\n        if d < 1e-12:\n            break\n        x -= (cdf(x) - p) / d\n    return x\ndef lpm(k):\n    return pdf(k) + k * cdf(k)\ndef fl(q):\n    return math.floor(q * 100 + 1e-9) / 100\n\nNODES = [(-2.2, .06), (-1.3, .17), (-0.6, .27), (0.6, .27), (1.3, .17), (2.2, .06)]\nPROBE = 0.01\n\n\nclass Strategy(BaseStrategy):\n    def __init__(self):\n        self.n = 0\n        self.ahead = set()     # main orders placed strictly ahead of any competitor order at their tick\n        self.res = {}          # order id -> uncovered quantity at placement\n        self.bc = None         # belief: sub-tick grid centres (ticks)\n        self.bw = None         # belief: weights\n        self.st = 0.5          # last one-step sd in ticks\n        self.pcb = self.pca = None\n        self.sp0 = 2\n        self.pb = set()\n        self.pa = set()\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        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        if P['pinf'] > 0:\n            sb = {o.price_ticks for o in state.own_orders if o.side is Side.BUY and o.remaining_quantity <= PROBE + 1e-9}\n            sa = {o.price_ticks for o in state.own_orders if o.side is Side.SELL and o.remaining_quantity <= PROBE + 1e-9}\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 sb and eb:\n                hi = min(hi, max(min(eb), lo))\n        if P['jumpinfo'] > 0 and 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        if self.pcb is None:\n            self.sp0 = max(1, (ca - cb + 1) // 2) if ca - cb < 20 else 2\n        self.pcb, self.pca = cb, ca\n        if lo > hi:\n            lo, hi = hi, lo\n        # sub-tick belief over p_(t-1): predict with one-step noise, truncate to [lo, hi]\n        wid = max(hi - lo, 1e-6)\n        nb = max(2, min(48, int(round(wid * P['bins']))))\n        cs = [lo + (i + 0.5) * wid / nb for i in range(nb)]\n        if self.bc is None or P['filt'] <= 0:\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 = P['uni'] * 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 = P['sig'] ** 2 + P['lam_j'] * P['sig_j'] ** 2\n        sd = math.sqrt(H * var)\n        z = inv(phat)\n        Z = z * sd\n        sp = pdf(z) / sd * P['sig']\n        self.st = sp * 100.0\n        s = math.sqrt(sp * sp + var_t / 1e4 + 1e-8)\n        sd1 = math.sqrt(max(1.0, H - 1.0) * var)\n        jp = [(cdf((Z + n * P['sig_j']) / sd1), w) for n, w in NODES]\n        lj = P['lam_j']\n\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\n        if H == 1:\n            def AB(x):\n                return (1 - phat) * x, phat * (1 - x)\n        rho = P['lam_r'] * 0.5\n        mu = math.log(P['m']) - 0.5 * P['sig_n'] ** 2\n        kA = P['kL'] if phat < P['pL'] else P['kA']\n\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(P['qmax'], math.exp(mu + P['sig_n'] * inv(1 - max(tail, 1e-6))) / px)\n\n        ptk = phat * 100\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 < P['dmin']:\n                return 0.0\n            if phat < P['pL']:\n                ytg = P['ydem'] * min(H, P['W']) / max(ca - 1, ptk + 1) * 100.0\n                a *= (P['kLb'] if state.yes_inventory < ytg else P['kLf']) / P['kL']\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 < P['dmin']:\n                return 0.0\n            return qsize(b, a, t / 100.0)\n\n        bids = [o for o in state.own_orders if o.side is Side.BUY and o.remaining_quantity > PROBE + 1e-9]\n        asks = [o for o in state.own_orders if o.side is Side.SELL and o.remaining_quantity > PROBE + 1e-9]\n        sticky = P['sticky'] > 0\n        def top(orders, comp, step):\n            if sticky and sum(o.remaining_quantity for o in orders if o.price_ticks == comp and o.order_id in self.ahead) >= P['min_ahead']:\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\n        Y = state.yes_inventory\n        if ask_t == 1 and H > P['H1'] and P['pre'] > 0 and not (P['h1y'] > 0 and Y >= P['h1y']):\n            qa = 0.0          # let the competitor's 2-tick ask erode instead of fronting it for nothing\n        # ammunition: hold YES so that low asks are covered\n        ptick = phat * 100\n        amt = 0\n        qam = 0.0\n        if P['ammo'] > 0 and ask_t >= 2 and phat < P['ammo_pmax']:\n            wealth = state.cash + Y * phat\n            x = max(ask_t, ptick + 1) / 100.0\n            target = min(P['ydem'] * min(H, P['W']) / x, P['fy'] * wealth / max(phat, 0.005))\n            if Y < target:\n                t = max(1, min(99, int(math.ceil(ptick + 1e-9))))\n                if bid_t <= t < ask_t and t / 100.0 - phat < P['ammo_maxpay']:\n                    amt = t\n                    qam = min(P['ammo_q'], target - Y)\n\n        if P['pre'] > 0 and ca == 2 and phat < 0.01 and H > P['H1'] and Y < P['pre'] and not qam:\n            amt, qam = 1, min(P['ammo_q'], P['pre'] - Y)\n        # trap: a bid just under p costs almost nothing when p falls through it\n        trt = 0\n        trq = 0.0\n        if P['trap'] > 0 and phat < P['trap_pmax'] and H > 1:\n            trt = int(math.floor(ptick - P['trap_m']))\n            if trt >= 1 and trt != amt:\n                x = max(self.sp0, trt) / 100.0\n                target = P['trap_c'] * min(H, P['trap_W']) / x\n                trq = min(P['trap_q'], target - Y)\n            if trq < 1.0:\n                trt = 0\n        # order management\n        actions = []\n        free = state.free_cash - 2.0\n        keep_ask = 0.0\n        new_b = []\n        new_a = []\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-9:\n                cancel(o)\n        kept_ids = set()\n        def manage(orders, t, q, comp):\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 * P['keep_hi'], 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, cb)\n        ka = manage(asks, ask_t, qa, ca)\n        add_b = (qb - kb) if (kb < qb * P['keep_lo'] and bid_t != cb) else 0.0\n        add_a = (qa - ka) if (ka < qa * P['keep_lo'] and ask_t != ca) else 0.0\n\n        budget = P['fb'] * max(free, 0.0)\n        cost = add_b * bid_t / 100.0 + qam * amt / 100.0 + trq * trt / 100.0\n        if cost > budget:\n            f = budget / cost\n            add_b *= f\n            qam *= f\n            trq *= f\n            cost = budget\n        out = []\n        if trt and trq >= 0.01:\n            q = fl(trq)\n            out.append(PlaceOrder(side=Side.BUY, price_ticks=trt, quantity=q))\n            free -= q * trt / 100.0 + 1e-6\n        if amt and qam >= 0.01:\n            q = fl(qam)\n            out.append(PlaceOrder(side=Side.BUY, price_ticks=amt, quantity=q))\n            free -= q * amt / 100.0 + 1e-6\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-6\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)\n                       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 - P['fu']) * max(state.cash, 0.0)) if x >= P['xu'] else 0.0\n                if H < P['Hu'] and phat < 0.05:\n                    ub = max(0.0, free * (1 - H / P['Hu']))\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-6\n                if ask_t < ca:\n                    self.ahead.add(oid)\n\n        # probes: tiny orders that the arbitrageur removes when p crosses them\n        f = int(math.floor(ptick + 1e-9))\n        r = max(int(P['rmin']), 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": "9391b90f54c0084e93deeb749c0dc86cebb0122861c1c4975dc95fdf197babdd", "tried": ["All scores below are local. Unless stated, n=300 from seed 0, differences are paired against the build named, with their standard error. Python 3.12.3, simulator commit b244530ee2a6247b5f930830eeca9dd950da0e7e.", "The final file also fails --sandbox with that same ntpath ImportError on 20 simulations, so the sandbox check gave no result. A check on a patched simulator copy was not run.", "Comparison after freezing, not used for tuning: the base scores 87.41650726068066 on seeds 0-599 and 85.46780344973116 on holdout seeds 20000-20599, se about 6 on each.", "Sandbox: --sandbox fails for examples/starter_strategy.py on Python 3.12 (ImportError: Import of 'ntpath' is not allowed), so no strategy can pass it here; the final file imports only math and the package's strategy and types modules. --workers 6 worked on this machine.", "Exact law with lower loss weights (kA 0.45, kL 0.08) on the last 600 steps: -4.21 +/- 0.73 against the then build", "Exact one-step law of p (mixture map, Gauss-Hermite) on the last 600 steps, n=200: -2.09 +/- 0.71 against the same build with it off; on the last 200 steps: -1.58; with kA 1, kL 0.3: -3.06 against off", "Exact law only at p of 5c or more, last 150 or last 30 steps: -0.016 +/- 0.048 and -0.035 +/- 0.014, no effect", "Quote nothing at p between 5c and 95c in the last 100 steps: -0.39 +/- 0.38, so late mid-price quoting is not where money leaks", "Uncovered-ask cash window Hu: 100 gave -0.45 +/- 0.29, 600 gave +0.35 +/- 0.43 then -1.15 +/- 0.51 on the later build; kept 300", "Stand-aside window H1 300: +0.10 +/- 0.13, kept 100", "Trap cap 2500, 5000, 10000 shares with a top-up at the tick above p just after a crossing: 82.43, 83.40, 83.90 against 84.58 for no top-up and a 20000 cap, even though five jump-through fills of 12000 to 20000 shares cost 100 to 190 each", "Trap size in shares at the spread alone: 76.63 against 83.71 with the old tick-based size, because one-tick runs overbought at 4c to 6c; split by spread and outcome this showed s=1 and s=2 needed less at high ticks and s=4 needed less at tick 1, which led to x = max(spread, tick)", "Ceiling-priced ammunition scaled to 0.3, 0.1 or off: within 0.2 of each other, it no longer matters once the trap fills", "Trap c 0.4, 0.8, 1.2 with W 300: 80.42, 83.07, 81.45; W 150 79.65; W 500 with c 0.5: 83.94; pmax 4c: 83.48 against 83.07; pmax 10c: -1.79 +/- 1.04", "Quote tick 1 once 500 YES are held, with trap c 0.8: 83.71 against 81.31 without", "Trap bids just under p below 6c: 81.31 against 77.24 with the trap off, which is the base's behaviour on the same seeds", "Final: trap below 4c, c 0.5, W 500, cap 20000, h1y 500: 84.58 on seeds 0-299; on seeds 0-599 see score, against the base's 87.42 there"], "next": "The largest visible gaps: runs with a one-tick spread settling at 0 earned about 62 against about 156 to 241 for wider spreads on seeds 0-299. Trap size still uses a fixed retail demand; an online estimate of each run's retail rate and size would set it per run, since rates vary about fivefold. Five jump-through fills of the trap cost 100 to 190 each, so a size that prices jump risk without giving up diffusion crossings may pay, though a plain cap and top-up did not. A value-based stop for the trap (share value times the chance it sells, against expected crossing loss) was designed and not tested. The exact one-step law need not be retried on quoting without first explaining why it lost at low prices; suspect the prior jump parameters, and try fitting them per run."}