{
 "key": "f-side-size-ratio",
 "mech": "side size ratio: multiply N's bid sizes by rb and ask sizes by ra (each from 0.5, 0.7, 1.0, 1.3) while the rival midpoint is between 20 and 80 cents",
 "approach": "Blind overlay on N: after super().on_step, every PlaceOrder is re-issued at the same side, price and client id with quantity x rb (bids) or x ra (asks) while (rival best bid + best ask)/2 is within 20..80 ticks; cancels pass through. Before returning, the list is replayed against the simulator's collateral rule (conservative account model); if scaled-up sizes would not fit, only cuts are applied, else N's list is returned. Three variants tuned on 320000..320199; best (rb=ra=1.3) frozen and run paired vs N on 430000..430499. Result: negative screen.",
 "tried": [
  "up: rb=1.3, ra=1.3 (both sides larger). Tuning -0.228 +/- 0.178 (retail +0.46, arb -0.69). Least bad, frozen. Holdout -0.345 +/- 0.140 (retail +0.40, arb -0.75): extra retail capture is more than paid back to the arbitrageur.",
  "dn: rb=0.7, ra=0.7 (both sides smaller). Tuning -2.047 +/- 1.087, dominated by spread 4 (-7.08 +/- 3.97; seed 320089 alone -190.42). Spread 2 was +0.234 +/- 0.162, not significant.",
  "ratio: rb=1.3, ra=0.7 (pure bid-heavy ratio, mean size unchanged). Tuning -1.425 +/- 1.056; same spread-4 outlier seed 320089 (-190.43), so the damage there comes with the smaller asks. Spread 2 was +0.406 +/- 0.194, about 2 SE on 50 seeds, untested on holdout.",
  "Spreads: acted on all four (1..4), fixed before tuning; not narrowed afterwards because that would have been a fourth variant.",
  "Collateral guard never triggered in the smoke run (0 fallbacks in 4391 resized steps per variant); no simulation failed anywhere.",
  "Besides the measured runs, seeds 310000..310009 were used only for check_values, off_equals_n (N, overlay off, and overlay on with rb=ra=1.0) and a 3-seed failure smoke test of the three variants (310000, 310001, 310003); none of that informed the selection."
 ],
 "next": "Do not promote: on holdout the frozen variant is -0.345 +/- 0.140 vs N (about -2.5 SE), worst at spread 2 (-0.582 +/- 0.149). N's sizes look at or slightly above the optimum for a uniform multiplier, so plain size scaling is exhausted as a lever. The one lead: larger size clearly loses at spread 2 and both ra=0.7 variants were mildly positive there on tuning, so a mild cut (rb=ra about 0.85) restricted to spread 2 is worth one screen. Smaller asks blew up on two spread-4 tuning seeds (320089: -190, 320034: -53 to -60) through arbitrage loss; whoever may read N should check how it reacts to resting orders smaller than it placed.",
 "spreads_acted": [
  1,
  2,
  3,
  4
 ],
 "off_equals_n": {
  "equal": true,
  "seeds": "310000..310009",
  "steps_compared": 20000,
  "steps_differing": 0,
  "seeds_equal": 10,
  "how": "overlay with SPREADS = () (off); repr of every action list compared with N's at every step; total edge also identical on all 10 seeds",
  "also_identity_at_rb_ra_1": {
   "steps_differing": 0,
   "seeds_equal": 10
  }
 },
 "code": "# Overlay f-side-size-ratio: scale N's bid sizes by RB and ask sizes by RA\n# while the rival midpoint is between LO and HI ticks, on the spreads in SPREADS.\nfrom orderbook_pm_challenge.types import CancelAll as _ZCA\nfrom orderbook_pm_challenge.types import CancelOrder as _ZCO\nfrom orderbook_pm_challenge.types import PlaceOrder as _ZPO\nfrom orderbook_pm_challenge.types import Side as _ZSide\n\n\nclass Strategy(_N):\n    RB = 1.3  # multiplier on BUY (bid) order sizes\n    RA = 1.3  # multiplier on SELL (ask) order sizes\n    LO = 20.0  # rival midpoint band, in ticks (cents), inclusive\n    HI = 80.0\n    SPREADS = (1, 2, 3, 4)  # rival spreads (N's self.s) acted on; () switches the overlay off\n\n    def on_step(self, state):\n        acts = super().on_step(state)\n        if not acts or getattr(self, \"s\", None) not in self.SPREADS:\n            return acts\n        bid = state.competitor_best_bid_ticks\n        ask = state.competitor_best_ask_ticks\n        if bid is None or ask is None:\n            return acts\n        mid = 0.5 * (bid + ask)\n        if mid < self.LO or mid > self.HI:\n            return acts\n        rb = float(self.RB)\n        ra = float(self.RA)\n        if rb == 1.0 and ra == 1.0:\n            return acts\n        src = list(acts)\n        out = self._z_scale(state, src, rb, ra)\n        if out is None and (rb > 1.0 or ra > 1.0):\n            # scaled-up sizes do not fit the collateral: only apply the cuts\n            rb = min(rb, 1.0)\n            ra = min(ra, 1.0)\n            if rb == 1.0 and ra == 1.0:\n                return acts\n            out = self._z_scale(state, src, rb, ra)\n        return acts if out is None else out\n\n    @staticmethod\n    def _z_scale(state, src, rb, ra):\n        \"\"\"Resize every PlaceOrder; replay the simulator's collateral rule on a\n        conservative model of the account and return None if anything would not fit.\"\"\"\n        cash = float(state.cash)\n        yes = float(state.yes_inventory)\n        free = float(state.free_cash)\n        buy_res = 0.0\n        sell_rem = 0.0\n        for o in state.own_orders:\n            if o.side is _ZSide.BUY:\n                buy_res += o.price_ticks / 100.0 * o.remaining_quantity\n            else:\n                sell_rem += o.remaining_quantity\n        covered = (float(state.reserved_cash) - buy_res) < 1e-6  # resting asks all backed by YES\n        avail = max(0.0, yes - sell_rem)\n        live = {}\n        for o in state.own_orders:\n            if o.side is _ZSide.BUY:\n                live[o.order_id] = (o.price_ticks / 100.0 * o.remaining_quantity, 0.0)\n            else:\n                live[o.order_id] = (0.0, o.remaining_quantity if covered else 0.0)\n        out = []\n        for act in src:\n            if isinstance(act, _ZCA):\n                free = cash\n                avail = yes\n                live = {}\n                out.append(act)\n            elif isinstance(act, _ZCO):\n                rel = live.pop(act.order_id, None)\n                if rel is not None:\n                    free += rel[0]\n                    avail += rel[1]\n                out.append(act)\n            elif isinstance(act, _ZPO):\n                f = rb if act.side is _ZSide.BUY else ra\n                q0 = float(act.quantity)\n                if f == 1.0:\n                    q = int(q0 * 100.0 + 1e-6) / 100.0\n                else:\n                    q = max(0.01, int(q0 * f * 100.0 + 1e-6) / 100.0)\n                price = act.price_ticks / 100.0\n                if act.side is _ZSide.BUY:\n                    need = price * q\n                    use_yes = 0.0\n                else:\n                    use_yes = min(q, avail)\n                    need = (1.0 - price) * (q - use_yes)\n                if free - need < 1e-6:\n                    return None\n                free -= need\n                avail -= use_yes\n                if act.client_order_id is not None:\n                    live[act.client_order_id] = (need, use_yes)\n                out.append(act if f == 1.0 else _ZPO(act.side, act.price_ticks, q, act.client_order_id))\n            else:\n                out.append(act)\n        return out\n",
 "code_sha256": "1a930d17d399b7f6491e0b2c6d3c7a4e46376fd106ffc2b1c508106391664e11",
 "assembled_sha256": "9a1ca39e05580cc0936f7705a43b36bf1970c398c05d2fda5a51bf39b68f3ee0",
 "n_sha256": "bf0d179f3e47d28819f6fa7e0d25548c2ced43374c216d36460b00a26a26ffae",
 "tuning": {
  "seeds": "320000..320199",
  "n": 200,
  "selected": {
   "name": "up",
   "rb": 1.3,
   "ra": 1.3,
   "spreads_acted": [
    1,
    2,
    3,
    4
   ],
   "rule": "highest paired mean difference vs N on the tuning seeds; all three were negative, the least negative was frozen",
   "tuning_score": 98.242465,
   "tuning_mean_diff": -0.228254,
   "tuning_se": 0.178406
  },
  "incumbent_mean": 98.470718,
  "variants": [
   {
    "name": "up",
    "rb": 1.3,
    "ra": 1.3,
    "spreads_acted": [
     1,
     2,
     3,
     4
    ],
    "tuning_score": 98.242465,
    "overall": {
     "n": 200,
     "sum_d": -45.650745,
     "sum_d2": 1277.200694,
     "mean_diff": -0.228254,
     "se": 0.178406,
     "incumbent_mean": 98.470718,
     "candidate_mean": 98.242465,
     "retail_diff": 0.462371,
     "arb_diff": -0.690625
    },
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": 1.383279,
      "sum_d2": 18.490682,
      "mean_diff": 0.027666,
      "se": 0.086785,
      "incumbent_mean": 25.711261,
      "candidate_mean": 25.738927,
      "retail_diff": -0.248599,
      "arb_diff": 0.276264
     },
     "2": {
      "n": 50,
      "sum_d": -3.470644,
      "sum_d2": 166.359227,
      "mean_diff": -0.069413,
      "se": 0.260391,
      "incumbent_mean": 61.219909,
      "candidate_mean": 61.150496,
      "retail_diff": 0.847702,
      "arb_diff": -0.917115
     },
     "3": {
      "n": 48,
      "sum_d": -38.174427,
      "sum_d2": 553.823719,
      "mean_diff": -0.795301,
      "se": 0.481697,
      "incumbent_mean": 130.834243,
      "candidate_mean": 130.038942,
      "retail_diff": 0.767569,
      "arb_diff": -1.56287
     },
     "4": {
      "n": 52,
      "sum_d": -5.388953,
      "sum_d2": 538.527066,
      "mean_diff": -0.103634,
      "se": 0.450393,
      "incumbent_mean": 174.375798,
      "candidate_mean": 174.272164,
      "retail_diff": 0.493765,
      "arb_diff": -0.597398
     }
    }
   },
   {
    "name": "dn",
    "rb": 0.7,
    "ra": 0.7,
    "spreads_acted": [
     1,
     2,
     3,
     4
    ],
    "tuning_score": 96.423577,
    "overall": {
     "n": 200,
     "sum_d": -409.428281,
     "sum_d2": 47891.797258,
     "mean_diff": -2.047141,
     "se": 1.087314,
     "incumbent_mean": 98.470718,
     "candidate_mean": 96.423577,
     "retail_diff": -0.157517,
     "arb_diff": -1.889624
    },
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": -42.957944,
      "sum_d2": 3216.815185,
      "mean_diff": -0.859159,
      "se": 1.139264,
      "incumbent_mean": 25.711261,
      "candidate_mean": 24.852103,
      "retail_diff": -1.87776,
      "arb_diff": 1.018601
     },
     "2": {
      "n": 50,
      "sum_d": 11.703491,
      "sum_d2": 66.982212,
      "mean_diff": 0.23407,
      "se": 0.161931,
      "incumbent_mean": 61.219909,
      "candidate_mean": 61.453978,
      "retail_diff": -0.605802,
      "arb_diff": 0.839871
     },
     "3": {
      "n": 48,
      "sum_d": -10.08025,
      "sum_d2": 117.826782,
      "mean_diff": -0.210005,
      "se": 0.226473,
      "incumbent_mean": 130.834243,
      "candidate_mean": 130.624238,
      "retail_diff": -1.092582,
      "arb_diff": 0.882576
     },
     "4": {
      "n": 52,
      "sum_d": -368.093579,
      "sum_d2": 44490.173078,
      "mean_diff": -7.078723,
      "se": 3.974112,
      "incumbent_mean": 174.375798,
      "candidate_mean": 167.297075,
      "retail_diff": 2.790742,
      "arb_diff": -9.869464
     }
    }
   },
   {
    "name": "ratio",
    "rb": 1.3,
    "ra": 0.7,
    "spreads_acted": [
     1,
     2,
     3,
     4
    ],
    "tuning_score": 97.045293,
    "overall": {
     "n": 200,
     "sum_d": -285.085159,
     "sum_d2": 44762.555839,
     "mean_diff": -1.425426,
     "se": 1.055688,
     "incumbent_mean": 98.470718,
     "candidate_mean": 97.045293,
     "retail_diff": 0.895119,
     "arb_diff": -2.320545
    },
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": -36.32233,
      "sum_d2": 3218.881117,
      "mean_diff": -0.726447,
      "se": 1.141516,
      "incumbent_mean": 25.711261,
      "candidate_mean": 24.984815,
      "retail_diff": -1.504689,
      "arb_diff": 0.778242
     },
     "2": {
      "n": 50,
      "sum_d": 20.297949,
      "sum_d2": 100.470071,
      "mean_diff": 0.405959,
      "se": 0.194023,
      "incumbent_mean": 61.219909,
      "candidate_mean": 61.625868,
      "retail_diff": 0.284161,
      "arb_diff": 0.121798
     },
     "3": {
      "n": 48,
      "sum_d": -29.537253,
      "sum_d2": 360.801866,
      "mean_diff": -0.615359,
      "se": 0.389709,
      "incumbent_mean": 130.834243,
      "candidate_mean": 130.218883,
      "retail_diff": -0.428419,
      "arb_diff": -0.18694
     },
     "4": {
      "n": 52,
      "sum_d": -239.523527,
      "sum_d2": 41082.402785,
      "mean_diff": -4.606222,
      "se": 3.882664,
      "incumbent_mean": 174.375798,
      "candidate_mean": 169.769576,
      "retail_diff": 5.011813,
      "arb_diff": -9.618035
     }
    }
   }
  ]
 },
 "paired": {
  "seeds": "430000..430499",
  "n": 500,
  "complete": true,
  "missing_seeds": [],
  "overall": {
   "n": 500,
   "sum_d": -172.573322,
   "sum_d2": 4915.084497,
   "mean_diff": -0.345147,
   "se": 0.139503,
   "incumbent_mean": 95.542015,
   "candidate_mean": 95.196868,
   "retail_diff": 0.400066,
   "arb_diff": -0.745212
  },
  "by_spread": {
   "1": {
    "n": 131,
    "sum_d": 1.655292,
    "sum_d2": 247.281806,
    "mean_diff": 0.012636,
    "se": 0.120495,
    "incumbent_mean": 38.277937,
    "candidate_mean": 38.290572,
    "retail_diff": -0.197605,
    "arb_diff": 0.210241
   },
   "2": {
    "n": 120,
    "sum_d": -69.895196,
    "sum_d2": 355.938503,
    "mean_diff": -0.58246,
    "se": 0.148576,
    "incumbent_mean": 77.855864,
    "candidate_mean": 77.273404,
    "retail_diff": 0.793835,
    "arb_diff": -1.376295
   },
   "3": {
    "n": 133,
    "sum_d": -57.511539,
    "sum_d2": 3402.411069,
    "mean_diff": -0.432418,
    "se": 0.438619,
    "incumbent_mean": 146.551404,
    "candidate_mean": 146.118986,
    "retail_diff": 0.623305,
    "arb_diff": -1.055723
   },
   "4": {
    "n": 116,
    "sum_d": -46.82188,
    "sum_d2": 909.45312,
    "mean_diff": -0.403637,
    "se": 0.258376,
    "incumbent_mean": 120.022047,
    "candidate_mean": 119.61841,
    "retail_diff": 0.411718,
    "arb_diff": -0.815355
   }
  }
 },
 "failures": [],
 "check_values": [
  17.116002,
  20.017111,
  2.390311,
  241.484752
 ],
 "python_version": "3.12.3",
 "seconds_per_simulation": 0.7158,
 "simulator": {
  "repo": "https://github.com/danrobinson/prediction-market-challenge",
  "commit": "b244530ee2a6247b5f930830eeca9dd950da0e7e",
  "unmodified": true,
  "steps": 2000,
  "serial": true,
  "simulations_run_measured": 1804
 },
 "verdict": "negative screen, not a promotion"
}
