Domain

The domain is pure and synchronous — value objects and transforms with no I/O. Every timestamp is nanoseconds UTC (int64). Exchange payloads are validated into these Pydantic models before anything is stored, so corrupt data never reaches Parquet.

Records at a glance

Model

Key fields

Notes

OHLCBar

ts, open, high, low, close, volume

quote_volume / trades may be null (see Exchanges).

Trade

ts, price, amount, side, tid

side ∈ {buy, sell}; tid is the dedup key.

OrderBookSnapshot

ts, bids, asks, is_snapshot

is_snapshot=False is an incremental delta.

Symbol & types

Symbol — canonical trading pair representation.

class Symbol(*, base, quote, market='spot')[source]

Canonical trading pair (base/quote, spot by default).

Examples

>>> Symbol(base='BTC', quote='USDT')
Symbol(base='BTC', quote='USDT', market='spot')
>>> str(Symbol(base='BTC', quote='USDT'))
'BTC/USDT'
>>> Symbol.parse('BTC/USDT')
Symbol(base='BTC', quote='USDT', market='spot')
>>> Symbol.parse('XBT/USD')
Symbol(base='BTC', quote='USD', market='spot')
classmethod parse(raw, market='spot')[source]

Parse a pair string with an optional separator.

Accepted formats: BTC/USDT, BTC-USDT, BTCUSDT (ambiguous, use explicit separator when possible).

Examples

>>> Symbol.parse('ETH-USD')
Symbol(base='ETH', quote='USD', market='spot')

DataType — closed enum for the three core data types.

class DataType(*values)[source]

Core data types supported by dccd v3.

The enum is intentionally closed. Extensions (funding, OI, liquidations) will require adding a new member here AND implementing the corresponding domain models and source protocols — never bypassed by string comparison.

Examples

>>> DataType.OHLC
<DataType.OHLC: 'ohlc'>
>>> DataType('trades')
<DataType.TRADES: 'trades'>

Records

Canonical data records — OHLCBar, Trade, OrderBookSnapshot.

class OHLCBar(*, ts, open, high, low, close, volume, quote_volume=None, trades=None)[source]

One OHLCV candle bar.

Attributes:
tsint

Open-time of the bar, nanoseconds UTC, aligned to span.

open, high, low, closefloat

Price values.

volumefloat

Base asset volume.

quote_volumefloat or None

Quote asset volume (not always available).

tradesint or None

Number of individual trades in the bar (not always available).

Examples

>>> bar = OHLCBar(ts=1_000_000_000_000_000_000, open=1.0, high=2.0, low=0.5, close=1.5, volume=10.0)
>>> bar.ts
1000000000000000000
class OrderBookLevel(*, price, amount, count=None)[source]

One price level in an order book.

Examples

>>> lvl = OrderBookLevel(price=50000.0, amount=1.5)
>>> lvl.price
50000.0
class OrderBookSnapshot(*, ts, bids, asks, is_snapshot=True)[source]

A complete (or delta) order book state at a point in time.

Attributes:
tsint

Snapshot timestamp, nanoseconds UTC.

bidslist[OrderBookLevel]

Bid levels, sorted descending by price.

askslist[OrderBookLevel]

Ask levels, sorted ascending by price.

is_snapshotbool

True = full state; False = incremental delta to apply locally.

Examples

>>> snap = OrderBookSnapshot(ts=1_000_000_000_000_000_000, bids=[], asks=[])
>>> snap.is_snapshot
True
class Trade(*, ts, price, amount, side=None, tid=None)[source]

Single trade (tick).

Attributes:
tsint

Trade timestamp, nanoseconds UTC.

pricefloat

Execution price.

amountfloat

Trade size (base asset).

sideLiteral[‘buy’, ‘sell’] or None

Taker side. None when not provided by the exchange.

tidstr or None

Trade ID as string (some exchanges use non-integer IDs).

Examples

>>> t = Trade(ts=1_000_000_000_000_000_000, price=50000.0, amount=0.1, side='buy')
>>> t.price
50000.0

Capabilities

A Capability is what an adapter declares it can do for a (data_type × transport × mode); the engine resolves against it and raises NoCapability early. See Architecture.

Capability — describes what a source can do.

class Capability(*, data_type, transport, mode, history='full', max_per_request=None, page_direction=None, spans=None, max_depth=None, auth_required=False)[source]

Declares one atomic capability of a source adapter.

Attributes:
data_typeDataType
transport‘rest’ or ‘ws’
mode‘historical’ or ‘live’
history‘full’ or ‘recent’

For historical REST: 'full' means the source covers the entire available exchange history; 'recent' means only the last N bars are accessible (e.g. Kraken OHLC = 720 recent bars).

max_per_requestint or None

Maximum items per API call (drives Paginator step size).

page_direction‘forward’, ‘backward’, or None

Pagination direction. None for single-shot / WS sources.

spanslist[int] or None

Supported OHLC spans in seconds. None = span list not constrained.

max_depthint or None

Maximum order book depth.

auth_requiredbool

Whether this capability requires authentication.

Examples

>>> from dccd.domain.types import DataType
>>> cap = Capability(data_type=DataType.OHLC, transport='rest', mode='historical', max_per_request=1000)
>>> cap.history
'full'

DatasetId and Provenance — dataset identity and lineage.

class DatasetId(*, exchange, symbol, data_type, span=None)[source]

Unique identifier for a dataset (exchange × symbol × type × span).

Examples

>>> from dccd.domain.symbol import Symbol
>>> from dccd.domain.types import DataType
>>> ds = DatasetId(exchange='binance', symbol=Symbol(base='BTC', quote='USDT'), data_type=DataType.OHLC, span=3600)
>>> ds.exchange
'binance'
pair_slug()[source]

Return filesystem-safe pair string (e.g. 'BTC-USDT').

class Provenance(*, source, derived_from=None)[source]

Dataset-level lineage metadata (stored in Parquet metadata, not per-row).

Attributes:
sourcestr

Origin description, e.g. "binance:rest" or "kraken:ws".

derived_fromDatasetId or None

Parent dataset when this dataset was derived (e.g. OHLC from trades).

Domain-level exceptions.

exception CoverageError(exchange, data_type, start, available_from=None)[source]

Raised when a source cannot cover the requested time window.

exception DccdError[source]

Base class for all dccd errors.

exception NoCapability(exchange, data_type, mode, reason='')[source]

Raised when a source cannot satisfy a requested operation/data type.

Transforms

Pure data transformations — no I/O, used by adapters and derivation.

aggregate_ohlc(trades, span)[source]

Aggregate trades into OHLC bars of span seconds.

Parameters:
tradeslist[Trade]

Input trades, sorted ascending by ts (nanoseconds UTC).

spanint

Bar duration in seconds.

Returns:
list[OHLCBar]

One bar per non-empty span window, ascending.

Examples

>>> from dccd.domain.records import Trade
>>> trades = [
...     Trade(ts=1_000_000_000_000_000_000, price=100.0, amount=1.0, side='buy'),
...     Trade(ts=1_000_000_060_000_000_000, price=110.0, amount=2.0, side='sell'),
... ]
>>> bars = aggregate_ohlc(trades, span=60)
>>> len(bars)
2