Тема
148: Restore bucket-arb strategy as layer
Identity
- Status: restoration design (open, multiple prereq blockers)
- Spawned from: F6 of ADR-024 pivot, 2026-05-13
- Original module:
crates/pm-bot/src/domain/strategies/bucket_arb/(~7200 LOC, multi-file at archive) - Recovery:
git show 619f7f0 -- crates/pm-bot/src/domain/strategies/bucket_arb/ - Target taxonomy:
multi-arb::Basketprofile (per ADR-018) - Original ADR: none specific (was implementation of ADR-018 §multi-arb)
- Type: restoration (largest)
Context
Bucket-arb captures arbitrage on neg-risk multi-outcome events with ≥3 buckets, where Σ(bucket_prices) drifts from 1.0 → can short the basket. FSM tracks N child markets simultaneously, posts coordinated basket orders, and exits на convertPositions post-resolution. Per Agent A: 63.5% production markets are neg-risk — high-value target. Largest archived strategy (~7200 LOC across multiple files).
Data model needs (from polymarket-data-model.md)
- Event-level view:
Event.markets[]— children sharingneg_risk_market_id - Per-child:
Market.tokens[0..2].best_bid/best_ask,Market.tick_size Market.neg_risk(must be true)Market.condition_idper child +Event.neg_risk_market_idparent- Cross-market Σ-price aggregation for basket valuation
Restoration scope
- New module tree:
crates/pm-bot/src/domain/strategies/bucket_arb/(layer) - Profile
Basketper ADR-018 §multi-arb - FSM phases (recover from 619f7f0): discovery → eligibility → entry → maintain → exit
- Implement
ScannerHooks+Strategytrait per ADR-025 - Strategy config:
multi_arb.*knobs (basket_min_n, target_sum_margin_bps, etc.) - Add
StrategyType::BucketArb(orMultiArb) variant + dispatcher branch - Config schema: new
crates/pm-bot/src/config/strategy/multi_arb.rs
Prerequisites (CRITICAL BLOCKERS)
EventViewtrait отсутствует — per F3 §8.4 gap. Strategy needs cross-market view of neg-risk event siblings (FSM tracks N child markets simultaneously). Must be added toReadCtxextension API per ADR-025.Decision::PostBucketArbBasket+BasketLegPlanremoved in F4.5 — restoration adds back through ADR-025 Decision contract evolution. Atomic multi-leg placement required.pm_sdk::onchain::ctf::convert_positions— shared blocker with #147 (merge-arb). Bucket-arb exit path also requires NegRiskAdapterconvertPositionsfor collateral recovery.- EventView consumer in scanner: hook routing must surface event-level updates (currently scanner is market-level only per F3 finding).
Restoration prereq commit chain:
- Implement
EventViewtrait + ReadCtx extension (NEW infra) - Implement
pm_sdk::onchain::ctf::convert_positions(shared with #147) - Add
Decision::PostBucketArbBasket+BasketLegPlantypes - Add executor handler for atomic basket placement (rollback on partial fail)
- Scanner event-level dispatch (route Event updates to hooks)
- Restoration of bucket-arb FSM itself
Out of scope
- Не модифицировать core engine за пределами ScannerHooks + EventView + Decision variants + executor.
- Не trash strategy isolation invariant.
Decomposition note
Per ADR-018 plan was Sprint 4 (~6 sprints total); restoration is approximately Sprint 4-scale work. Consider sub-decomposition into separate backlog items per FSM phase:
- 148a: EventView + ReadCtx extension infrastructure
- 148b: Decision::PostBucketArbBasket + executor (atomic multi-leg)
- 148c: FSM discovery + eligibility phases
- 148d: FSM entry + maintain phases
- 148e: FSM exit + convertPositions integration
Decomposition deferred — user decision pending.
Acceptance criteria
- ScannerHooks impl green per contract test pattern (event-level routing tested)
- EventView contract test
- Atomic basket placement test (all-or-nothing semantics)
- Convert-on-exit fork or RPC-mock test
- VERIFIED markers per
feedback_silent_feature_broken - New ADR (post-024) confirming restoration semantics + EventView design
Dependencies
- HARD blocker: EventView trait (NEW infra commit).
- HARD blocker: pm-sdk
convert_positions(shared with #147). - HARD blocker: Decision::PostBucketArbBasket variant.
- Independent of #145, #146, #149.
LOC estimate
- EventView trait + ReadCtx extension: ~400-600 LOC
- Decision variant + atomic executor: ~500-700 LOC
- Scanner event-level dispatch: ~200-400 LOC
- New strategy FSM: ~4000-5000 LOC (originally 7200; ReadCtx + EventView-slimmer)
- New strategy config: ~250 LOC
- Tests: ~1000-1500 LOC (FSM regression + atomic placement critical)
- Total: ~6500-8500 LOC (largest restoration)
References
- ADR-024, ADR-025, ADR-018 §multi-arb
- 619f7f0 (archive reference)
- .tmp/audit-reports/A-data-model.md (neg-risk 63.5% distribution)
- .tmp/audit-reports/F-extension-design.md §8.4 (EventView gap)
- docs/architecture/polymarket-data-model.md (Event ↔ Market relations)
- docs/strategies/bucket-arbitrage.md (legacy FSD)