docs(spec): SMART-EXEC — non-naive MM/trade executor at the venue-adapter seam
Urgency ladder mapped to A-G doctrine, Router+SmartPlacer adjudication first, inherits indeterminate triage, venue-side catastrophic backstop, parity-invisible. Build is POST_FINISH-sequenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
125
prod/docs/SPEC_UV_SMART_EXEC_MM.md
Normal file
125
prod/docs/SPEC_UV_SMART_EXEC_MM.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# SPEC — UV Non-Naive Execution Layer ("SMART-EXEC")
|
||||||
|
**Status:** SPEC ONLY — build is POST_FINISH-SEQUENCED (first task upon parity cert).
|
||||||
|
**Author:** Fable, 2026-07-13. **Owner seam:** DITAv2 venue-adapter boundary.
|
||||||
|
|
||||||
|
## 0. One paragraph
|
||||||
|
Everything above the venue adapter decides WHAT (side, size, asset, exit trigger).
|
||||||
|
SMART-EXEC decides HOW: maker-vs-taker, where-in-book, when to chase, when to give
|
||||||
|
up and cross. It slots BELOW the DITAv2 kernel at the venue-adapter seam, so the
|
||||||
|
kernel, FSM, journals, and the parity ledger see identical semantics — SMART-EXEC
|
||||||
|
is **parity-invisible by construction**. Economics: taker RT ~0.10% → maker-both
|
||||||
|
~0.04%; day-1 smoke flips breakeven → +0.9% equal-weight. Research: 90%+ of orders
|
||||||
|
fill as maker when price "moves to us".
|
||||||
|
|
||||||
|
## 1. Assets unified (adjudication = sub-task 1, DO FIRST)
|
||||||
|
| asset | what it is | keep |
|
||||||
|
|---|---|---|
|
||||||
|
| PINK `ExecutionRouter` | maker/taker POLICY + hooks; 265 tests; `maker_both` ran production since 2026-06-11 | the policy state machine + test corpus |
|
||||||
|
| BLUE `alpha_engine/execution/` SmartPlacer | OB-aware PLACEMENT: `fill_simulator` (30s bookDepth), `signal_confidence_adapter` (conviction→placement), `ob_reader`, `smartplacer_constants` | the where-in-book model |
|
||||||
|
| `BingX_FILL_CHARACTERIZATION_AND_ADVANTAGES.md` | measured venue friction, incl. VST conditional-order sampling (`prod/bingx/characterization.py`) | ground truth to adjudicate BOTH against |
|
||||||
|
Likely complementary (Router = whether-maker; SmartPlacer = where-maker). The
|
||||||
|
adjudication verdict decides: Router ∪ SmartPlacer ∪ union — nothing built before
|
||||||
|
that memo exists.
|
||||||
|
|
||||||
|
## 2. Contract
|
||||||
|
**Input** (from kernel via venue adapter): `KernelIntent` + `guideline_price`
|
||||||
|
(decision layer's reference — e.g. tick price that triggered the exit) +
|
||||||
|
`urgency_class` (below). Decision layers NEVER place orders; they hand a
|
||||||
|
guideline and an urgency. (Resolves the ADVSL-stale-price concern: scan-clock
|
||||||
|
exits pass their price as guideline; SMART-EXEC executes against live book.)
|
||||||
|
**Output**: same `VenueEvent`/receipt stream the naive adapter emits today —
|
||||||
|
plus friction telemetry (§8). The kernel cannot tell SMART-EXEC from naive
|
||||||
|
MARKET; only the fills get cheaper.
|
||||||
|
|
||||||
|
## 3. Urgency ladder (maps to exec-priority doctrine A–G)
|
||||||
|
| class | source | policy |
|
||||||
|
|---|---|---|
|
||||||
|
| `CATASTROPHIC` | SL / kill switch (C-tier) | taker MARKET immediately. No cleverness. Ever. |
|
||||||
|
| `PROTECT` | TP_FLOOR give-back, ADVSL full-retract (C/D) | maker at touch, **one** reprice, ≤2s total, then cross |
|
||||||
|
| `HARVEST` | FIXED_TP (D) | maker-first at target±placement offset; chase ≤N repricings; give-up trigger: if regression eats X% of unrealized, cross |
|
||||||
|
| `ROTATE` | MAX_HOLD, admin exits (E) | patient maker; TTL minutes; cross at TTL |
|
||||||
|
| `ACQUIRE` | ENTER (F) | patient maker inside spread per SmartPlacer; abandon (don't chase) if price runs — a missed entry is free, a chased entry is not |
|
||||||
|
Urgency is assigned by the CALLER (it knows why), never inferred by SMART-EXEC.
|
||||||
|
|
||||||
|
## 4. Order-management loop
|
||||||
|
- Runs on the steel clock (1s now; L2/L3 ladder later — design for cadence
|
||||||
|
injection, no hardcoded 1s).
|
||||||
|
- Per working order: state = {placed_px, queue_age, book_state, chases_left, ttl}.
|
||||||
|
- Reprice rule: only toward urgency (never widen an exit). Max chases per class
|
||||||
|
(constants from characterization data, not vibes).
|
||||||
|
- Every transition journaled (§8). Single-writer discipline: one owned dispatch
|
||||||
|
lane (ASEx pattern, as `uv-exit-dispatch` today); the price/tick lane never
|
||||||
|
blocks on wire time.
|
||||||
|
|
||||||
|
## 5. Execution truth (inherits bdc54fb doctrine wholesale)
|
||||||
|
- Failure triage on every wire op: NOT_ATTEMPTED / REFUSED → rollback sound;
|
||||||
|
INDETERMINATE → point-lookup own clientOrderID (bounded, read-only, NOT a
|
||||||
|
reconcile); unresolved → UNKNOWN, no synthetic REJECT, E-feed FILL settles.
|
||||||
|
- Cancel is a wire op too: cancel-INDETERMINATE means the order MAY still be
|
||||||
|
live → do not re-place until truth established (double-fill guard).
|
||||||
|
- Idempotency: every order carries our clientOrderID; replace = cancel-confirm
|
||||||
|
→ place, never blind amend.
|
||||||
|
- Partial fills are normal in maker land: FSM already speaks PARTIAL_FILL;
|
||||||
|
SMART-EXEC must never hold a partial hostage to policy — remainder follows
|
||||||
|
the same urgency ladder, fills stream up immediately.
|
||||||
|
|
||||||
|
## 6. Venue-side catastrophic backstop (rides along, parity-invisible)
|
||||||
|
On ENTER, attach `stopLoss` (STOP_MARKET, workingType=MARK_PRICE) at ~2× the
|
||||||
|
software SL on the SAME placeOrder request. It acts only if the client is dead
|
||||||
|
or blind (HZ silent-death history) — hence parity-invisible: it fires only when
|
||||||
|
the system parity measures has already failed. **VST-verify before live:
|
||||||
|
attached stop auto-cancels when position closes** (orphan-order risk = proto-
|
||||||
|
PINK hell). Serializer support for attach params must be added to prod/bingx
|
||||||
|
(execution.py has standalone conditionals only).
|
||||||
|
|
||||||
|
## 7. What SMART-EXEC is NOT (negative constraints — encode in tests)
|
||||||
|
- NOT a reconciler. It never scans open orders it didn't place. Never grows
|
||||||
|
the point-lookup into one.
|
||||||
|
- NOT a decision layer. It never overrides side/size/asset, never vetoes an
|
||||||
|
exit, never delays CATASTROPHIC by even one loop tick.
|
||||||
|
- NOT multi-venue (yet). BingX only; the seam (venue adapter) is where
|
||||||
|
multi-venue lands later, not inside policy.
|
||||||
|
- NOT dependent on IMPETUS. Guideline price comes from caller; live book from
|
||||||
|
ob_reader/REST today. IMPETUS (wire-atomic shm tick) plugs into the SAME
|
||||||
|
price seam later and only makes it faster.
|
||||||
|
- Telemetry NEVER on the exec path (b46ebd2 lesson): lossless side-lane spool,
|
||||||
|
0-drop, own thread.
|
||||||
|
|
||||||
|
## 8. Observability (before-and-after or it didn't happen)
|
||||||
|
Per order: intended px (guideline) / placed px / fill px / maker-vs-taker flag /
|
||||||
|
queue_age / chases / fees. Aggregates: effective friction bps per urgency class
|
||||||
|
vs the naive-MARKET baseline measured 2026-07-10 (venue-friction-half audit).
|
||||||
|
Table: `dolphin_uv.exec_smart_journal` (DDL ships WITH the code + applier
|
||||||
|
verify-set entry — lesson of 2026-07-13: tables that don't exist journal
|
||||||
|
nothing).
|
||||||
|
|
||||||
|
## 9. Testing doctrine (non-negotiable subset)
|
||||||
|
- Mutation litmus on: urgency mapping (flip CATASTROPHIC→maker must go RED),
|
||||||
|
give-up triggers, chase bounds, indeterminate triage, backstop attach.
|
||||||
|
- fill_simulator replay: policy vs recorded 30s bookDepth — deterministic,
|
||||||
|
seed-pinned.
|
||||||
|
- VST live E2E per class (Router corpus pattern — it has 265 to crib from).
|
||||||
|
- Poison: partial fill mid-chase, cancel-INDETERMINATE, venue reject storms,
|
||||||
|
clock stall, spread inversion, zero-liquidity book.
|
||||||
|
- No green-by-pollution; env-gate live tests.
|
||||||
|
|
||||||
|
## 10. Rollout ladder
|
||||||
|
shadow (log-only intents) → `maker_entry_only` → `maker_both` → live capital.
|
||||||
|
Env kill switch `UV_SMART_EXEC=0` reverts to naive MARKET instantly (deployment
|
||||||
|
knob, not code path removal). Each rung: friction delta vs baseline published
|
||||||
|
before the next rung.
|
||||||
|
|
||||||
|
## 11. NFRs (standing hardening doctrine applies)
|
||||||
|
Graal-ready, ASEx single-writer, jemalloc, no hardcoded paths/ports, V-TYPES
|
||||||
|
at boundaries, self-test-to-death on boot, DeadNode reaper hygiene, cadence
|
||||||
|
injectable (no literal 1s), constants in one `_constants.py` with provenance
|
||||||
|
comments citing characterization data.
|
||||||
|
|
||||||
|
## 12. Open questions (answer during adjudication, not during build)
|
||||||
|
1. Router's maker_both stats on PINK vs BingX *perp* book microstructure now.
|
||||||
|
2. SmartPlacer signal_confidence_adapter: is Alpha-conviction available in UV's
|
||||||
|
PRIME path, or does UV need a conviction proxy (vel_div magnitude)?
|
||||||
|
3. Attached-TP alongside attached-SL: worth it, or software TP_FLOOR only?
|
||||||
|
(TP_FLOOR ratchet is inexpressible venue-side — likely software-only.)
|
||||||
|
4. Does BingX queue-priority survive price-unchanged replaces? (characterize)
|
||||||
|
5. Backstop width: 2× software SL, or ATR-scaled?
|
||||||
Reference in New Issue
Block a user