# Phase 0b — Venue Consolidation to Bybit + IBKR (Design)

> Sub-project of Phase 0 (uniform two-venue foundation). Follows 0a (unified DB-backed backtest→ref
> architecture, branch `feat/unified-db-backtest-architecture`, pushed/unmerged). **0b depends on 0a** —
> it modifies 0a's xsfunding ref wiring (see §7). Start 0b from the 0a branch or after 0a merges.

## Goal

Make **Bybit** (crypto) and **IBKR** (tradfi) the *only* venues in the system — for both **execution and
data**. Remove the dead Binance/Alpaca **execution** surface, migrate the crypto edges that *actually work
on Bybit* onto Bybit data, retire the ones that don't, and remove Binance **entirely** (execution + data).

## Governing principle (operator)

> "We can't *trade* Binance — but that doesn't mean we can't run strats on Bybit. Keep the strats that
> **actually work on Bybit**; understand, per strat, whether the edge survives on Bybit."

A crypto strat survives 0b only if **(a)** Bybit lists the instruments it needs **and** **(b)** the edge
holds on Bybit data. This was checked empirically per edge (§3).

## Current state (verified this session)

- **Two data worlds coexist today:** the Binance-fed `features` warehouse (default `warehouse_table`) feeds
  the standalone crypto *forward tracks* (`xsfunding_nav`, `crypto_tstrend_nav`, `unlock_nav`,
  `stablecoin_rotation_nav`); the Bybit-fed `bybit_features` feeds the **deploy book** `bybit_4edge`
  (sleeves tstrend/unlock/xsfunding/positioning) + the `positioning` standalone track.
- **The crypto edges are duplicated:** xsfunding/tstrend/unlock exist as *both* a Binance-data standalone
  track *and* a Bybit-data sleeve in `bybit_4edge`. The Binance standalone tracks are research-era artifacts;
  the memory finding is that the **Binance broad book is a mirage; the Bybit liquid book is the real edge**.
- **Only one live executor:** `fxhnt-ibkr-rebalancer` CronJob (active). `fxhnt-alpaca-rebalancer`,
  `fxhnt-bybit-rebalancer`, and the old `multistrat-rebalancer` are suspended.

## §3 — Per-edge Bybit-survival verdicts (measured, not assumed)

Leave-one-out marginal contribution to the equal-weight `bybit_4edge` book (2023–2026, cost-netted;
book Sharpe +3.47, maxDD −8.9%) + crash behavior:

| Edge | Standalone Sharpe / maxDD | Marginal to book (Sharpe / maxDD) | Worst-20-day behavior | **Verdict** |
|---|---|---|---|---|
| **xsfunding** | +3.55 / −3.4% | +0.28 / −3.3pp | **+0.20%/day (hedges)** | **Migrate → Bybit track** |
| **unlock** | +1.04 / −23.8% | **+0.34 / −3.7pp** | −0.71%/day | **Migrate → Bybit track** (uncorrelated, protective) |
| positioning | +2.79 / −14.3% | +1.22 / −3.8pp | −0.95%/day | Keep (already Bybit) |
| **crypto_tstrend** | +0.74 / −54.3% | **−0.21 / +1.2pp** | **−6.46%/day (amplifies)** | **Retire standalone track** (drag; not a hedge here) |
| **stablecoin_rotation** | n/a | not in book | n/a | **Retire** (does not exist/work on Bybit — §3a) |

