Skip to content

Capture record

Every live capture, and every segment of a long one, writes a meta.json beside its files. Most of its fields are counters. A few say how to read the data back: the source that made the capture and what it declares about its feed, and the instrument's tick size and lot size. This module writes and reads those fields. It is outside ob_analytics.live, so code that only replays files does not need the live-capture extras.

Pipeline.run reads the record of the capture it is given, and uses the recorded tick size and lot size when your config does not set them. So Pipeline.from_source("depth_csv").run(capture) and ob-analytics process capture --source depth_csv give the same result. See Capture live data.

read_record

read_record(path: Any) -> CaptureRecord

Read the record of the capture at path.

Parameters:

Name Type Description Default
path Any

A capture folder, a segment's folder, a file inside one, or the output of ob-analytics process. Anything that is not a path (a frame, say) has no record.

required

Returns:

Type Description
CaptureRecord

What the capture recorded. Empty when there is no meta.json, or it cannot be read. A declaration with a value this version does not know is left out with a warning.

CaptureRecord dataclass

CaptureRecord(
    source: str | None = None,
    feed_type: FeedType | None = None,
    trade_attribution: TradeAttribution | None = None,
    sequence_kind: SequenceKind | None = None,
    clocks: Clocks | None = None,
    sequence_restarts: int = 0,
    tick_size: float | None = None,
    lot_size: float | None = None,
)

What a capture recorded about how to read its data.

Every field is None (0 for sequence_restarts) when the capture did not record it: input that is not a capture, a capture written before captures recorded the field, or a venue that does not give the value.

Attributes:

Name Type Description
source str or None

The name of the source that made the capture. It can differ from the source that reads the files: a cryptofeed L3 capture is read as bitstamp.

feed_type FeedType or None

What that source declares about crossing (see :class:~ob_analytics.protocols.FeedType).

trade_attribution TradeAttribution or None

Which orders of a trade that source's feed names (see :class:~ob_analytics.protocols.TradeAttribution).

sequence_kind SequenceKind or None

What the venue sequence promises (see :class:~ob_analytics.protocols.SequenceKind). None when the source declares none; then use what the source declares now (:func:~ob_analytics.protocols.sequence_kind_of).

clocks Clocks or None

Which clocks the capture's rows carry (see :class:~ob_analytics.protocols.Clocks). A live source learns this from the venue's books, so it is written when the capture closes.

sequence_restarts int

How many times the venue's sequence started again. A source that finds a lost message itself starts again from a new opening book, and on some venues the sequence starts again too. These steps back are not faults (see :func:~ob_analytics.analytics.data_quality_summary).

tick_size float or None

The instrument's price step, in the quote currency.

lot_size float or None

The instrument's size step, in the base asset.

instrument

instrument() -> dict[str, Any]

Return the :class:~ob_analytics.config.PipelineConfig fields recorded.

The recorded tick size comes with the price_decimals that shows one tick, and the lot size with its volume_decimals. A step the capture did not record is left out.

read_instrument

read_instrument(path: Any) -> dict[str, Any]

Return the :class:~ob_analytics.config.PipelineConfig fields a capture recorded.

The same as read_record(path).instrument(), without reading the source's declarations, so a declaration this version does not know is not warned about. This is what :meth:~ob_analytics.pipeline.Pipeline.run reads.

Parameters:

Name Type Description Default
path Any

As for :func:read_record.

required

Returns:

Type Description
dict of str to Any

The recorded tick_size and lot_size, each with its display precision; empty when the capture records neither.

write_record

write_record(folder: Path, fields: dict[str, Any]) -> None

Write fields as the record of the capture in folder.

The file is replaced in one step, so a reader never sees half of it, and any API key the capture holds is removed from the text first. A value JSON cannot hold is written as its text.

source_declarations

source_declarations(source: Any) -> dict[str, Any]

Return what a live source declares about its feed, as record fields.

source names the source; feed_type and trade_attribution are what it declares (see :class:~ob_analytics.protocols.FeedType and :class:~ob_analytics.protocols.TradeAttribution). sequence_kind is written only by a source that declares one. clocks (see :class:~ob_analytics.protocols.Clocks) is read when the capture closes, since a live source learns it from the venue's books.

It runs while a capture is closing, so a declaration that cannot be read (a plug-in's value outside the enum, say) is logged and never stops the files being finished: an unreadable feed_type is recorded as unknown, and an unreadable trade_attribution is left out, so audit falls back to --source rather than to a guess.

read_fields

read_fields(path: Any) -> dict[str, Any] | None

Return every field of the record at path, as written.

None when there is no record, or it is not a JSON object. Any other error reading the file is raised, so a writer never replaces a record it could not read.

record_path

record_path(path: Any) -> Path

Return where the record of the capture at path is.

path is a capture folder, a segment's folder, a file inside one, or the output of ob-analytics process, which keeps the capture's record.