Expand description
Writing the event stream to a file and playing it back.
A research program needs the same events twice: once live, to record, and later from a file, as
many times as it takes to debug a strategy. This module does the file part with no dependencies
beyond JSON. The format is one JSON line per [Envelope], after a header line that names the
format and the schema of the envelopes:
{"brokapi_log":1,"envelope_schema":1}
{"schema":1,"source":"bcs-md","sub":1,"ts":{...},"payload":{"OrderBook":{...}}}| Need | Item |
|---|---|
| Append envelopes to a file | EnvelopeWriter |
| Read them back in order | EnvelopeReader |
| Feed them to a channel, as fast as possible or at the recorded pace | replay, ReplaySpeed |
What the file keeps and what it does not:
- Prices, quantities and money are written as decimal strings, so they come back exactly.
- The monotonic clock
Timestamps::rx_monois not stored. A replayed envelope carries the time of reading in it. Userx_tsandbroker_tsto order and measure replayed data, neverrx_mono. - A line that cannot be read stops the read with an error that names the line. A reader never skips a bad line silently.
- An envelope with a
schemanewer than this build understands is refused (LogError::Schema), as the rules of [ENVELOPE_SCHEMA] ask.
This is a log of a stream, not a catalog: there is no index by instrument or time, so filter while you read. Compare NautilusTrader, whose data catalog keeps typed data in Parquet files and queries it by instrument and time: a catalog is the right tool for years of data, this log is the smallest thing that records a live run and plays it back.
§Examples
use std::sync::Arc;
use std::time::Instant;
use brokapi_core::{Envelope, Event, Timestamps, UnixNanos};
use brokapi_runtime::record::{EnvelopeReader, EnvelopeWriter};
let ts = Timestamps::new(UnixNanos::from_nanos(7), Instant::now());
let env = Envelope::new(Arc::from("bcs-md"), ts, Event::Balances(vec![]));
let mut writer = EnvelopeWriter::new(Vec::new())?;
writer.write(&env)?;
let bytes = writer.finish()?;
let back: Vec<Envelope> = EnvelopeReader::new(bytes.as_slice())?.collect::<Result<_, _>>()?;
assert_eq!(back, vec![env]);Structs§
- Envelope
Reader - Reads envelopes back from any
BufRead, in the order they were written. - Envelope
Writer - Appends envelopes to any
Write: a file, a buffer, a compressor. - Replay
Report - What a finished
replaydid.
Enums§
- LogError
- Why a log could not be written or read.
- Replay
Speed - How fast
replayplays.
Constants§
- LOG_
FORMAT - The version of the file format. It is in the header line of every file.
Functions§
- replay
- Sends envelopes into a channel, in order, like a connector would.