### §3a — Stablecoin does not port to Bybit
The strat trades peg-reversion on **FDUSD/USDT, TUSD/USDT, USDP/USDT** (Binance spot). Bybit listing check:
FDUSD **NOT LISTED**, USDP **NOT LISTED**, TUSD listed. Bybit's *entire* stablecoin/USDT spot set is
{TUSD, PYUSD, USDC, USDE} — a poor peg-reversion basis (USDC/USDT deviations are tiny; USDE is a structural
synthetic dollar), and the primary edge driver (FDUSD's Binance zero-fee microstructure) is Binance-specific.
→ **Retire.** A Bybit-native stablecoin edge would be a *fresh research probe with its own gate*, explicitly
out of 0b scope.

## Architecture — what changes (grouped)

### A. Migrate xsfunding + unlock → standalone Bybit forward tracks
**Template = `positioning`.** `build_positioning_forward_nav(repo, store, sleeve='positioning', …)`
(assets.py:177) builds a single-sleeve Bybit forward track from `sleeve_returns_from_store` /
`naive_eqwt_daily_returns` on `bybit_features`; its reconciliation ref comes from the Bybit book persist
(`bybit_4edge_backtest_summary(sleeves=['positioning'])`, one of `_BYBIT_BOOK_SIDS`).

- Generalize to `build_bybit_sleeve_forward_nav(repo, store, sleeve, …)` (or add xsfunding/unlock the same
  way positioning is built). Repoint `xsfunding_nav` and `unlock_nav` assets to construct the **Bybit**
  single-sleeve track over `TimescaleFeatureStore(dsn, table='bybit_features')` — dropping
  `XsFundingForward(BinanceXsFundingLive())` and the Binance `features` unlock construction.
- Registry `xsfunding` / `unlock`: `venue` → `bybit-perp`; data basis → Bybit; `backtest.kind` moves to the
  Bybit-book report basis (like `positioning`) — xsfunding **from `sleeve`** (0a), unlock **from
  `recompute-replay`** (0a) — and both sids join `_BYBIT_BOOK_SIDS` in `_persist_bybit_book` so their refs
  are written from the Bybit sleeve series (§7).
- Forward re-inception: the Bybit track is a NEW basis, so xsfunding/unlock re-inception on cutover
  (deterministic-forward-state; a re-inception, not silent). Document the `migrate-forward-anchors` step.

### B. Retire crypto_tstrend (standalone) + stablecoin_rotation
- Delete `crypto_tstrend_nav` (assets.py:669) and `stablecoin_rotation_nav` (assets.py:691) assets +
  their registry entries. Delete `stablecoin_strategy.py` / `stablecoin_runner.py` (no other consumer).
- **crypto_tstrend stays a sleeve in the `bybit_4edge` deploy book** — 0b retires only the redundant
  *standalone Binance track*, not the book sleeve. (The −0.21 marginal-drag finding is a **separate
  portfolio-composition question**, flagged in §Out-of-scope, NOT decided by 0b.)

### C. Remove the dead Alpaca execution surface (keep the Broker port, IBKR sole impl)
- Delete `src/fxhnt/adapters/broker/alpaca.py` (`AlpacaBroker`), `AlpacaSettings` (config.py:45) + the
  `alpaca` field (config.py:185).
- Remove the `--broker` option and its `alpaca` branches from `execute-multistrat` (cli.py:257–325) and any
  peer command (cli.py:206–223) — **IBKR becomes implicit** (the sole impl behind the retained Broker port).
- Delete manifests `infra/k8s/jobs/fxhnt-alpaca-rebalancer.yaml`,
  `infra/k8s/secrets/alpaca-credentials.yaml`; delete the in-cluster `multistrat-rebalancer` CronJob
  (superseded by `fxhnt-ibkr-rebalancer`; locate its manifest) and the `alpaca-credentials` cluster secret.
- **Keep the Broker port/interface** with `IBKRBroker` as the only implementation (clean seam; a future
  venue plugs in without reintroducing an abstraction).

### D. Remove the Binance execution surface
- Delete `src/fxhnt/adapters/exchange/binance_ccxt.py`, the `crypto-rebalance` / `crypto-positions` /
  `crypto-flatten` CLI commands (cli.py:4746/4768/4776), and the Binance coupling in
  `crypto_execution.py`. Remove the execution-only parts of `BinanceSettings`.

### E. Remove Binance DATA entirely (after A + B land)
- Delete the Binance data adapters: `binance_funding_history.py`, `binance_spot_history.py`,
  `binance_xsfunding_live.py`.
- Delete/repoint the Binance ingest assets `crypto_bars` / `crypto_funding` / `crypto_spot` (assets.py:263/
  322/345) — with A/B done, nothing live reads the `features` table, so the Binance ingest chain and the
  `features` table are retired. Verify no residual reader (e.g. `bybit_edges_eval.py`'s Binance imports —
  remove or repoint) before dropping the table.

### F. Remove the vestigial registry `state_file` field
The `state_file` field on every registry entry (the old JSON-tracker-on-PVC path) is vestigial since the
single-DB-SSOT forward engine — `_run_paper_tracker` documents it as "retained ONLY for the one-time
migration seed, unused at steady state." Remove the `state_file` field from all registry entries and drop
the parameter from `_run_paper_tracker` / any `entry["state_file"]` reads. **Guard:** the JSON-based
`ForwardTracker` (+ its `.bak` crash-recovery) is still used by the standalone `fxhnt forward-track` CLI —
that command supplies its OWN path and must keep working; only the *registry field* + the Dagster-asset
plumbing of it are removed (verify the CLI path is independent before deleting).

## §7 — 0a interaction (must-carry)
0a Task 6 wired the `xsfunding` reconciliation ref via `get_feature_store(s)` (= `features` = **Binance**),
deliberately, to match the *then*-live `XsFundingForward(BinanceXsFundingLive())`. 0b **moves xsfunding onto
Bybit**, so that wiring must flip: xsfunding's (and unlock's) ref now comes from the **Bybit** sleeve series
(`bybit_features`), via `_persist_bybit_book` / the `backtest-refs` CronJob, exactly like `positioning`.
Net: after 0b, `_persist_track_backtest_ref`'s sleeve-kind branch no longer serves any Binance sid (the
only inline sleeve sid, xsfunding, becomes a Bybit report-book sid). The 0a invariant test still must pass.

