Adapters translate. Core decides.
That rule is the main defense against rebuilding another options-first or venue-first system.
Adapter Categories
| Adapter type | Owns | Must not own |
|---|---|---|
| Market data adapter | raw venue payload parsing, schema normalization, event identity | feature computation or pattern matching |
| Instrument adapter | contract lookup, option strike selection, perp/spot/future expression | thesis generation |
| Expression adapter | turning PositionIntent into ExposureExpression | permission or portfolio policy |
| Execution adapter | order placement, venue reconciliation, fills | core lifecycle state definitions |
| Persistence adapter | serialization and storage | business rules |
| Presentation adapter | dashboard/API view models | core object shape |
Market Data Boundary
The current adapter boundary is:
class MarketDataAdapter(Protocol):
adapter_id: str
adapter_version: str
event_schema_version: str
def normalize_market_payload(
self,
payload: object,
*,
reference_time: ReferenceTime,
) -> AdapterEventBatch:
...
AdapterEventBatch validates that every event is an EventEnvelope and that every event source matches the adapter id.
Delta-Style Quote Fixture
The first adapter boundary test uses a fake Delta-style quote payload modeled on legacy quote rows from:
/Users/home/dev/atlantis/process/move_intelligence/delta_greeks_loader.py
The fixture includes symbol, close, volume, and oi, but only price enters the core price event. Volume and OI are future capability blocks, not accidental fields on MarketEvent.
batch = adapter.normalize_market_payload(raw_delta_quote, reference_time=reference_time)
snapshot = SnapshotBuilder(...).build(events=batch.events)
What The Adapter Does
The adapter may:
- parse raw venue timestamps
- choose an event id
- set
source_sequence - assign an instrument reference string
- emit a typed
EventEnvelope - record adapter version and schema version
What Core Still Does
SnapshotBuilder still owns:
- duplicate event filtering
- future-event cutoff
- stable event ordering
- invalid payload quality flags
- freshness policy evaluation
- capability availability
- source lineage retention
This separation is intentional. It keeps every adapter small and makes replay use the same decision logic as live.
Expression Boundary
After permission admits a signal intent, expression adapters turn PositionIntent into ExposureExpression.
The current expression boundary already includes:
ExposurePreferenceQuantityModelKindInstrumentCandidateEntryReferenceCostEstimateLiquiditySnapshotAdapterAttribution- adapter capability metadata
- exposure compatibility rules
- mode escalation guards
The core lifecycle can open and track an ExposureExpression, but it does not know how to place a broker order.
Adapter Quality Bar
Every new adapter should have tests proving:
- raw payloads do not leak into core
- adapter version and schema version are explicit
- event ids are deterministic
- source lineage is preserved
- missing or invalid payloads become explicit quality flags
- the core builder, not the adapter, owns reference-time filtering
- no broker order fields appear before the execution adapter layer