Skip to main content

wos-rfq

The client of the Wolverine tick-quote add-on. The add-on stores private::RealFutureQuote at granularity 0, one row per tick, under the DATED contract code. This package is pure Python and works from any host with Python 3.9 or newer — and inside the Wolverine ring images, on the image's own binding.

pip install wos-rfq          # also installs wos-py (the native pycaitlyn binding) >= 0.0.8
wos-rfq --help

Endpoints

The add-on has no login. The client talks to two endpoints:

  • The storage master, raw TCP — the binary protocol, the default and fast route for reads. Pass --master HOST:PORT, or set WOS_RFQ_MASTER.
  • The add-on's web. Pass --web http://HOST:PORT, or set WOS_RFQ_WEB. It carries the upload API and a JSON read API (/rfq/api/structs, /ticks, /bars, /main) for inspection and debugging. Reads use it only when asked: --via web (--via master is the default; --via auto = web when it answers). JSON is much slower than the binary route; no binding is needed for it.

Commands

Command What it does
structs Lists the storage master's catalog.
read Reads stored ticks. --bars N folds them into N-second bars by the ring sampler's rules (below); the sections come from the ring's market metadata (--sessions-from-master HOST:PORT, a master serving global::Market/Commodity/Holiday), or --manual-trade-period + --manual-time-zone as a marked debugging override.
sessions Prints a commodity's trade-day sections (China time) from the ring's singularity (--sessions-from-master / --sessions-from-web, or the manual override); --format json prints the full document.
main The trade day's main (dated) contract of a commodity, decided by --main-source (env WOS_RFQ_MAIN_SOURCE): metadata (default — the ring's <commodity><00> mapping through --meta-upstream), open_interest (the roll rule on the add-on's own ticks) or ticks (the busiest code of the day). All three are printed with whether they agree; a lagging/leading mapping is a warning with the numbers.
roll The roll days over --from..--to under both sources side by side (metadata and the open-interest rule), with the open interest and volume that decided each rule roll and the days the metadata lagged or led.
sniff Inspects a foreign tick file set and suggests a mapping.
convert Converts a file set to the canonical upload zip and writes a summary.
mapping-help Prints the mapping reference.
upload Uploads a converted zip.
list Lists the uploads.
status Gives the true outcome of one upload.
artifact Shows an upload's processing log.
delete-upload Removes an upload record.
check Compares the stored ticks with the converted rows.
remove Deletes the stored ticks in a time window (storage master only).

A separate milliseconds column (mapping role millis) holds a whole number 0..999. Both spellings are read alike: 209 and 209.0 (any number of trailing zeros) give the same stored time tag, so a vendor that writes the column as decimals needs no normalised copy and no extra mapping key. A fractional value (500.5) is refused with the file, the row and the value — it is never rounded. sniff reads the column the same way: it reports the millisecond values it found (time_shape.millis_examples, time_shape.millis_written_as_decimals) and lists a millisecond-named column holding fractions as unresolved (columns.millis).

The same features are available from Python as wos_rfq.master, wos_rfq.reads, wos_rfq.ticks, wos_rfq.convert and wos_rfq.web (ReadWeb is the JSON read client).

The main contract — three sources, one record

The add-on stores dated contracts; which one is a commodity's main on a trade day comes from one of three sources (wos_rfq.reads.main_contract, wos-rfq main, GET /rfq/api/main?source=):

Source What decides When to choose it
metadata (default) the ring's futures metadata: global::Futures, key <commodity><00>, real_contract_code always, unless you have a reason not to: the ring's continuous series is built from this mapping, so following it never deviates from the ring
open_interest the roll rule on the add-on's own ticks (below) a cross-check, or a reader with no reachable ring metadata
ticks the dated code holding the most ticks of the day what a one-contract capture stored; last resort

The roll rule (open_interest): for trade day T, take every dated contract of the commodity holding ticks of the previous trade day P, its closing open interest (the open_interest of its last tick of P) and its volume of P (the cumulative volume of that tick). The challenger is the contract with the largest open interest among those delivering LATER than the current main. It becomes the main iff its open interest AND its volume both exceed the main's at P — effective from T's trade-day begin, never intraday; no hysteresis margin, no multi-day confirmation. If the main holds no tick of P, the largest open interest takes over (forced). An imported tick's open_interest is its price (not market data): such a day is compared on volume only, and the decision says so. The rule needs every listed contract captured; on a store holding one contract per commodity it cannot see a challenger (a warning says so).

Robust metadata. An unreachable meta upstream is retried (--meta-retries, backoff 1 s doubling); then the last good mapping of that (market, commodity, trade day) from the cache (--cache-dir, env WOS_RFQ_CACHE_DIR, default ~/.cache/wos-rfq) is used and the source says metadata (cached: … N s ago …); with no cache the decision falls to the next source and says so — source = "open_interest (metadata unavailable: <why>)". Every answer carries agree (per source) and warnings (a mapping that LAGS or LEADS the rule, with the open interest and volume that decided it).

Bars — the sampler's rules

wos_rfq.ticks.fold (and read --bars, read_bars, the web's /bars) builds by default the bars the ring's own sampler stores for the contract (global::SampleQuote), traded minute for traded minute:

  1. OHLC from traded ticks only — a tick whose cumulative volume advanced over the previous tick of its trade day. A tick that only moved the book adds no price; it is still counted in ticks and kept in the vectors (tick_time_tags, prices, tick_volumes, bid1, ask1, …). traded counts the traded ticks of the bar.
  2. The pre-open auction (a tick before the trade day's first section) belongs to the first bar, its volume included.
  3. A tick between two sections, or after the close, belongs to the last bar of the preceding section — never forward.
  4. No trade, no bar — the sampler stores no bar for a slot in which nothing traded. quiet_bars=True (--quiet-bars, /bars?quiet_bars=1) returns a dense grid instead: those slots too, traded 0, prices empty.

volume/turnover are sums of per-tick deltas of the cumulative fields over every tick of the bar. outside="drop" (a tick outside every section is in no bar) and outside="next" (to the first bar of the following section) remain as explicit choices; rules 1 and 4 apply in every mode. Bar bounds are the binding's tradeday_sections / sampler_tm_bound on the singularity's rows.

A day the singularity has no row for fails with one stable prefix, no singularity sections for <market> <commodity> on <day>:, followed by the case, read from the same master: holiday/weekend, a gap on the global ring (the neighbours <d1>, <d2> answer; use their sections as the manual override …) or a day not yet reached.

Bindings

The storage-master route needs a pycaitlyn binding; it is imported at the first connect, not at import wos_rfq:

  • the wos-py wheel (>= 0.0.8) — the declared dependency, for every pip user;
  • a ring image's own binding — the SWIG build the ring's workers import. wos_rfq detects it by its surface and does the raw ring frames, the delete body and the error body in pure Python.

wos_rfq.binding() says which one is in use. Without either, import wos_rfq and the JSON read route still work; a storage-master call stops with one line naming what is missing (exit 1 from the command).

Inside a ring image install with --no-deps:

pip install --no-deps wos-rfq

The image already has its binding; installing the wos-py dependency there would put a second pycaitlyn in the venv and, for any process that does not put the image's directory first, shadow the one the ring's workers depend on. The ring images built by the regular pipeline ship this package that way.

Metadata

Release files for wos-rfq 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for wos-rfq 0.5.0
File Interpreter ABI Platform
wos_rfq-0.5.0-py3-none-any.whl Python 3 none any Details

Release files / wos_rfq-0.5.0-py3-none-any.whl

Download URL wos_rfq-0.5.0-py3-none-any.whl
Size 92.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
da095c21b9354804514ad0451d4e457aa06f7e068ef41d42c00e9f1540285a08
BLAKE2b-256 checksum
How to use checksums
5f5edea2472112f3079b466f12e2e700b0f57aaae2032fd140257963ab8d1c14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.11

Release history Release notifications | RSS feed

This release

0.5.0 This release

1 release file

0.4.4

1 release file

0.4.3

1 release file

0.4.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page