## Out of scope (explicit)
- **Re-composing the `bybit_4edge` deploy book** (e.g. dropping tstrend from the book on its −0.21 marginal /
  crash-amplifier finding) — a real-capital portfolio decision, separate from venue cleanup. Flagged for a
  later, deliberate decision with the crash-protection question (does trend protect out-of-sample?) resolved.
- **A Bybit-native stablecoin edge** — fresh research + its own gate, not a migration.
- Alpaca/Bybit rebalancer *code* that is venue-generic and reused by IBKR stays; only Alpaca/Binance-specific
  execution is removed.

## Risks & verification
- **Real-capital gate safety:** xsfunding/unlock re-inception on cutover must be a *visible* re-inception
  (deterministic-forward-state), never a silent reset; their new Bybit refs must exist before the gate can
  PASS (0a invariant + the `migrate-forward-anchors` post-deploy step). Errs false-WAIT, never false-FUND.
- **No orphaned reads:** removing the `features` table must follow a repo-wide check that no live path reads
  it (the §E verify). A guard test (like 0a's `test_no_live_duckdb_files`) asserting no live Binance-data
  consumer remains.
- **Cockpit:** verify locally (real browser) that the migrated xsfunding/unlock Bybit tracks render and the
  retired tracks (tstrend-standalone/stablecoin) disappear cleanly — no 500s, no dangling nav rows.
- **Full suite green** + whole-branch review before merge.

## Success criteria
1. Crypto is 100% Bybit (data + execution): xsfunding/unlock on Bybit tracks; tstrend-standalone + stablecoin
   retired; `bybit_4edge` book unchanged.
2. No Binance code remains (execution *or* data adapters/ingests); `features` table retired; a guard test
   proves it.
3. No Alpaca code/manifests/secret remain; IBKR is the sole equity executor behind the retained Broker port.
4. The 0a reconciliation invariant still holds; xsfunding/unlock reconcile against **Bybit** refs.
5. Cockpit verified locally; full suite green; whole-branch review clean.
