{
 "key": "f-lowp-bid-drop",
 "mech": "drop bids at very low probability: when the rival midpoint is below a cents, place no bids at all; tune a (3, 5, 8)",
 "approach": "Overlay on N. Rival midpoint is (best bid + best ask)/2, a missing side counted as 0 or 100. Below a cents, N's new bids are stripped and resting bids cancelled; asks and N's internal state stay as N left them. Cancels N later sends for bids the overlay removed are filtered, since the simulator fails a run on an unknown id. Frozen a=3 lost on the holdout on every spread, almost entirely retail edge, with arbitrage loss unchanged. Reject.",
 "tried": [
  "a=3, 5, 8 on all four spreads, tuning seeds 320000..320199: a=3 d=-17.195 (se 3.808), a=5 d=-49.214 (se 7.925), a=8 d=-63.596 (se 9.270); a=3 frozen as least negative. It was negative on all four spreads.",
  "Higher a does recover arbitrage loss on tuning (a=5 +7.850, a=8 +9.757) but gives up far more retail edge (-57.064, -73.353).",
  "No spread subset was tested as a variant: that would have been a fourth, and no spread was positive on tuning.",
  "Bug check on seeds 310000..310009 with a=3 and a=5 (outside tuning and holdout, not scored): no failed runs, no bid placed while active, and in the one exit seen (a=5, seed 310001) a bid was back on the same step. This range had few exits, so resumption is lightly tested."
 ],
 "next": "Do not take this further: bids at very low probability earn retail edge worth more than the arbitrage loss they avoid, and a=3 did not reduce arbitrage loss at all. Not measured here, and only a lead: the simulator sizes retail sells as notional / max(p, 0.05), which may be why these bids pay. Keeping or enlarging them may be worth testing, as may trimming only the size exposed to a sweep.",
 "spreads_acted": [
  1,
  2,
  3,
  4
 ],
 "off_equals_n": true,
 "code": "# f-lowp-bid-drop: when the rival midpoint is below A_CENTS, hold no bids.\nfrom orderbook_pm_challenge.types import CancelAll, CancelOrder, PlaceOrder, Side\n\n\nclass Strategy(_N):\n    A_CENTS = 3  # 0 switches the overlay off\n    SPREADS = (1, 2, 3, 4)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self._ov_gone = set()  # ids this overlay cancelled behind N's back\n\n    def _ov_active(self, state):\n        if getattr(self, \"s\", None) not in self.SPREADS:\n            return False\n        # A missing side of the ladder counts as the edge of the price range.\n        bid = state.competitor_best_bid_ticks\n        ask = state.competitor_best_ask_ticks\n        bid = 0 if bid is None else bid\n        ask = 100 if ask is None else ask\n        return (bid + ask) / 2.0 < self.A_CENTS\n\n    def on_step(self, state):\n        actions = list(super().on_step(state))\n        active = self._ov_active(state)\n        if not active and not self._ov_gone:\n            return actions\n\n        out = []\n        cleared = False\n        for act in actions:\n            if isinstance(act, CancelOrder):\n                # N may still cancel a bid that this overlay already removed:\n                # the simulator fails the run on an unknown id.\n                if act.order_id in self._ov_gone:\n                    self._ov_gone.discard(act.order_id)\n                    continue\n            elif isinstance(act, CancelAll):\n                cleared = True\n            elif isinstance(act, PlaceOrder):\n                if active and act.side is Side.BUY:\n                    continue\n                self._ov_gone.discard(act.client_order_id)\n            out.append(act)\n\n        if active and not cleared:\n            named = {a.order_id for a in out if isinstance(a, CancelOrder)}\n            front = []\n            for order in state.own_orders:\n                if order.side is Side.BUY and order.order_id not in named:\n                    front.append(CancelOrder(order.order_id))\n                    self._ov_gone.add(order.order_id)\n            out = front + out\n        return out\n",
 "code_sha256": "08bd50493fbfe3fbdb3f5943d0670ef30cd7747c572d1f89b434514e75764e9e",
 "assembled_sha256": "aa0bfae6008b597fed0038d697f020f8ed776005f35afd43d6f33d491b2d7223",
 "tuning": {
  "seeds": "320000..320199",
  "selected": "a3",
  "variants": {
   "a3": {
    "n": 200,
    "sum_d": -3439.033561,
    "sum_d2": 636406.19011,
    "mean_diff": -17.195168,
    "se": 3.808452,
    "incumbent_mean": 98.470718,
    "candidate_mean": 81.275551,
    "retail_diff": -17.111786,
    "arb_diff": -0.083382,
    "a_cents": 3,
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": -1194.21311,
      "mean_diff": -23.884262,
      "se": 8.285497,
      "incumbent_mean": 25.711261,
      "candidate_mean": 1.826999,
      "retail_diff": -26.504738,
      "arb_diff": 2.620476
     },
     "2": {
      "n": 50,
      "sum_d": -1523.479685,
      "mean_diff": -30.469594,
      "se": 10.719295,
      "incumbent_mean": 61.219909,
      "candidate_mean": 30.750315,
      "retail_diff": -27.218346,
      "arb_diff": -3.251247
     },
     "3": {
      "n": 48,
      "sum_d": -504.480473,
      "mean_diff": -10.51001,
      "se": 6.23558,
      "incumbent_mean": 130.834243,
      "candidate_mean": 120.324233,
      "retail_diff": -10.119835,
      "arb_diff": -0.390175
     },
     "4": {
      "n": 52,
      "sum_d": -216.860292,
      "mean_diff": -4.17039,
      "se": 2.593205,
      "incumbent_mean": 174.375798,
      "candidate_mean": 170.205408,
      "retail_diff": -4.816362,
      "arb_diff": 0.645972
     }
    }
   },
   "a5": {
    "n": 200,
    "sum_d": -9842.759977,
    "sum_d2": 2983862.442237,
    "mean_diff": -49.2138,
    "se": 7.924681,
    "incumbent_mean": 98.470718,
    "candidate_mean": 49.256918,
    "retail_diff": -57.064183,
    "arb_diff": 7.850383,
    "a_cents": 5,
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": -1190.008264,
      "mean_diff": -23.800165,
      "se": 8.842826,
      "incumbent_mean": 25.711261,
      "candidate_mean": 1.911096,
      "retail_diff": -33.734656,
      "arb_diff": 9.934491
     },
     "2": {
      "n": 50,
      "sum_d": -2027.203891,
      "mean_diff": -40.544078,
      "se": 12.814754,
      "incumbent_mean": 61.219909,
      "candidate_mean": 20.675831,
      "retail_diff": -47.44079,
      "arb_diff": 6.896712
     },
     "3": {
      "n": 48,
      "sum_d": -3026.208876,
      "mean_diff": -63.046018,
      "se": 19.365366,
      "incumbent_mean": 130.834243,
      "candidate_mean": 67.788225,
      "retail_diff": -72.312618,
      "arb_diff": 9.2666
     },
     "4": {
      "n": 52,
      "sum_d": -3599.338946,
      "mean_diff": -69.218057,
      "se": 19.354856,
      "incumbent_mean": 174.375798,
      "candidate_mean": 105.157742,
      "retail_diff": -74.674203,
      "arb_diff": 5.456146
     }
    }
   },
   "a8": {
    "n": 200,
    "sum_d": -12719.142384,
    "sum_d2": 4228716.313894,
    "mean_diff": -63.595712,
    "se": 9.269599,
    "incumbent_mean": 98.470718,
    "candidate_mean": 34.875006,
    "retail_diff": -73.353167,
    "arb_diff": 9.757455,
    "a_cents": 8,
    "by_spread": {
     "1": {
      "n": 50,
      "sum_d": -1222.594515,
      "mean_diff": -24.45189,
      "se": 9.03433,
      "incumbent_mean": 25.711261,
      "candidate_mean": 1.259371,
      "retail_diff": -35.133653,
      "arb_diff": 10.681762
     },
     "2": {
      "n": 50,
      "sum_d": -2170.511259,
      "mean_diff": -43.410225,
      "se": 13.400604,
      "incumbent_mean": 61.219909,
      "candidate_mean": 17.809683,
      "retail_diff": -51.793885,
      "arb_diff": 8.38366
     },
     "3": {
      "n": 48,
      "sum_d": -4038.819265,
      "mean_diff": -84.142068,
      "se": 22.142202,
      "incumbent_mean": 130.834243,
      "candidate_mean": 46.692175,
      "retail_diff": -95.947558,
      "arb_diff": 11.80549
     },
     "4": {
      "n": 52,
      "sum_d": -5287.217344,
      "mean_diff": -101.677257,
      "se": 23.632917,
      "incumbent_mean": 174.375798,
      "candidate_mean": 72.698542,
      "retail_diff": -109.976417,
      "arb_diff": 8.29916
     }
    }
   }
  }
 },
 "paired": {
  "seeds": "430000..430499",
  "n": 500,
  "complete": true,
  "missing_seeds": [],
  "overall": {
   "n": 500,
   "sum_d": -12159.100802,
   "sum_d2": 3760198.217208,
   "mean_diff": -24.318202,
   "se": 3.726367,
   "incumbent_mean": 95.542015,
   "candidate_mean": 71.223814,
   "retail_diff": -24.301712,
   "arb_diff": -0.01649
  },
  "by_spread": {
   "1": {
    "n": 131,
    "sum_d": -4912.629408,
    "sum_d2": 1819596.540351,
    "mean_diff": -37.500988,
    "se": 9.799421,
    "incumbent_mean": 38.277937,
    "candidate_mean": 0.776949,
    "retail_diff": -34.901391,
    "arb_diff": -2.599597
   },
   "2": {
    "n": 120,
    "sum_d": -4362.906133,
    "sum_d2": 1332976.162922,
    "mean_diff": -36.357551,
    "se": 9.06849,
    "incumbent_mean": 77.855864,
    "candidate_mean": 41.498313,
    "retail_diff": -42.828031,
    "arb_diff": 6.47048
   },
   "3": {
    "n": 133,
    "sum_d": -1632.597142,
    "sum_d2": 372518.2408,
    "mean_diff": -12.275166,
    "se": 4.480775,
    "incumbent_mean": 146.551404,
    "candidate_mean": 134.276237,
    "retail_diff": -10.821057,
    "arb_diff": -1.45411
   },
   "4": {
    "n": 116,
    "sum_d": -1250.968118,
    "sum_d2": 235107.273136,
    "mean_diff": -10.784208,
    "se": 4.075897,
    "incumbent_mean": 120.022047,
    "candidate_mean": 109.237839,
    "retail_diff": -8.622495,
    "arb_diff": -2.161713
   }
  }
 },
 "failures": 0,
 "check_values": {
  "310000": 17.116002,
  "310001": 20.017111,
  "310002": 2.390311,
  "310003": 241.484752
 },
 "python_version": "3.12.3",
 "seconds_per_simulation": 0.751
}