{
 "key": "f-microprice-shift",
 "mech": "microprice shift",
 "approach": "StepState does not expose rival sizes, so imbalance is rebuilt from the simulator's rule that every rival level holds quote_notional/price shares: top sizes are proportional to 1/bid and 1/ask, imb=(a-b)/(a+b) (quote_notional cancels). imb>+t moves N's new asks one tick up, imb<-t moves new bids one tick down; N is shown its shifted orders at their original prices so it does not chase them. This proxy is always >=0, so only asks shift, at low prices or wide spreads. Every t tried lost about 30 of edge (retail falls, arbitrage barely changes).",
 "tried": [
  "t=0.05: tuning -42.50 (se 5.60)",
  "t=0.1: tuning -37.34 (se 5.49)",
  "t=0.2: tuning -30.35 (se 5.00), frozen; holdout -30.88 (se 3.09)"
 ],
 "next": "Drop this mechanism: raising N's ask gives up retail edge and saves little arbitrage loss. A real size-imbalance signal would need the rival's remaining sizes, which StepState does not provide. A partial-depletion estimate built from rival best-quote moves could be screened as a separate idea.",
 "spreads_acted": [
  1,
  2,
  3,
  4
 ],
 "off_equals_n": {
  "seeds": "310000..310009",
  "equal_every_step": true,
  "steps_per_seed": 2000
 },
 "code": "# Overlay f-microprice-shift on incumbent N.\n# The rival's resting sizes are not in StepState; the simulator sizes every\n# rival level at quote_notional/price, so the rival's top-of-book sizes are\n# rebuilt as proportional to 1/bid and 1/ask (quote_notional cancels).\n# imb = (Sb - Sa)/(Sb + Sa). imb > +T: our new asks go one tick up;\n# imb < -T: our new bids go one tick down. N sees its own resting orders at\n# the prices it asked for, so it does not chase the shifted ones.\nimport dataclasses\n\nMP_T = 0.2\nMP_ON = True\nMP_SPREADS = (1, 2, 3, 4)\n\n\nclass Strategy(_N):\n    def __init__(self, *a, **k):\n        super().__init__(*a, **k)\n        self._mp_shift = {}\n        self._mp_k = 0\n\n    def on_step(self, state):\n        if not MP_ON:\n            return super().on_step(state)\n        if self._mp_shift and state.own_orders:\n            live = set()\n            views = []\n            for o in state.own_orders:\n                d = self._mp_shift.get(o.order_id)\n                if d:\n                    live.add(o.order_id)\n                    o = dataclasses.replace(o, price_ticks=o.price_ticks - d)\n                views.append(o)\n            self._mp_shift = {i: self._mp_shift[i] for i in live}\n            state = dataclasses.replace(state, own_orders=tuple(views))\n        acts = super().on_step(state)\n        if getattr(self, \"s\", None) not in MP_SPREADS:\n            return acts\n        b = state.competitor_best_bid_ticks\n        a = state.competitor_best_ask_ticks\n        if b is None or a is None or b <= 0 or a <= 0:\n            return acts\n        sb = 1.0 / b\n        sa = 1.0 / a\n        imb = (sb - sa) / (sb + sa)\n        if imb > MP_T:\n            side, d = Side.SELL, 1\n        elif imb < -MP_T:\n            side, d = Side.BUY, -1\n        else:\n            return acts\n        out = []\n        for x in acts:\n            if isinstance(x, PlaceOrder) and x.side is side and 1 <= x.price_ticks + d <= 99:\n                cid = x.client_order_id\n                if cid is None:\n                    self._mp_k += 1\n                    cid = \"mp-%d\" % self._mp_k\n                x = PlaceOrder(side=x.side, price_ticks=x.price_ticks + d,\n                               quantity=x.quantity, client_order_id=cid)\n                self._mp_shift[cid] = d\n            out.append(x)\n        return out\n",
 "code_sha256": "032ddde692ad498208dda62a07a9a59819fe2fb6b8bfb6ca870bc108a82c6d39",
 "assembled_sha256": "81ca9d5bb8ff5eccaf768e19ac4281a6d2a8928f3050f05be5694493768987d6",
 "tuning": {
  "seeds": "320000..320199",
  "selected": {
   "t": 0.2
  },
  "variants": [
   {
    "t": 0.05,
    "overall": {
     "n": 200,
     "sum_d": -8499.510067,
     "sum_d2": 1607862.340855,
     "mean_diff": -42.49755,
     "se": 5.596692,
     "incumbent_mean": 98.470718,
     "candidate_mean": 55.973168,
     "retail_diff": -45.419535,
     "arb_diff": 2.921985
    },
    "by_spread_mean_diff": {
     "1": -14.196971,
     "2": -23.702312,
     "3": -54.677637,
     "4": -76.538833
    }
   },
   {
    "t": 0.1,
    "overall": {
     "n": 200,
     "sum_d": -7468.670297,
     "sum_d2": 1476422.190924,
     "mean_diff": -37.343351,
     "se": 5.485286,
     "incumbent_mean": 98.470718,
     "candidate_mean": 61.127367,
     "retail_diff": -39.715137,
     "arb_diff": 2.371786
    },
    "by_spread_mean_diff": {
     "1": -14.8877,
     "2": -20.426636,
     "3": -48.081594,
     "4": -65.289174
    }
   },
   {
    "t": 0.2,
    "overall": {
     "n": 200,
     "sum_d": -6070.187145,
     "sum_d2": 1177699.587048,
     "mean_diff": -30.350936,
     "se": 4.996139,
     "incumbent_mean": 98.470718,
     "candidate_mean": 68.119783,
     "retail_diff": -32.093555,
     "arb_diff": 1.742619
    },
    "by_spread_mean_diff": {
     "1": -10.137253,
     "2": -16.410898,
     "3": -40.333672,
     "4": -53.976217
    }
   }
  ]
 },
 "paired": {
  "seeds": "430000..430499",
  "n": 500,
  "complete": true,
  "missing_seeds": [],
  "overall": {
   "n": 500,
   "sum_d": -15437.669677,
   "sum_d2": 2853642.679767,
   "mean_diff": -30.875339,
   "se": 3.086592,
   "incumbent_mean": 95.542015,
   "candidate_mean": 64.666676,
   "retail_diff": -32.743386,
   "arb_diff": 1.868046
  },
  "by_spread": {
   "1": {
    "n": 131,
    "sum_d": -1698.026052,
    "sum_d2": 406750.158341,
    "mean_diff": -12.962031,
    "se": 4.753095,
    "incumbent_mean": 38.277937,
    "candidate_mean": 25.315906,
    "retail_diff": -16.660331,
    "arb_diff": 3.6983
   },
   "2": {
    "n": 120,
    "sum_d": -3451.62474,
    "sum_d2": 434674.41935,
    "mean_diff": -28.76354,
    "se": 4.846332,
    "incumbent_mean": 77.855864,
    "candidate_mean": 49.092325,
    "retail_diff": -29.895527,
    "arb_diff": 1.131987
   },
   "3": {
    "n": 133,
    "sum_d": -5642.933895,
    "sum_d2": 1136871.486736,
    "mean_diff": -42.428074,
    "se": 7.149785,
    "incumbent_mean": 146.551404,
    "candidate_mean": 104.123329,
    "retail_diff": -45.863275,
    "arb_diff": 3.4352
   },
   "4": {
    "n": 116,
    "sum_d": -4645.084989,
    "sum_d2": 875346.61534,
    "mean_diff": -40.043836,
    "se": 7.188507,
    "incumbent_mean": 120.022047,
    "candidate_mean": 79.978211,
    "retail_diff": -38.809576,
    "arb_diff": -1.234261
   }
  }
 },
 "failures": [],
 "check_values": {
  "310000": 17.116002,
  "310001": 20.017111,
  "310002": 2.390311,
  "310003": 241.484752
 },
 "python_version": "3.14.4",
 "seconds_per_simulation": 1.39,
 "notes": "Simulator at commit b244530 unmodified; serial engine runs, no --workers/--sandbox; up to 4 independent single-process runs at once on disjoint (seed,strategy) sets; each (seed,strategy) run exactly once. Screen, not a promotion."
}