{"approach":"Frozen candidate simplify measured against frozen incumbent B on seeds 225000\u2013225499 using the pinned simulator, default ChallengeConfig and ParameterVariance, 2000 steps, serial in-process.","tried":"No development or tuning; ran all 500 required fallback-block seeds for candidate and incumbent on identical seeds.","next":"Do not promote: paired gain is not positive and does not exceed twice its standard error; retain incumbent B.","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":"225000..225499","n":500,"complete":true,"mean_diff":-0.6997147701784002,"se":1.0082475384616933,"sum_d":-349.85738508920014,"sum_d2":253877.29353391178,"candidate_mean":100.1531660313472,"incumbent_mean":100.85288080152559,"retail_diff":-3.6809130724863994,"retail_se":0.4968725579108442,"arb_diff":2.9811983023010002,"arb_se":0.9567757374963433,"nonzero_diff_seeds":499,"failures":[]},"seconds_per_simulation":1.3084330544841942}

