{
 "key": "f-late-widen",
 "mech": "f-late-widen",
 "approach": "Overlay on N: when steps_remaining <= W (W frozen at 100), every N order is placed one tick further from the rival midpoint (bids -1, asks +1, clamped to 1..99), sizes unchanged; orders already resting when the window opens are cancelled and re-placed one tick out under the same id. N sees its own orders at the prices it asked for, so its logic runs unchanged. Result: a large loss, almost all retail edge, because late fills at N's prices are worth a lot and one tick back gives them to the rival.",
 "tried": [
  "W=100 tuning d=-15.56 se 1.66",
  "W=200 tuning d=-28.06 se 2.95",
  "W=400 tuning d=-46.75 se 5.11",
  "froze W=100 (least negative), all spreads; holdout d=-14.15 se 1.15"
 ],
 "next": "Drop late widening: it loses on every spread and the loss grows with W, so late retail fills are valuable and N should keep them. The opposite direction (late tightening, or a larger late size where the arb risk is small) is untested here. A rerun would also need a fix: place the re-placed orders before N's new orders, since 4 holdout runs failed on collateral.",
 "spreads_acted": [
  1,
  2,
  3,
  4
 ],
 "off_equals_n": {
  "seeds": "310000..310009",
  "steps_compared": 20000,
  "mismatched_steps": 0,
  "equal": true,
  "how": "LATE_W=0; N and overlay fed the identical StepState every step, repr of action lists compared"
 },
 "code": "# f-late-widen overlay: in the last W steps every N order sits one tick\n# further from the rival midpoint (bids -1, asks +1); sizes unchanged.\n# N is shown its own orders at the prices it asked for, so its logic is unchanged.\nfrom dataclasses import replace as _dc_replace\nfrom orderbook_pm_challenge.types import CancelAll as _CA, CancelOrder as _CO, PlaceOrder as _PO, Side as _Side\n\nLATE_W = 100\nACT_SPREADS = (1, 2, 3, 4)\n\n\nclass Strategy(_N):\n    def __init__(self, *a, **k):\n        super().__init__(*a, **k)\n        self._lw_shift = {}\n        self._lw_n = 0\n\n    def _lw_tick(self, side, px):\n        q = px - 1 if side == _Side.BUY else px + 1\n        return q if 1 <= q <= 99 else px\n\n    def on_step(self, state):\n        sh = self._lw_shift\n        if sh:\n            live = {o.order_id for o in state.own_orders}\n            for oid in list(sh):\n                if oid not in live:\n                    del sh[oid]\n            view = tuple(_dc_replace(o, price_ticks=o.price_ticks - sh[o.order_id]) if o.order_id in sh else o\n                         for o in state.own_orders)\n            state = _dc_replace(state, own_orders=view)\n        acts = super().on_step(state)\n        if LATE_W <= 0 or state.steps_remaining > LATE_W or getattr(self, \"s\", None) not in ACT_SPREADS:\n            return acts\n        acts = list(acts or [])\n        out = []\n        cancelled = set()\n        wiped = False\n        for a in acts:\n            if isinstance(a, _PO):\n                oid = a.client_order_id\n                if oid is None:\n                    self._lw_n += 1\n                    oid = \"lw%d\" % self._lw_n\n                px = self._lw_tick(a.side, a.price_ticks)\n                sh[oid] = px - a.price_ticks\n                out.append(_PO(side=a.side, price_ticks=px, quantity=a.quantity, client_order_id=oid))\n            else:\n                if isinstance(a, _CA):\n                    wiped = True\n                elif isinstance(a, _CO):\n                    cancelled.add(a.order_id)\n                out.append(a)\n        pre, post = [], []\n        if not wiped:\n            for o in state.own_orders:\n                if o.order_id in sh or o.order_id in cancelled:\n                    continue\n                px = self._lw_tick(o.side, o.price_ticks)\n                if px == o.price_ticks:\n                    continue\n                pre.append(_CO(o.order_id))\n                post.append(_PO(side=o.side, price_ticks=px, quantity=o.remaining_quantity, client_order_id=o.order_id))\n                sh[o.order_id] = px - o.price_ticks\n        return pre + out + post\n",
 "code_sha256": "6d2f94dae65d158bf0b26183a5f70750229109979d6054769d5127bc0c2974c6",
 "assembled_sha256": "65be48cbb1500035cc0ab5ede6aa060fa3f67e1c02a1b99ced01be5ed6173404",
 "n_sha256": "bf0d179f3e47d28819f6fa7e0d25548c2ced43374c216d36460b00a26a26ffae",
 "tuning": {
  "seeds": "320000..320199",
  "selected": "W100",
  "variants": {
   "W100": {
    "W": 100,
    "overall": {
     "n": 200,
     "mean_diff": -15.557867378893507,
     "se": 1.6582036835384026,
     "retail_diff": -16.231554870233467,
     "arb_diff": 0.6736874913230118
    },
    "by_spread_mean_diff": {
     "1": [
      -10.127,
      2.607
     ],
     "2": [
      -14.43,
      3.445
     ],
     "3": [
      -16.691,
      3.457
     ],
     "4": [
      -20.818,
      3.565
     ]
    }
   },
   "W200": {
    "W": 200,
    "overall": {
     "n": 200,
     "mean_diff": -28.055027143984994,
     "se": 2.949801074746473,
     "retail_diff": -29.2322746893921,
     "arb_diff": 1.17724754539449
    },
    "by_spread_mean_diff": {
     "1": [
      -18.297,
      5.334
     ],
     "2": [
      -22.636,
      5.413
     ],
     "3": [
      -30.985,
      6.261
     ],
     "4": [
      -39.943,
      6.214
     ]
    }
   },
   "W400": {
    "W": 400,
    "overall": {
     "n": 200,
     "mean_diff": -46.749935029562984,
     "se": 5.112054188704644,
     "retail_diff": -49.54590128003308,
     "arb_diff": 2.795966250465007
    },
    "by_spread_mean_diff": {
     "1": [
      -22.518,
      6.629
     ],
     "2": [
      -35.087,
      8.803
     ],
     "3": [
      -54.596,
      11.034
     ],
     "4": [
      -74.021,
      12.129
     ]
    }
   }
  }
 },
 "paired": {
  "seeds": "430000..430499",
  "n": 500,
  "complete": true,
  "missing_seeds": [],
  "overall": {
   "n": 500,
   "sum_d": -7074.6297460202,
   "sum_d2": 432628.473255611,
   "mean_diff": -14.1492594920404,
   "se": 1.1544593355294224,
   "incumbent_mean": 95.54587347343701,
   "candidate_mean": 81.3966139813965,
   "retail_diff": -15.234180397404089,
   "arb_diff": 1.0849209053983841
  },
  "by_spread": {
   "1": {
    "n": 131,
    "sum_d": -1307.5303462037,
    "sum_d2": 61055.9873498945,
    "mean_diff": -9.981147680944275,
    "se": 1.6789486872704973,
    "incumbent_mean": 38.27342786619541,
    "candidate_mean": 28.29228018525116,
    "retail_diff": -10.199723174550428,
    "arb_diff": 0.21857549363282658
   },
   "2": {
    "n": 120,
    "sum_d": -1712.8634670041,
    "sum_d2": 70081.8273283534,
    "mean_diff": -14.273862225034167,
    "se": 1.7876139792467771,
    "incumbent_mean": 77.87680751697249,
    "candidate_mean": 63.602945291938354,
    "retail_diff": -15.459700668155065,
    "arb_diff": 1.1858384431316722
   },
   "3": {
    "n": 133,
    "sum_d": -2346.811966464599,
    "sum_d2": 219282.29516225538,
    "mean_diff": -17.645202755372928,
    "se": 3.183034907190754,
    "incumbent_mean": 146.5514036364661,
    "candidate_mean": 128.9062008810932,
    "retail_diff": -20.566060521201507,
    "arb_diff": 2.920857765877482
   },
   "4": {
    "n": 116,
    "sum_d": -1707.423966347799,
    "sum_d2": 82208.36341510764,
    "mean_diff": -14.719172123687922,
    "se": 2.068477196760355,
    "incumbent_mean": 120.02210431517413,
    "candidate_mean": 105.30293219148615,
    "retail_diff": -14.573071839116295,
    "arb_diff": -0.14610028451897605
   }
  },
  "overall_excluding_failed_seeds": {
   "n": 496,
   "mean_diff": -14.117619259839715,
   "se": 1.156910229156101,
   "retail_diff": -15.166810167916239,
   "arb_diff": 1.0491909081112851
  }
 },
 "failures": {
  "count": 4,
  "note": "Failed runs counted with the edge the engine reported at failure (SimulationResult with failed=True); N had no failures. Probable cause: re-placed resting orders were emitted after N's new orders, which could have used the collateral the cancels freed.",
  "runs": [
   {
    "seed": 430009,
    "strategy": "candidate W=100",
    "error": "orderbook_pm_challenge.market.OrderBookError: Insufficient free cash for order collateral",
    "spread": 1,
    "total_edge_at_failure": 4.260062
   },
   {
    "seed": 430171,
    "strategy": "candidate W=100",
    "error": "orderbook_pm_challenge.market.OrderBookError: Insufficient free cash for order collateral",
    "spread": 1,
    "total_edge_at_failure": -11.363443
   },
   {
    "seed": 430185,
    "strategy": "candidate W=100",
    "error": "orderbook_pm_challenge.market.OrderBookError: Insufficient free cash for order collateral",
    "spread": 1,
    "total_edge_at_failure": -6.619581
   },
   {
    "seed": 430212,
    "strategy": "candidate W=100",
    "error": "orderbook_pm_challenge.market.OrderBookError: Insufficient free cash for order collateral",
    "spread": 3,
    "total_edge_at_failure": 343.390495
   }
  ]
 },
 "check_values": {
  "310000": 17.116002,
  "310001": 20.017111,
  "310002": 2.390311,
  "310003": 241.484752
 },
 "python_version": "3.10.12",
 "seconds_per_simulation": 0.787,
 "simulator": "danrobinson/prediction-market-challenge @ b244530ee2a6247b5f930830eeca9dd950da0e7e, unmodified, serial, default ChallengeConfig/ParameterVariance, 2000 steps",
 "screen_only": true
}