Skip to content

TD3-B — Maker-Rebate Hook Migration & LegacyStrategy Trait Removal ​

Historical sprint summary — TD3-B was completed 2026-04-21 (cutover). Archived under docs/history/sprints/ as a record of the final LegacyStrategy trait deletion. Not a living doc.

Branch: worktree-agent-a1acabb6Baseline: 004b621 (RTDS R.12) Cutover date: 2026-04-21

Summary ​

TD3-B finishes the multi-sprint cleanup that started with TD3-A (bucket-arb hook authoritative). With this sprint:

  1. Maker-rebate's discovery + placement migrated to the Strategy::evaluate_periodic hook (MakerRebateStrategy), exactly reproducing the legacy OrderManager::discover_and_place + legacy::maker_rebate::evaluate pipeline (single-side cheaper-leg parity preserved per Phase 1 limitation).
  2. The legacy LegacyStrategy trait, Box<dyn LegacyStrategy> dispatcher, OrderManager::discover_and_place (~1397 LOC), place_bucket_arb_group_parallel helper, and the entire strategies::legacy/ subtree were retired — every strategy now dispatches through the new Strategy + StrategyEngine pipeline exclusively.
  3. The bucket_arb_hooks_emit_decisions kill-switch flag (retained for one release cycle past TD3-A) was deleted along with its 3 gate sites, 2 unit tests, the simulator's legacy evaluate_events_for_poll shim, the 586-LOC e2e_hook_parity_replay harness, and 4 dependent simulator tests. There is no longer a legacy execution arm to roll back to.

Commits ​

CommitStepWhat
b1e7f7eTD3-B.1Migrate maker-rebate paired-bid logic to evaluate_periodic hook
bf29e85TD3-B.3Delete legacy/maker_rebate.rs evaluator
201bc96TD3-B.4Delete LegacyStrategy trait + discover_and_place + Box<dyn> selector
62b31cfTD3-B.5Delete bucket_arb_hooks_emit_decisions flag + evaluate_events_for_poll shim

(TD3-B.2 — new MakerRebatePlacementClient trait — was unnecessary; the maker-rebate hook emits Decision::PlaceOrder which already routes through the existing OrderClient::place_limit_order.)

LOC delta ​

FileDelta
crates/pm-bot/src/strategies/maker_rebate.rs+570 / -32
crates/pm-bot/src/strategies/legacy/maker_rebate.rs-395 (deleted)
crates/pm-bot/src/strategies/legacy/mod.rs-108 (deleted)
crates/pm-bot/src/strategies/legacy/no_op.rs-110 (deleted)
crates/pm-bot/src/strategies/legacy/ (directory)gone
crates/pm-bot/src/order_manager.rs-1397 (discover_and_place + place_bucket_arb_group_parallel)
crates/pm-bot/src/scanner.rs-45 (maker_loop arg cleanup, dispatch swap)
crates/pm-bot/src/main.rs-25 (selector + dry-run dispatch swap)
crates/pm-bot/src/weather/context.rs+72 (new — migrated from legacy/)
crates/pm-bot/src/simulator/engine.rs-190 (evaluate_events_for_poll shim)
crates/pm-bot/src/config.rs-45 (flag field, env parse, 2 unit tests)
crates/pm-bot/tests/e2e_hook_parity_replay.rs-586 (deleted)
crates/pm-bot/tests/{strategy_partition,sync_order_status_rest_path,ws_fill_before_insert_race,bucket_arb_no_exit_sell}.rs-16 (flag setters)

Net LOC: ~ -2 277 LOC removed from pm-bot.

Test count ​

Phasepm-bot libTotal (lib + integration + doctests)
Baseline (RTDS R.12, 004b621)839~942
After TD3-B.1847(+8 new periodic tests)
After TD3-B.3834(-13 legacy maker-rebate tests)
After TD3-B.4831(-3 no-op stub name tests)
After TD3-B.5824949

