Skip to content

146: Restore maker-rebate strategy as layer ​

Identity ​

  • Status: restoration design (open)
  • Spawned from: F6 of ADR-024 pivot, 2026-05-13
  • Original module: crates/pm-bot/src/domain/strategies/maker_rebate.rs (~3703 LOC at archive)
  • Recovery: git show 619f7f0:crates/pm-bot/src/domain/strategies/maker_rebate.rs + git show 619f7f0:crates/pm-bot/src/domain/strategies/shared/usdc.rs
  • Target taxonomy: split per ADR-018 — directional::MakerRebateSingleSide profile + binary-arb::PairedRebate profile (per CLAUDE.md taxonomy + 4-base-algorithms memory; currently SUPERSEDED via feedback_directional_first_core; restoration would need user re-decision on whether to keep split or fuse)
  • Original ADR: ADR-011 (paired maker rebate emission, IMPLEMENTED → ARCHIVED-BY-024)
  • Type: restoration

Context ​

Maker-rebate strategy emits passive maker orders to capture Polymarket's maker-rebate program. ADR-011 introduced paired YES+NO emission semantics with on-chain merge follow-up. Was production-deployed feature pre-ADR-024 pivot. Restoration must preserve paired emission semantics through ADR-025 Decision contract, without core engine modification.

Data model needs (from polymarket-data-model.md) ​

  • Market.tokens[0..2].best_bid/best_ask — both sides required for paired path
  • Market.tick_size — paired orders must respect per-side tick
  • Market.neg_risk — informs whether mergePositions (CTF) or mergePositions (NegRiskAdapter) is target
  • Per-side orderbook depth for cheaper-leg single-side variant

Restoration scope ​

  • New module: crates/pm-bot/src/domain/strategies/maker_rebate.rs (layer crate or in-tree)
  • Both profiles: MakerRebateSingleSide (cheaper-leg) AND PairedRebate (YES+NO coordinated)
  • Implement ScannerHooks + Strategy trait per ADR-025
  • Shared utility: USDC arithmetic helpers (recover shared/usdc.rs if not migrated)
  • Strategy config: maker_rebate.* knobs (rebate_bps, paired_enabled, ladder rungs, etc.)
  • Add StrategyType::MakerRebate variant back + dispatcher branch
  • Config schema: new crates/pm-bot/src/config/strategy/maker_rebate.rs (recover from 619f7f0)

Prerequisites ​

  • ADR-025 ReadCtx pattern (existing).
  • NEW Decision variant: Decision::PairedPlacement { yes_order, no_order } — current Decision enum (post-F4.5) only has single-order placement; paired emission requires atomic coordination. Pre-restoration commit must add this variant + executor handler.
  • Merge follow-up may reuse existing Decision::CallMergePositions if present, else add.
  • pm-sdk: no new contract calls beyond existing merge_positions / merge_positions_neg_risk.
  • Liveness/integration tests required: paired emission semantics regression test (was production feature; semantic regression test mandatory).

Out of scope ​

  • Не модифицировать core engine за пределами ScannerHooks impls + new Decision variant.
  • Не вводить новые traits в core layer.
  • Не trash strategy isolation invariant.

Acceptance criteria ​

  • ScannerHooks impl green per contract test pattern
  • Paired emission regression test (YES + NO coordinated placement and cancellation)
  • Single-side cheaper-leg integration test
  • VERIFIED markers per feedback_silent_feature_broken
  • ADR-011 amendment OR new ADR (post-024) confirming restoration semantics

Dependencies ​

  • Decision::PairedPlacement variant (prereq sub-task; might be merged into this commit chain).
  • Independent of #145 (maker) and #147 (merge-arb).
  • Independent of #148 (bucket-arb), #149 (single-token-mm).

LOC estimate ​

  • New strategy: ~2500-3500 LOC (originally 3703; slimmer via ReadCtx but paired logic complex)
  • New strategy config: ~250 LOC
  • Tests: ~600-900 LOC (paired semantics demands extensive coverage)
  • Decision::PairedPlacement wiring: ~200-300 LOC
  • Total: ~3500-5000 LOC

References ​

  • ADR-024, ADR-025, ADR-011
  • 619f7f0 (archive reference)
  • docs/architecture/strategy-extension-points.md §8 (restoration sketches)
  • CLAUDE.md taxonomy (ADR-018, 4-base-algorithms memory)