Expand description
Bulk export jobs against the vault: submit, poll, download.
The vault serves candles over REST (historical), but the raw tick tape
is reachable only here — there is no streaming or REST path to it. Exports are asynchronous:
submit a job, poll it to ready, then download the artifact.
§⚠️ This is a different API surface from the candles endpoint
Measured differences that a client written against the candles path gets wrong:
- Submit answers
202 Accepted, not200. A== 200check never polls. - The job-id field is renamed between responses: the submit body says
job_id, the status body saysid. HenceLseExportJobandLseExportJobStatusare separate types. - Allowance exhaustion is a
429with noRetry-After, mapped here toLseError::QuotaExceededrather thanLseError::RateLimited— an exhausted export allowance is a different condition from a per-minute rate limit, and only the former carries aQuotaStatus.
§⚠️ A rejected submit still costs you an export
The allowance is 5 exports per hour, and the counter increments on attempt: a 400 for a
misspelled dataset consumes 20% of the hour’s budget just as a successful job does. (Requests
rejected at the CDN edge do not count.) This is why LseExportRequest::new validates
everything it can before a request is ever sent — pre-flight validation here is an economic
requirement, not defensive style.
§⚠️ symbol: "all" does not mean “every symbol”, and every artifact is single-symbol
It is a literal that matches nothing. Measured as a controlled pair on one dataset, timeframe
and range: symbol: "all" returned 202 → ready → a valid Parquet file with the full
schema and zero rows, while the same request naming a real symbol returned rows. There is no
error and no warning, and it costs an export. The tick path behaves identically, and omitting
symbol is a hard 400 — so no spelling produces a multi-symbol export, and an export
naming "all" is rejected before it is sent; see LseExportRequest::new.
The consequence reaches the consumer: combining N instruments means N artifacts merged with
merge_time_sorted, as on the candle replay path.
A decoded artifact is a synchronous iterator of already-tagged events, so it needs adapting to
that merge’s stream item first; read_export documents the adapter. (Not linked: the decoder is
behind its own feature, so the link would be dead in a build without it.)
The rejection is case-sensitive on purpose: ALL is Allstate’s real ticker, so refusing it
would forbid a correct export with no way around it. “Matches nothing” is a property of the
(dataset, symbol) pair, not of the string.
§Range semantics
start is inclusive and end is exclusive, matching the candles endpoint. Measured
twice: a tick export over [2026-07-01, 2026-07-02) yielded only 2026-07-01, and a daily candle
export ending 2026-07-20 produced no bar for the 20th. The range is date-granular, which
LseExportRange makes explicit by taking NaiveDate rather than silently truncating a
timestamp.
§⚠️ Licensing
Exported data is not redistributable. An export produces a file on your disk that is trivially easy to commit or share by accident; it must not be. See the module documentation and https://londonstrategicedge.com/terms.
Structs§
- LseExport
- A downloaded export artifact, with the provenance needed to decode it safely.
- LseExport
Job - The response to an export submission.
- LseExport
JobStatus - The state of an export job, as reported by the status endpoint.
- LseExport
Range - The date range an export covers.
- LseExport
Request - A validated export request.
Enums§
- LseExport
Status - Lifecycle state of an export job.
- LseExport
Timeframe - What an export job covers, in the provider’s own timeframe vocabulary.