Net library delta: -15 (added 8 new functional tests, removed 23 tests for code that no longer exists).

Files removed ​

  • crates/pm-bot/src/strategies/legacy/maker_rebate.rs
  • crates/pm-bot/src/strategies/legacy/mod.rs
  • crates/pm-bot/src/strategies/legacy/no_op.rs
  • crates/pm-bot/src/strategies/legacy/ directory
  • crates/pm-bot/tests/e2e_hook_parity_replay.rs

Files added ​

  • crates/pm-bot/src/weather/context.rs — BotMarketSnapshot + WeatherContext migrated from the deleted legacy/ module (sole consumer is bin/backtest.rs).
  • td3-b-cleanup-report.md (this file).

Maker-rebate functional verification ​

  • Unit: 7 new periodic_tests cover happy path (cheaper-side emission, tie-break to YES), dedup paths (open-order skip, filled-position skip, slug mismatch), neg-risk skip, combined-too-high skip, and live-orderbook override of cached best_bid. All green.
  • Webhook + RTDS: pre-existing webhook_tests (3) + RTDS toxic-flow tests (4) continue green — preserved verbatim.
  • E2E: pm-bot is configured with BOT_STRATEGY=maker-rebate to run the engine path; MarketCache + OrderManagerRepository are attached unconditionally in main.rs. The first engine.tick_periodic() fires from scanner::maker_loop initial discovery (replacing the legacy initial discover_and_place), then on every fallback scan (fallback_scan_secs) and every 10 s basket watchdog tick (idempotent under repository dedup).

Live-test status: not validated against production CLOB in this sprint — recommended before flipping to live trading. The hook emits Decision::PlaceOrder with the same shape the previous OrderManager::clob().buy(...) call produced (Side::Buy, OrderType::Gtd, post_only=true, gtd_seconds = config.gtd_expire_secs, size = floor(budget_per_market / price) capped at min 5 shares).

Phase 1 invariants ​

INV-5/6/7/20/21/22/23/25/26/27 (bucket-arb basket placement invariants) are unaffected. TD3-B.4 deleted OrderManager::discover_and_place and the bucket-arb-specific place_bucket_arb_group_parallel helper, but OrderManager::place_bucket_arb_from_fsm (the canonical primitive called by OrderManagerBucketArbPlacementClient from the hook path's Decision::PostBucketArbBasket) and cancel_basket_open_orders (called by OrderManagerAbandonClient on Decision::AbandonBasket) are kept verbatim.

Build / test status ​

  • cargo build -p pm-bot --release: GREEN (3 m 15 s, 0 warnings)
  • cargo test -p pm-bot --lib: GREEN (824 / 824)
  • cargo test -p pm-bot (full suite incl. integration tests + doctests): GREEN (949 / 949)

pm-orchestrator has a pre-existing NEG_RISK_ADAPTER_ADDRESS import error (5 errors) unrelated to TD3-B — verified by stashing this branch's diff and re-running the workspace check on baseline. That issue belongs to the orchestrator binary's own pm-sdk upgrade work and is out of scope here.

What remains for TD4 / future sprints ​

  • TD4 (final rebuild) — operator-facing docs + .env.example cleanup pass, removal of stale rustdoc references to discover_and_place and LegacyStrategy (a handful of inline comments in order_manager.rs mention them historically).
  • #16 live test — recommended pre-cutover validation of the maker-rebate hook path against production CLOB on a small capital allocation.
  • Two-sided maker-rebate placement — current hook preserves the Phase 1 single-side parity (one cheaper leg per market). The RebatePair state machine in MakerRebateStrategy is wired but not yet driven; a future sprint can land paired YES + NO emission on top of the existing structure without disturbing the TD3-B contract.
  • pm-weather::trading — the #![cfg(any())]-gated reference source still imports super::{BotMarketSnapshot, Signal, Strategy} (preserved as-is per the file's docstring); rewire onto pm_common types when WeatherEdge gets re-introduced under the unified Directional strategy.