exec(unified): L2 foundation — contract §2 + whether-maker Router §6, pure, 26 tests
First code of the Unified Execution Layer (SPEC_UNIFIED_EXEC_LAYER_20260714.md). Pure
policy, stdlib+Decimal only, zero I/O, zero venue knowledge, zero importers elsewhere —
adopting it breaks nothing (freeze-safe; operator unparked the build 2026-07-14).
- contract.py: ExecutionRequest input surface (§2.1) + V-TYPES (Side, UrgencyClass,
ProtectiveSpec, ExecutionAdvice), frozen, validated-at-construction, illegal states
unrepresentable. 'an asset, a size, and a prayer'.
- router.py: decide(request) -> RoutingDecision — total pure map of the §6 urgency
ladder. Encodes A1 adjudication verdict in the architecture: Router=whether-maker,
SmartPlacer=where-in-book via the wants_placement/pre_submit seam. Complementary.
- _constants.py: policy magnitudes with provenance; PROVISIONAL ones flagged for
L8/L10 calibration (never vibes, never a hardcoded cadence).
- test_exec_unified.py: 26 behaviour + mutation-litmus tests. Verified RED under
CATASTROPHIC->MAKER and ACQUIRE cross_on_expiry->True mutations.
Not yet wired: PINK drive-loop port (§7), venue dialect (§11), telemetry (§12).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 23:00:42 +02:00
|
|
|
"""The whether-maker policy machine (spec §6 urgency ladder).
|
|
|
|
|
|
|
|
|
|
Adjudication verdict (spec §17-A1, ratified here in code): the Router and SmartPlacer
|
|
|
|
|
are **complementary, not competitors**. The Router decides *whether* to rest as maker
|
|
|
|
|
and how hard to work the order (reprice budget, TTL discipline, give-up rule). The
|
|
|
|
|
SmartPlacer decides *where in the book* the maker quote sits — it plugs into the
|
|
|
|
|
``pre_submit`` seam (``wants_placement`` below) and is free to return a replacement
|
|
|
|
|
plan. Neither subsumes the other; this module is the Router half and knows nothing
|
|
|
|
|
about order books, offsets, or venues.
|
|
|
|
|
|
|
|
|
|
PURE: no I/O, no clock, no venue, no ambient state. ``decide()`` is a total function of
|
|
|
|
|
the request alone. Everything time/price-dependent is expressed as a *rule the drive
|
|
|
|
|
loop enforces* (§7), not as a value read here — that is what keeps this layer
|
|
|
|
|
parity-invisible and venue-side-portable (C1).
|
|
|
|
|
|
|
|
|
|
Provenance: prod/docs/SPEC_UNIFIED_EXEC_LAYER_20260714.md §4, §6, §17-A1.
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from decimal import Decimal
|
|
|
|
|
from enum import Enum
|
|
|
|
|
|
|
|
|
|
from . import _constants as K
|
|
|
|
|
from .contract import ExecutionRequest, UrgencyClass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExecutionMethod(Enum):
|
|
|
|
|
MAKER = "MAKER" # rest post-only (GTX); the only certified fill-improvement path (§4-16)
|
|
|
|
|
TAKER = "TAKER" # cross the spread now (MARKET / marketable)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TtlDiscipline(Enum):
|
|
|
|
|
IMMEDIATE = "immediate" # act now, no resting (CATASTROPHIC)
|
|
|
|
|
BOUNDED_MS = "bounded_ms" # rest up to a fixed wall-clock bound, then cross (PROTECT)
|
|
|
|
|
DEADLINE = "deadline" # rest until caller's deadline_ms, then cross (ROTATE)
|
|
|
|
|
UNBOUNDED = "unbounded" # rest patiently; do NOT cross on expiry (ACQUIRE abandons)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class RoutingDecision:
|
|
|
|
|
"""What the Router decided — the plan the drive loop executes (§7).
|
|
|
|
|
|
|
|
|
|
Carries *rules*, not live values: ``max_ms`` is a bound the loop measures against
|
|
|
|
|
its injected clock; the Router itself never reads a clock.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
method: ExecutionMethod
|
|
|
|
|
max_reprices: int # chase budget; 0 = place-once (no chase)
|
|
|
|
|
ttl: TtlDiscipline
|
|
|
|
|
cross_on_expiry: bool # on TTL/reprice exhaustion: cross (True) or abandon (False)
|
|
|
|
|
wants_placement: bool # invite SmartPlacer to set the offset (pre_submit seam)
|
|
|
|
|
ignore_advice: bool # advice is inadmissible (CATASTROPHIC only, by law)
|
|
|
|
|
max_ms: int | None = None # wall-clock bound for BOUNDED_MS; else None
|
|
|
|
|
giveup_regression_frac: Decimal | None = None # HARVEST: cross if regression eats this of unrealized
|
|
|
|
|
rationale: str = ""
|
|
|
|
|
|
|
|
|
|
def __post_init__(self) -> None:
|
|
|
|
|
if self.max_reprices < 0:
|
|
|
|
|
raise ValueError("max_reprices cannot be negative")
|
|
|
|
|
if (self.ttl is TtlDiscipline.BOUNDED_MS) != (self.max_ms is not None):
|
|
|
|
|
raise ValueError("max_ms must be set iff ttl is BOUNDED_MS")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def decide(request: ExecutionRequest) -> RoutingDecision:
|
|
|
|
|
"""Map urgency → routing policy. Total, pure, deterministic (spec §6).
|
|
|
|
|
|
|
|
|
|
The five promises this enforces (spec §2.3): CATASTROPHIC is never delayed; WHAT is
|
|
|
|
|
never changed (this function reads urgency, never mutates side/size/asset); advice is
|
|
|
|
|
ignored for CATASTROPHIC by law.
|
|
|
|
|
"""
|
|
|
|
|
u = request.urgency
|
|
|
|
|
|
|
|
|
|
if u is UrgencyClass.CATASTROPHIC:
|
|
|
|
|
# Taker MARKET immediately. No cleverness. Ever. Advice ignored by law (§6).
|
|
|
|
|
return RoutingDecision(
|
|
|
|
|
method=ExecutionMethod.TAKER,
|
|
|
|
|
max_reprices=0,
|
|
|
|
|
ttl=TtlDiscipline.IMMEDIATE,
|
|
|
|
|
cross_on_expiry=True,
|
|
|
|
|
wants_placement=False,
|
|
|
|
|
ignore_advice=True,
|
|
|
|
|
rationale="CATASTROPHIC: cross now, no resting, advice inadmissible",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if u is UrgencyClass.PROTECT:
|
|
|
|
|
# Maker at touch, one reprice, ≤2 s total, then cross (§6).
|
|
|
|
|
return RoutingDecision(
|
|
|
|
|
method=ExecutionMethod.MAKER,
|
|
|
|
|
max_reprices=K.PROTECT_REPRICE_LIMIT,
|
|
|
|
|
ttl=TtlDiscipline.BOUNDED_MS,
|
|
|
|
|
max_ms=K.PROTECT_MAX_MS,
|
|
|
|
|
cross_on_expiry=True,
|
exec_unified: add placer.py (SmartPlacer pre_submit seam) + mutation-litmus tests
- MarketSnapshot: best_bid, best_ask, spread_bps, tick, step (Decimal, frozen, validated)
- PlacementPlan: limit_price (quantized to tick), post_only=True
- pre_submit: returns None for TAKER, spread gate failure, or quantize-cross; otherwise PlacementPlan
- Spread gate uses live spread_bps (fixes dead _spread_allows_maker)
- Quantize to tick BEFORE returning (ROUND_HALF_EVEN per §4-15)
- Cross-after-quantize guard rejects if tick quantization crosses book
- 33 mutation-litmus tests: spread-gate flip, TAKER gate, cross-after-quantize all go RED
- Router.PROTECT wants_placement=True (at touch)
- Pure stdlib+Decimal, zero I/O/venue
2026-07-14 23:14:07 +02:00
|
|
|
wants_placement=True, # at touch 2014 SmartPlacer places at best_bid/best_ask
|
exec(unified): L2 foundation — contract §2 + whether-maker Router §6, pure, 26 tests
First code of the Unified Execution Layer (SPEC_UNIFIED_EXEC_LAYER_20260714.md). Pure
policy, stdlib+Decimal only, zero I/O, zero venue knowledge, zero importers elsewhere —
adopting it breaks nothing (freeze-safe; operator unparked the build 2026-07-14).
- contract.py: ExecutionRequest input surface (§2.1) + V-TYPES (Side, UrgencyClass,
ProtectiveSpec, ExecutionAdvice), frozen, validated-at-construction, illegal states
unrepresentable. 'an asset, a size, and a prayer'.
- router.py: decide(request) -> RoutingDecision — total pure map of the §6 urgency
ladder. Encodes A1 adjudication verdict in the architecture: Router=whether-maker,
SmartPlacer=where-in-book via the wants_placement/pre_submit seam. Complementary.
- _constants.py: policy magnitudes with provenance; PROVISIONAL ones flagged for
L8/L10 calibration (never vibes, never a hardcoded cadence).
- test_exec_unified.py: 26 behaviour + mutation-litmus tests. Verified RED under
CATASTROPHIC->MAKER and ACQUIRE cross_on_expiry->True mutations.
Not yet wired: PINK drive-loop port (§7), venue dialect (§11), telemetry (§12).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 23:00:42 +02:00
|
|
|
ignore_advice=False,
|
|
|
|
|
rationale="PROTECT: maker@touch, 1 reprice, cross at 2s",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if u is UrgencyClass.HARVEST:
|
|
|
|
|
# Maker at target ± SmartPlacer offset; chase ≤ N; give up on regression → cross (§6).
|
|
|
|
|
return RoutingDecision(
|
|
|
|
|
method=ExecutionMethod.MAKER,
|
|
|
|
|
max_reprices=K.HARVEST_MAX_CHASES,
|
|
|
|
|
ttl=TtlDiscipline.UNBOUNDED, # bounded by chases + regression, not wall-clock
|
|
|
|
|
cross_on_expiry=True, # give-up crosses (harvest still wants the fill)
|
|
|
|
|
wants_placement=True,
|
|
|
|
|
ignore_advice=False,
|
|
|
|
|
giveup_regression_frac=K.HARVEST_GIVEUP_REGRESSION_FRAC,
|
|
|
|
|
rationale="HARVEST: maker@target±offset, chase<=N, cross on regression give-up",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if u is UrgencyClass.ROTATE:
|
|
|
|
|
# Patient maker; TTL from caller's deadline_ms; cross at TTL (§6).
|
|
|
|
|
return RoutingDecision(
|
|
|
|
|
method=ExecutionMethod.MAKER,
|
|
|
|
|
max_reprices=K.HARVEST_MAX_CHASES, # patient chasing within the deadline
|
|
|
|
|
ttl=TtlDiscipline.DEADLINE,
|
|
|
|
|
cross_on_expiry=True,
|
|
|
|
|
wants_placement=True,
|
|
|
|
|
ignore_advice=False,
|
|
|
|
|
rationale="ROTATE: patient maker, cross at caller deadline",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if u is UrgencyClass.ACQUIRE:
|
|
|
|
|
# Patient maker inside spread; abandon, never chase (§4-1: a missed entry is free).
|
|
|
|
|
return RoutingDecision(
|
|
|
|
|
method=ExecutionMethod.MAKER,
|
|
|
|
|
max_reprices=K.ACQUIRE_MAX_CHASES, # == 0: no chase
|
|
|
|
|
ttl=TtlDiscipline.UNBOUNDED,
|
|
|
|
|
cross_on_expiry=False, # ABANDON on expiry — do NOT cross
|
|
|
|
|
wants_placement=True,
|
|
|
|
|
ignore_advice=False,
|
|
|
|
|
rationale="ACQUIRE: patient maker inside spread, abandon (never chase, never cross)",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
raise ValueError(f"unhandled urgency {u!r}") # unreachable given the enum is closed
|