Files
sentiment-engine/prod/exec_unified/_constants.py
Codex 21419b03d0 exec(unified): UnifiedExecutor — initial-submit pipeline + S2 pain-fence
executor.py composes the built parts into one execute(request, snapshot): S-grade fence →
router.decide → placer.pre_submit → submit → register working. The initial-submit half that
complements DriveLoop's expiry half (analogue of pink_direct.py:1645-1700).

Composition rulings encoded + tested:
- S2/S3 pain-fence (§15.2): refused WHOLE, loudly, below T14 — never silently sliced.
- placer declines (spread gate) → cross ONLY if urgency crosses on expiry; ACQUIRE ABANDONS
  (a missed entry is free, §4-1). Both mutation-verified RED.
- TTL from urgency discipline: PROTECT 2s / ROTATE deadline_ms / ACQUIRE quote-lifetime.

contract.py: SGrade enum (S0-S3) + s_grade/parent_request_id fields. _constants: MAKER_QUOTE_TTL_S.

FIX (real bug, not just test): drive_loop._is_resolved EXIT was trade_id-based (a PINK
artifact — PINK reused the position's trade_id for exits). The agnostic layer never gets
the position id, so exit-done is now SIZE-based. Kept ENTER on clientOrderId match.

Full exec_unified suite: 94 green, mutation-litmus verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 02:30:30 +02:00

43 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Policy constants — from data, never vibes (spec §6 closing note).
Every constant cites its provenance. Where a number is not yet backed by an L8/L10
characterization row it is marked PROVISIONAL and must be calibrated before the smart
path arms with real capital — a provisional constant is a known-unknown, not a vibe.
Cadence is NEVER hardcoded here (no literal 1 s): the drive loop takes its clock
injected (spec §7, C1). These are policy magnitudes, not periods.
"""
from __future__ import annotations
from decimal import Decimal
# PROTECT: "maker at touch, one reprice, ≤2 s total, then cross" (spec §6).
PROTECT_REPRICE_LIMIT: int = 1
PROTECT_MAX_MS: int = 2_000
# HARVEST: "maker at target ± offset, chase ≤ N; give up when regression eats X%
# of unrealized → cross" (spec §6). N and X are PROVISIONAL — no characterization
# row fixes them yet (§17 open question: chase bounds from bookDepth replay).
HARVEST_MAX_CHASES: int = 3 # PROVISIONAL — calibrate vs L8 fill_sim
HARVEST_GIVEUP_REGRESSION_FRAC: Decimal = Decimal("0.25") # PROVISIONAL — 25% of unrealized
# ACQUIRE: "patient maker inside spread; abandon, never chase" (spec §6, §4-1:
# a missed entry is free, a chased entry is not). No chase budget by construction.
ACQUIRE_MAX_CHASES: int = 0
# Dead-man's stop default multiple of software SL distance (spec §10, §17 open
# question: 2× vs ATR-scaled). PROVISIONAL default.
PROTECTIVE_STOP_MULT_DEFAULT: Decimal = Decimal("2.0")
# Maker-quote lifetime for UNBOUNDED-TTL urgencies (HARVEST/ACQUIRE): how long a resting
# quote lives before the drive loop sweeps + re-evaluates it. Bounded quote lifetime +
# cancel/replace is the certified GTX discipline (spec §4-16). PROVISIONAL — calibrate vs
# L8 GTX fill latencies; measured in injected-clock seconds, never a hardcoded loop literal.
MAKER_QUOTE_TTL_S: float = 6.0
# Requote hot-window: after an OWN fill, refuse to re-quote for this long because the
# REST venue reconcile lags the WS fill by seconds — re-quoting inside it double-enters.
# Provenance: live double-entry, pink_direct.py:1055 / :1323 (2026-06-10). Measured in
# injected-clock seconds; the loop reads it, never a hardcoded literal in the branch.
REQUOTE_HOT_WINDOW_S: float = 5.0