{
 "approach": "Literal complete-set arbitrage does not exist here: the API is passive-only, nothing can be lifted, and the competitor book was crossed on only 29 of 240,000 tuning-seed steps. The book's equivalent: an uncovered ask buys NO at 1-ask and the simulator never merges YES with NO, so a bid resting against a held NO lot buys a set below one. Diagnostics showed S0 ran out of cash mostly at p<0.1, where a retail order is many shares (median minimum cash 17.7 of 1000). S1 therefore (a) adds a bid completing open NO lots when bid + average NO cost <= 0.99 and bid is at least 0.5 tick under fair, sized for 12 notional, capped at the open lot; (b) gives that bid first call on cash; (c) keeps 100 cash from uncovered asks and halves what is left for them while NO lots are open. YES bought at a few cents then covers later asks with no collateral. This is not riskless under the score: edge is marked to p at each fill, and arbitrage loss rose by 22.98. S0 and S1 differ only in the mechanism block, three init fields and the budget rule. S0 is weak (18.7 against B's 99.7), so the gain is measured on a cash-starved baseline.",
 "tried": [
  {
   "strategy": "S0",
   "variant": "v1 mid of competitor quotes, fixed distance and size",
   "score": -46.758,
   "seeds": "115000..115019",
   "n": 20,
   "note": "also about -48.4 on the first 120 tuning seeds; rejected before a 500-seed run"
  },
  {
   "strategy": "S0",
   "variant": "v2 score filter on ladder bounds, flow-against-sweep sizing, MIN_EDGE 1, FLOW_MULT 1, cash to ask first",
   "score": 10.91,
   "seeds": "115000..115119",
   "n": 120,
   "note": "sum of per-window means from the diagnostic run; not run on all 500"
  },
  {
   "strategy": "S0",
   "variant": "v3 MIN_EDGE 0.4, FLOW_MULT 2, cash split evenly between legs",
   "score": 9.684,
   "seeds": "115000..115499",
   "n": 500
  },
  {
   "strategy": "S0",
   "variant": "v4 v3 plus two-point jump cost and 20 notional size cap (FROZEN)",
   "score": 18.412,
   "seeds": "115000..115499",
   "n": 500
  },
  {
   "strategy": "S1",
   "variant": "v1 no set bid; bid first on cash, asks get all the rest",
   "score": 15.679,
   "seeds": "115000..115499",
   "n": 500,
   "note": "below S0: spending cash faster on asks hurt"
  },
  {
   "strategy": "S1",
   "variant": "v2 set bid, SET_EDGE 0.25, asks get half the rest, RESERVE 0",
   "score": 23.484,
   "seeds": "115000..115499",
   "n": 500,
   "paired_vs_s0": 5.072,
   "se": 1.501
  },
  {
   "strategy": "S1",
   "variant": "v3 SET_EDGE 0.5, RESERVE 30",
   "score": 29.247,
   "seeds": "115000..115499",
   "n": 500,
   "paired_vs_s0": 10.835,
   "se": 1.624
  },
  {
   "strategy": "S1",
   "variant": "v4 SET_EDGE 0.5, RESERVE 100 (FROZEN)",
   "score": 32.956,
   "seeds": "115000..115499",
   "n": 500,
   "paired_vs_s0": 14.545,
   "se": 2.266
  }
 ],
 "next": "Graft onto the current best and measure paired there; the gain depends on how often that strategy runs short of cash, which was not measured because B's code was not read. RESERVE rose at every step and the variant budget ended there, so a larger value is untested. The reserve and the set bid were changed together in v3 and v4 and are not separated on holdout: ablate them. On 120 tuning seeds about 30 of the retail gain came at p<0.1 (58.19 against 28.60), so the same cash logic near low p is the place to look. A mirror rule at high p was not tried.",
 "code": "\"\"\"S0: quotes around a filtered probability estimate, sized by retail flow\nagainst adverse selection. The estimate tracks the latent score from the only\npublic signal: the arbitrageur keeps the competitor ladder bracketing p.\"\"\"\nimport math\n\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelAll, PlaceOrder, Side\n\nSIGMA = 0.02            # score diffusion per step\nVAR_STEP = 0.00073      # diffusion plus mean jump variance per step\nJUMP_RATE = 0.0019      # mean jumps per step\nJUMP_SD = 0.40          # typical jump size in score units\nRETAIL_RATE = 0.125     # mean retail orders per step on one side\nLOG_MU, LOG_SD = 0.784, 1.2   # retail notional is lognormal\nMAX_NOTIONAL = 20.0     # never quote more than a large retail order\n\n\ndef cdf(x):\n    return 0.5 * (1.0 + math.erf(x / 1.4142135623730951))\n\n\ndef pdf(x):\n    return 0.3989422804014327 * math.exp(-0.5 * x * x)\n\n\ndef inv_cdf(p):\n    p = min(1.0 - 1e-9, max(1e-9, p))\n    lo, hi = -7.0, 7.0\n    for _ in range(36):\n        mid = 0.5 * (lo + hi)\n        if cdf(mid) < p:\n            lo = mid\n        else:\n            hi = mid\n    return 0.5 * (lo + hi)\n\n\ndef truncate(m, v, lo, hi):\n    \"\"\"Mean and variance of N(m, v) restricted to [lo, hi].\"\"\"\n    s = math.sqrt(v)\n    a, b = (lo - m) / s, (hi - m) / s\n    mass = cdf(b) - cdf(a)\n    if mass < 1e-6:     # prior disagrees with the book: trust the book\n        c = min(max(m, lo), hi) if hi - lo > 8.0 else 0.5 * (lo + hi)\n        return c, max(((hi - lo) / 3.5) ** 2, 1e-6) if hi - lo < 8.0 else v\n    pa, pb = pdf(a), pdf(b)\n    shift = (pa - pb) / mass\n    return m + s * shift, max(v * (1.0 + (a * pa - b * pb) / mass - shift * shift), 1e-8)\n\n\nclass Strategy(BaseStrategy):\n    MIN_EDGE = 0.4     # ticks of expected edge a quote must keep\n    FLOW_MULT = 2.0    # scales expected retail flow against adverse selection\n\n    def __init__(self):\n        self.mean = None\n        self.var = 0.0\n        self.prev_bid = None\n        self.prev_ask = None\n        self.no_seen = 0.0\n        self.no_cost = 0.0\n        self.ask_price = 50\n        self.bid_need = 0.0\n\n    def update(self, state):\n        h = max(state.steps_remaining, 1)\n        sd = math.sqrt(VAR_STEP * h)\n        bid = state.competitor_best_bid_ticks\n        ask = state.competitor_best_ask_ticks\n        lo = sd * inv_cdf(bid / 100.0) if bid else -9.0\n        hi = sd * inv_cdf(ask / 100.0) if ask else 9.0\n        if self.mean is None:\n            self.mean, self.var = 0.5 * (lo + hi), ((hi - lo) / 3.5) ** 2\n        self.var += SIGMA * SIGMA\n        if ask and self.prev_ask and ask > self.prev_ask:     # asks lifted: p above them\n            lo = max(lo, sd * inv_cdf((ask - 1) / 100.0))\n            if ask - self.prev_ask >= 3:                      # jump: forget the prior\n                self.mean, self.var = 0.5 * (lo + hi), 4.0 * (hi - lo) ** 2\n        if bid and self.prev_bid and bid < self.prev_bid:     # bids hit: p below them\n            hi = min(hi, sd * inv_cdf((bid + 1) / 100.0))\n            if self.prev_bid - bid >= 3:\n                self.mean, self.var = 0.5 * (lo + hi), 4.0 * (hi - lo) ** 2\n        if lo < hi:\n            self.mean, self.var = truncate(self.mean, self.var, lo, hi)\n        self.prev_bid, self.prev_ask = bid, ask\n        return sd\n\n    def quote(self, dist, spread, jump_move, scale):\n        \"\"\"Size for one quote: retail edge against arbitrage loss, per share.\"\"\"\n        if dist < self.MIN_EDGE:\n            return 0.0\n        u = dist / spread\n        sweep = spread * (pdf(u) - u * (1.0 - cdf(u)))\n        sweep += 0.5 * JUMP_RATE * max(jump_move - dist, 0.0)\n        tail = sweep / (self.FLOW_MULT * RETAIL_RATE * dist)\n        if tail >= 0.999:\n            return 0.0\n        return min(math.exp(LOG_MU + LOG_SD * inv_cdf(1.0 - tail)), MAX_NOTIONAL) * scale\n\n    def choose(self, state, fair, spread, up, down):\n        bid_lim = state.competitor_best_bid_ticks or 0\n        ask_lim = state.competitor_best_ask_ticks or 100\n        sell_scale = 1.0 / max(fair / 100.0, 0.05)\n        bid, ask, bid_value, ask_value = (0, 0.0), (0, 0.0), 0.0, 0.0\n        for price in range(max(1, bid_lim + 1), min(99, ask_lim + 3)):\n            size = self.quote(fair - price, spread, down, sell_scale)\n            if size * (fair - price) > bid_value:\n                bid_value, bid = size * (fair - price), (price, size)\n        for price in range(max(1, bid_lim - 3), min(99, ask_lim - 1) + 1):\n            size = self.quote(price - fair, spread, up, 100.0 / price)\n            if size * (price - fair) > ask_value:\n                ask_value, ask = size * (price - fair), (price, size)\n        return bid, ask\n\n    # --- complete-set mechanism (the only difference from S0) ---------------\n    # This book has one YES ladder: an uncovered ask buys NO at 1 - ask, and the\n    # simulator never merges YES with NO. A resting bid plus a held NO lot is a\n    # complete set bought below one when bid + NO cost < 1. Completing sets is\n    # also what frees collateral: YES in hand covers later asks for no cash.\n    SET_LEG = 1.0      # 1: add a bid that completes open NO lots\n    SET_MARGIN = 0.01  # the set must cost at most 1 minus this\n    SET_EDGE = 0.5     # ticks of expected edge the completing bid must keep\n    SET_NOTIONAL = 12.0  # retail notional the completing bid is sized for\n    RESERVE = 100.0    # cash kept from uncovered asks while NO lots are open\n\n    def track_sets(self, state):\n        if state.no_inventory > self.no_seen + 1e-9:\n            added = state.no_inventory - self.no_seen\n            self.no_cost += added * (1.0 - self.ask_price / 100.0)\n        if state.no_inventory < 1e-9:\n            self.no_cost = 0.0\n        self.no_seen = state.no_inventory\n\n    def adjust(self, state, fair, bid, ask):\n        self.track_sets(state)\n        self.ask_price = ask[0] or self.ask_price\n        open_no = state.no_inventory - state.yes_inventory\n        if self.SET_LEG > 0.0 and open_no > 0.0:\n            no_cost = self.no_cost / max(state.no_inventory, 1e-9)\n            limit = min(fair - self.SET_EDGE, 100.0 * (1.0 - no_cost - self.SET_MARGIN))\n            price = int(math.floor(limit))\n            if price > (state.competitor_best_bid_ticks or 0) and price >= max(bid[0], 1):\n                size = min(self.SET_NOTIONAL / max(fair / 100.0, 0.05), open_no)\n                bid = (price, max(size, bid[1]) if price == bid[0] else size)\n        self.bid_need = bid[0] / 100.0 * bid[1]\n        return bid, ask, []\n\n    def budgets(self, state, fair):\n        if state.no_inventory <= state.yes_inventory:\n            return 0.5 * state.cash, 0.5 * state.cash\n        need = min(state.cash, self.bid_need)    # the set leg has first call on cash\n        return 0.5 * max(state.cash - need - self.RESERVE, 0.0), need\n\n    def on_step(self, state):\n        sd = self.update(state)\n        sd_next = math.sqrt(VAR_STEP * max(state.steps_remaining - 1, 1))\n        z = self.mean / sd_next\n        fair = 100.0 * cdf(z)\n        spread = max(100.0 * pdf(z) / sd_next * math.sqrt(self.var + SIGMA * SIGMA), 0.05)\n        up = 100.0 * cdf(z + JUMP_SD / sd_next) - fair\n        down = fair - 100.0 * cdf(z - JUMP_SD / sd_next)\n        bid, ask = self.choose(state, fair, spread, up, down)\n        bid, ask, extra = self.adjust(state, fair, bid, ask)\n\n        actions = [CancelAll()]\n        yes = state.yes_inventory\n        sell_budget, buy_budget = self.budgets(state, fair)\n        for side, price, size in [(Side.SELL, *ask), (Side.BUY, *bid)] + extra:\n            if size <= 0.0 or price < 1 or price > 99:\n                continue\n            unit = price / 100.0\n            if side is Side.BUY:\n                size = min(size, buy_budget / unit)\n                buy_budget -= unit * size + 1e-6\n            else:\n                covered = min(size, yes)\n                yes -= covered\n                uncovered = min(size - covered, sell_budget / (1.0 - unit))\n                size = covered + uncovered\n                sell_budget -= (1.0 - unit) * uncovered + 1e-6\n            size = math.floor(size * 100.0) / 100.0\n            if size >= 0.01:\n                actions.append(PlaceOrder(side=side, price_ticks=price, quantity=size))\n        return actions\n",
 "code_sha256": "4587c61432f18e0c9e33061def6661cfffd7fbcc01c209f7e29ab391767b9c15",
 "code_s0": "\"\"\"S0: quotes around a filtered probability estimate, sized by retail flow\nagainst adverse selection. The estimate tracks the latent score from the only\npublic signal: the arbitrageur keeps the competitor ladder bracketing p.\"\"\"\nimport math\n\nfrom orderbook_pm_challenge.strategy import BaseStrategy\nfrom orderbook_pm_challenge.types import CancelAll, PlaceOrder, Side\n\nSIGMA = 0.02            # score diffusion per step\nVAR_STEP = 0.00073      # diffusion plus mean jump variance per step\nJUMP_RATE = 0.0019      # mean jumps per step\nJUMP_SD = 0.40          # typical jump size in score units\nRETAIL_RATE = 0.125     # mean retail orders per step on one side\nLOG_MU, LOG_SD = 0.784, 1.2   # retail notional is lognormal\nMAX_NOTIONAL = 20.0     # never quote more than a large retail order\n\n\ndef cdf(x):\n    return 0.5 * (1.0 + math.erf(x / 1.4142135623730951))\n\n\ndef pdf(x):\n    return 0.3989422804014327 * math.exp(-0.5 * x * x)\n\n\ndef inv_cdf(p):\n    p = min(1.0 - 1e-9, max(1e-9, p))\n    lo, hi = -7.0, 7.0\n    for _ in range(36):\n        mid = 0.5 * (lo + hi)\n        if cdf(mid) < p:\n            lo = mid\n        else:\n            hi = mid\n    return 0.5 * (lo + hi)\n\n\ndef truncate(m, v, lo, hi):\n    \"\"\"Mean and variance of N(m, v) restricted to [lo, hi].\"\"\"\n    s = math.sqrt(v)\n    a, b = (lo - m) / s, (hi - m) / s\n    mass = cdf(b) - cdf(a)\n    if mass < 1e-6:     # prior disagrees with the book: trust the book\n        c = min(max(m, lo), hi) if hi - lo > 8.0 else 0.5 * (lo + hi)\n        return c, max(((hi - lo) / 3.5) ** 2, 1e-6) if hi - lo < 8.0 else v\n    pa, pb = pdf(a), pdf(b)\n    shift = (pa - pb) / mass\n    return m + s * shift, max(v * (1.0 + (a * pa - b * pb) / mass - shift * shift), 1e-8)\n\n\nclass Strategy(BaseStrategy):\n    MIN_EDGE = 0.4     # ticks of expected edge a quote must keep\n    FLOW_MULT = 2.0    # scales expected retail flow against adverse selection\n\n    def __init__(self):\n        self.mean = None\n        self.var = 0.0\n        self.prev_bid = None\n        self.prev_ask = None\n\n    def update(self, state):\n        h = max(state.steps_remaining, 1)\n        sd = math.sqrt(VAR_STEP * h)\n        bid = state.competitor_best_bid_ticks\n        ask = state.competitor_best_ask_ticks\n        lo = sd * inv_cdf(bid / 100.0) if bid else -9.0\n        hi = sd * inv_cdf(ask / 100.0) if ask else 9.0\n        if self.mean is None:\n            self.mean, self.var = 0.5 * (lo + hi), ((hi - lo) / 3.5) ** 2\n        self.var += SIGMA * SIGMA\n        if ask and self.prev_ask and ask > self.prev_ask:     # asks lifted: p above them\n            lo = max(lo, sd * inv_cdf((ask - 1) / 100.0))\n            if ask - self.prev_ask >= 3:                      # jump: forget the prior\n                self.mean, self.var = 0.5 * (lo + hi), 4.0 * (hi - lo) ** 2\n        if bid and self.prev_bid and bid < self.prev_bid:     # bids hit: p below them\n            hi = min(hi, sd * inv_cdf((bid + 1) / 100.0))\n            if self.prev_bid - bid >= 3:\n                self.mean, self.var = 0.5 * (lo + hi), 4.0 * (hi - lo) ** 2\n        if lo < hi:\n            self.mean, self.var = truncate(self.mean, self.var, lo, hi)\n        self.prev_bid, self.prev_ask = bid, ask\n        return sd\n\n    def quote(self, dist, spread, jump_move, scale):\n        \"\"\"Size for one quote: retail edge against arbitrage loss, per share.\"\"\"\n        if dist < self.MIN_EDGE:\n            return 0.0\n        u = dist / spread\n        sweep = spread * (pdf(u) - u * (1.0 - cdf(u)))\n        sweep += 0.5 * JUMP_RATE * max(jump_move - dist, 0.0)\n        tail = sweep / (self.FLOW_MULT * RETAIL_RATE * dist)\n        if tail >= 0.999:\n            return 0.0\n        return min(math.exp(LOG_MU + LOG_SD * inv_cdf(1.0 - tail)), MAX_NOTIONAL) * scale\n\n    def choose(self, state, fair, spread, up, down):\n        bid_lim = state.competitor_best_bid_ticks or 0\n        ask_lim = state.competitor_best_ask_ticks or 100\n        sell_scale = 1.0 / max(fair / 100.0, 0.05)\n        bid, ask, bid_value, ask_value = (0, 0.0), (0, 0.0), 0.0, 0.0\n        for price in range(max(1, bid_lim + 1), min(99, ask_lim + 3)):\n            size = self.quote(fair - price, spread, down, sell_scale)\n            if size * (fair - price) > bid_value:\n                bid_value, bid = size * (fair - price), (price, size)\n        for price in range(max(1, bid_lim - 3), min(99, ask_lim - 1) + 1):\n            size = self.quote(price - fair, spread, up, 100.0 / price)\n            if size * (price - fair) > ask_value:\n                ask_value, ask = size * (price - fair), (price, size)\n        return bid, ask\n\n    def adjust(self, state, fair, bid, ask):\n        return bid, ask, []\n\n    def budgets(self, state, fair):\n        return 0.5 * state.cash, 0.5 * state.cash\n\n    def on_step(self, state):\n        sd = self.update(state)\n        sd_next = math.sqrt(VAR_STEP * max(state.steps_remaining - 1, 1))\n        z = self.mean / sd_next\n        fair = 100.0 * cdf(z)\n        spread = max(100.0 * pdf(z) / sd_next * math.sqrt(self.var + SIGMA * SIGMA), 0.05)\n        up = 100.0 * cdf(z + JUMP_SD / sd_next) - fair\n        down = fair - 100.0 * cdf(z - JUMP_SD / sd_next)\n        bid, ask = self.choose(state, fair, spread, up, down)\n        bid, ask, extra = self.adjust(state, fair, bid, ask)\n\n        actions = [CancelAll()]\n        yes = state.yes_inventory\n        sell_budget, buy_budget = self.budgets(state, fair)\n        for side, price, size in [(Side.SELL, *ask), (Side.BUY, *bid)] + extra:\n            if size <= 0.0 or price < 1 or price > 99:\n                continue\n            unit = price / 100.0\n            if side is Side.BUY:\n                size = min(size, buy_budget / unit)\n                buy_budget -= unit * size + 1e-6\n            else:\n                covered = min(size, yes)\n                yes -= covered\n                uncovered = min(size - covered, sell_budget / (1.0 - unit))\n                size = covered + uncovered\n                sell_budget -= (1.0 - unit) * uncovered + 1e-6\n            size = math.floor(size * 100.0) / 100.0\n            if size >= 0.01:\n                actions.append(PlaceOrder(side=side, price_ticks=price, quantity=size))\n        return actions\n",
 "tuning_score": {
  "seeds": "115000..115499",
  "n": 500,
  "s1_mean": 32.9565,
  "s0_mean": 18.4118
 },
 "paired": {
  "seeds": "200000..200999",
  "n": 1000,
  "complete": true,
  "mechanism_diff": 15.3204,
  "mechanism_se": 1.5768,
  "mechanism_retail_diff": 38.3008,
  "mechanism_arb_diff": -22.9803,
  "reference_diff": -65.6599,
  "reference_se": 3.855,
  "s1_mean": 34.036,
  "s0_mean": 18.7156,
  "b_mean": 99.6959,
  "failures": []
 },
 "graft": "Track NO lots and their cost. While no>yes, post a bid at floor(min(fair-0.5, 100*(0.99-avgNOcost))) if above the competitor bid, sized min(12/max(p,.05), no-yes). Pay for it first; give uncovered asks half of (cash-bid cost-100). Covered asks need no cash.",
 "seconds_per_simulation": 0.57
}