Orderflow Python Binding (orderflow-gregorian09)
Production-focused Python API for the Orderflow runtime.
This package wraps the stable of_ffi_c ABI via ctypes and provides a typed,
high-level interface for lifecycle management, subscriptions, snapshots, and
external feed ingestion.
The package includes a PEP 561 py.typed marker so type checkers can consume
the inline annotations shipped with the binding.
The binding also exposes an additive execution API through ExecutionEngine.
Execution uses a separate native handle from analytics and returns typed
execution events rather than JSON on the order path.
The README is intentionally API-complete so the PyPI page can be used as a single reference, similar to high-signal package pages such as TA-Lib and FastAPI.
What's New In 0.5.0
0.5.0 keeps the existing Python market-data and execution APIs intact while
adding production persistence lifecycle, typed adapter diagnostics,
config-driven signal replay validation, and deterministic TWAP parent control.
Highlights:
- additive simulated execution APIs:
ExecutionEngine,ConcurrentExecutionEngine,OrderRequest,CancelRequest,AmendRequest,RiskLimits,RouteConfig, and execution event dataclasses - multi-route execution construction for multi-symbol order flow
- bounded concurrent execution worker for many producers and one deterministic native order-state owner
- typed execution events and command reports instead of JSON on the order path
- route/account/symbol-scoped risk checks before adapter routing
- offline WAL and checkpoint-store diagnostics for recovery checks without opening an execution engine
- adapter inventory/status helpers for provider capability discovery before connecting a feed
- signal descriptor discovery through
signal_descriptors()andEngine.signal_descriptors()for dashboard/configuration inventory - signal explanation discovery through
Engine.signal_explanation(symbol)for audit and dashboard diagnostics - signal metrics through
Engine.signal_metrics()for state counts, confidence, quality, and explanation coverage diagnostics - offline config-driven signal validation through
SignalConfig,validate_signal_config(), andvalidate_signal_replay()with parsed reports, retained samples, and replay-order warnings - manifest/header-driven low-level
ctypessignature generation with CI drift checks, while typed high-level wrappers remain manually designed - analytics-to-execution examples in this README and the handbook
- continued PEP 561
py.typedsupport and bundled native library lookup
Version policy:
- Python package:
0.5.0 - compatible native
of_ffi_clibrary/header:0.5.0 of_execution 0.2.0,of_execution_core 0.2.0, and their independently versioned execution companions behind the native ABI (of_execution_algosis0.1.0,of_execution_adaptersis0.2.0, andof_fixremains0.1.x)
Install the Python package and native runtime at the same release version.
Execution users should pin of_execution_core and of_execution to compatible
0.2.x versions, and use the matching 0.1.x algorithm/adapter companion
releases when they build custom native providers.
Execution quick start
from orderflow import (
ConcurrentExecutionEngine, ExecutionEngine, ExecutionOrderType, ExecutionSide, ExecutionTimeInForce,
OrderRequest, RiskLimits, RouteConfig,
)
limits = RiskLimits(False, 100, 1_000_000, 10, 10_000_000, 0)
routes = [
RouteConfig("SIM", "ACC", "SIM", "ES", True, limits),
RouteConfig("SIM", "ACC", "SIM", "NQ", True, limits),
]
with ExecutionEngine(routes) as execution:
events = execution.submit_order(OrderRequest(
"C1", "ACC", "SIM", "STRAT", "SIM", "ES",
ExecutionSide.BUY, ExecutionOrderType.LIMIT, ExecutionTimeInForce.DAY,
10, 5000,
))
Deterministic TWAP planning remains separate from OMS submission:
from orderflow import TwapConfig, TwapExecutionAlgo
config = TwapConfig(
"parent-1", "ACC", "SIM", "TWAP", "SIM", "ES",
ExecutionSide.BUY, ExecutionOrderType.LIMIT, ExecutionTimeInForce.DAY,
100, 5000, 1_000, 11_000, 10, 25, 2_000,
)
with ExecutionEngine(routes) as execution, TwapExecutionAlgo(config) as twap:
child = twap.plan(1_000, "child-1", "order-1", 1_001)
if child is not None:
events = execution.submit_order(child.request)
twap.commit_pending()
for event in events:
twap.record_execution(event.last_qty, event.leaves_qty, event.order_status)
plan() is retry-stable while a child is pending. Call commit_pending()
only after OMS submission succeeds, or discard_pending() when submission did
not occur. The planner itself cannot bypass OMS risk, journaling, or adapters.
ExecutionEngine(route) remains supported for single-symbol integrations. When
you pass a route list, native risk accounting is scoped per
route/account/symbol.
Use ConcurrentExecutionEngine(routes) when multiple producer threads need to
queue commands into one deterministic native worker. Command methods return a
sequence number; try_recv_report() returns completed command reports without
blocking.
Binding manifest policy
Low-level native symbols are tracked in bindings/api_manifest.toml. The
manifest controls membership, ordering, ownership metadata, and exposure. The
validated orderflow.h supplies exact parameter and return types to
tools/generate_binding_signatures.py, which commits
orderflow/_generated_signatures.py. orderflow/_ffi.py defines structure
layouts and library loading, then delegates function registration to that
generated private module. CI runs the generator with --check and compiles the
result.
Do not edit _generated_signatures.py directly. After an additive C ABI change,
update the header and manifest, run:
python3 tools/check_api_manifest.py
python3 tools/generate_binding_signatures.py
python3 tools/test_generate_binding_signatures.py
python3 tools/check_binding_parity.py
Generation does not replace the hand-written Engine, ExecutionEngine, and
ConcurrentExecutionEngine wrappers. Context managers, dataclasses, typed
requests/events, automatic buffers, exceptions, and Python naming remain manual
because they express user-facing ownership and ergonomics rather than C types.
Signal descriptor discovery
from orderflow import signal_descriptors
inventory = signal_descriptors()
for descriptor in inventory.get("signals", []):
print(descriptor["id"], descriptor["required_inputs"], descriptor["output_semantics"])
The descriptor inventory is read-only metadata. It helps dashboards and config tools list built-in signals, required inputs, warmup, parameters, and output semantics without constructing a live strategy or submitting orders.
After a signal has evaluated for a symbol, Engine.signal_explanation(symbol)
returns the latest explanation payload with reason code, observed inputs,
thresholds, and confidence contributors. This is a diagnostics surface; order
submission decisions should still flow through explicit strategy/risk/OMS code.
Engine.signal_metrics() returns a compact runtime summary of the current
signal cache: state counts, directional count, average confidence, quality
flagged signals, and explanation coverage.
Config-driven replay validation
Use the offline facade to validate a built-in signal without creating a live engine. Parameters are checked against the selected descriptor before native construction. Each observation is evaluated before its future markout is read, and optional exchange timestamps are checked for backward movement.
from orderflow import (
SignalConfig,
SignalConfigParameter,
SignalValidationConfig,
SignalValidationEvent,
validate_signal_config,
validate_signal_replay,
)
signal = SignalConfig(
"delta_momentum_v1",
(SignalConfigParameter("threshold", 10),),
)
config_result = validate_signal_config(signal)
if not config_result["valid"]:
raise ValueError(config_result["error"])
events = [
SignalValidationEvent(delta=20, last_price=100, ts_exchange_ns=1),
SignalValidationEvent(delta=-20, last_price=90, ts_exchange_ns=2),
SignalValidationEvent(delta=-20, last_price=80, ts_exchange_ns=3),
]
report = validate_signal_replay(
signal,
events,
SignalValidationConfig(
markout_horizon_events=1,
flat_price_threshold=0,
min_confidence_bps=0,
store_samples=True,
check_monotonic_timestamps=True,
),
)
print(report.directional_accuracy_bps, report.label_coverage_bps)
for sample in report.samples:
print(sample["event_index"], sample["predicted_direction"], sample["correct"])
for warning in report.warnings:
print(warning["code"])
SignalValidationReport.raw retains the full schema-versioned native document.
An invalid registry id, duplicate/unknown parameter, type mismatch, or
descriptor range violation raises OrderflowArgError from
validate_signal_replay; use validate_signal_config first when a UI or config
service needs a non-throwing validation result. This path is for research,
replay review, and CI. It does not alter live Engine signal state or send OMS
orders.
Architecture
Installation
pip install orderflow-gregorian09
Python support
- Python 3.10+
Native runtime requirement
The Python package is a wrapper. A compatible libof_ffi_c shared library must
be available at runtime. Binary wheels can bundle this library under
orderflow/native/; source installs can still use an externally-built runtime.
Library resolution order:
library_path=passed toEngine(...)ORDERFLOW_LIBRARY_PATHenvironment variable- bundled wheel library (
orderflow/native/libof_ffi_c.*) - default local debug path (
target/debug/libof_ffi_c.*)
export ORDERFLOW_LIBRARY_PATH=/absolute/path/to/libof_ffi_c.so
Quick Start
from orderflow import DataQualityFlags, Engine, EngineConfig, Symbol, StreamKind
with Engine(EngineConfig(instance_id="py-client")) as eng:
sym = Symbol("CME", "ESM6", depth_levels=10)
eng.subscribe(sym, StreamKind.ANALYTICS)
eng.poll_once(DataQualityFlags.NONE)
print("api_version", eng.api_version)
print("build_info", eng.build_info)
print("analytics", eng.analytics_snapshot(sym))
print("derived", eng.derived_analytics_snapshot(sym))
print("signal", eng.signal_snapshot(sym))
print("metrics", eng.metrics())
Production normalized market-data WAL
from orderflow import (
Engine,
EngineConfig,
MarketDataPersistenceFailureAction,
MarketDataWalConfig,
MarketDataWalSyncPolicy,
)
eng = Engine(EngineConfig(instance_id="capture"))
eng.configure_market_data_wal(MarketDataWalConfig(
root_path="data/normalized-wal",
queue_capacity=8192,
max_queued_payload_bytes=128 * 1024 * 1024,
sync_policy=MarketDataWalSyncPolicy.EVERY_RECORDS,
sync_every_records=1000,
failure_action=MarketDataPersistenceFailureAction.STOP_TRADING,
))
eng.start()
try:
# subscribe/poll or configure external ingest here
print(eng.market_data_persistence_health())
eng.flush_market_data_wal() # blocking control-plane barrier
finally:
eng.stop()
eng.shutdown_market_data_wal()
eng.close()
Event admission is bounded and nonblocking; native worker-side encoding keeps filesystem work and JSON formatting off the calling thread. Flush and shutdown block and belong on a control-plane thread. The health payload exposes queue depth and high-water marks, event-time backlog, rejected/abandoned records, write/sync failures, and last written/durable sequence.
Complete End-To-End Example
This example uses deterministic external ingest and simulated execution. It is safe for documentation, CI smoke tests, and first user experiments because it does not connect to a broker.
from orderflow import (
BookAction,
DataQualityFlags,
Engine,
EngineConfig,
ExecutionEngine,
ExecutionOrderType,
ExecutionSide,
ExecutionTimeInForce,
ExternalFeedPolicy,
OrderRequest,
RiskLimits,
RouteConfig,
Side,
StreamKind,
Symbol,
)
def signal_allows_long(analytics: dict, signal: dict) -> bool:
quality = int(analytics.get("quality_flags", 0))
delta = int(analytics.get("delta", 0))
cumulative_delta = float(analytics.get("cumulative_delta", 0.0))
confidence = float(signal.get("confidence", 0.0))
return (
quality == DataQualityFlags.NONE
and delta > 0
and cumulative_delta > 0.0
and confidence >= 0.50
)
sym = Symbol("SIM", "ES", 10)
limits = RiskLimits(False, 5, 1_000_000, 1, 1_000_000, 0)
routes = [RouteConfig("SIM", "ACC", "SIM", "ES", True, limits)]
with Engine(EngineConfig(instance_id="py-end-to-end")) as market, ExecutionEngine(routes) as execution:
market.configure_external_feed(ExternalFeedPolicy(2_000, True))
market.subscribe(sym, StreamKind.ANALYTICS)
market.subscribe(sym, StreamKind.SIGNALS)
market.ingest_book(sym, Side.BID, 0, 500_000, 100, BookAction.UPSERT, sequence=1)
market.ingest_book(sym, Side.ASK, 0, 500_025, 120, BookAction.UPSERT, sequence=2)
market.ingest_trade(sym, 500_025, 2, Side.ASK, sequence=3)
market.poll_once(DataQualityFlags.NONE)
analytics = market.analytics_snapshot(sym)
signal = market.signal_snapshot(sym)
if signal_allows_long(analytics, signal):
events = execution.submit_order(OrderRequest(
"PY-0001",
"ACC",
"SIM",
"DOCS",
"SIM",
"ES",
ExecutionSide.BUY,
ExecutionOrderType.LIMIT,
ExecutionTimeInForce.DAY,
1,
500_025,
))
print("events", events)
print("state", execution.order_state("PY-0001"))
print("execution metrics", execution.execution_metrics())
else:
print("blocked", {"analytics": analytics, "signal": signal})
Production applications add durable persistence, execution journaling, provider adapter ownership, reconnect/recovery policy, and monitoring around this shape.
Public API Reference
Constants
StreamKind
| Name | Value | Meaning |
|---|---|---|
BOOK |
1 | Level-2 book update stream |
TRADES |
2 | Trade print stream |
ANALYTICS |
3 | Analytics snapshot stream |
SIGNALS |
4 | Signal snapshot stream |
HEALTH |
5 | Health transition stream |
BOOK_SNAPSHOT |
6 | Materialized book snapshot stream after book changes |
DERIVED_ANALYTICS |
7 | Derived analytics stream after trade-driven analytics changes |
Side
| Name | Value | Meaning |
|---|---|---|
BID |
0 | Bid / buy side |
ASK |
1 | Ask / sell side |
BookAction
| Name | Value | Meaning |
|---|---|---|
UPSERT |
0 | Insert or update price level |
DELETE |
1 | Delete price level |
DataQualityFlags
| Name | Value | Meaning |
|---|---|---|
NONE |
0 |
No quality issues |
STALE_FEED |
1 << 0 |
Feed became stale |
SEQUENCE_GAP |
1 << 1 |
Sequence gap detected |
CLOCK_SKEW |
1 << 2 |
Clock skew detected |
DEPTH_TRUNCATED |
1 << 3 |
Depth truncation occurred |
OUT_OF_ORDER |
1 << 4 |
Out-of-order sequence detected |
ADAPTER_DEGRADED |
1 << 5 |
Adapter/feed degraded |
Exceptions
| Exception | Purpose |
|---|---|
OrderflowError |
Base binding/runtime failure |
OrderflowStateError |
Invalid lifecycle/state transition |
OrderflowArgError |
Invalid argument passed to native API |
Data Classes
Symbol(venue: str, symbol: str, depth_levels: int = 10)
- venue/instrument descriptor used by subscribe/snapshot/ingest APIs.
EngineConfig(...)
EngineConfig fields:
| Field | Type | Default | Notes |
|---|---|---|---|
instance_id |
str |
"python" |
Runtime instance id |
config_path |
str |
"" |
Optional runtime config file path |
log_level |
int |
0 |
Reserved log-level field |
enable_persistence |
bool |
False |
Enable local persistence |
audit_max_bytes |
int |
10*1024*1024 |
Per-file audit size before rotation |
audit_max_files |
int |
5 |
Number of rotated audit files |
audit_redact_tokens_csv |
str |
"secret,password,token,api_key" |
Redaction tokens |
data_retention_max_bytes |
int |
10*1024*1024 |
Persistence retention limit |
data_retention_max_age_secs |
int |
7*24*60*60 |
Max retention age |
ExternalFeedPolicy(stale_after_ms: int = 15000, enforce_sequence: bool = True)
- external ingest supervision policy for stale and sequence validation.
Engine API
Constructor and properties
| Signature | Description |
|---|---|
Engine(config: EngineConfig, library_path: Optional[str] = None) |
Creates native engine handle |
engine.api_version -> int |
Returns native ABI version |
engine.build_info -> str |
Returns native build descriptor |
Lifecycle and session
| Signature | Description |
|---|---|
start() -> None |
Starts runtime |
stop() -> None |
Stops runtime |
close() -> None |
Unsubscribes and destroys native handle |
context-manager (with Engine(...)) |
Calls start() / close() automatically |
Subscription and polling
| Signature | Description |
|---|---|
subscribe(symbol, stream_kind=StreamKind.ANALYTICS, callback=None) |
Registers stream subscription with optional callback |
unsubscribe(symbol) |
Unsubscribes all streams for symbol |
poll_once(quality_flags=DataQualityFlags.NONE) |
Drains adapter/runtime once |
reset_symbol_session(symbol) |
Resets per-symbol session/profile state |
Adapter discovery
| Signature | Description |
|---|---|
adapter_inventory(library_path=None) |
Returns native build adapter descriptor inventory |
available_adapters(library_path=None) |
Returns the inventory adapters list |
engine.adapter_inventory() |
Returns adapter inventory with this engine's active provider marked |
engine.adapter_status() |
Returns configured adapter descriptor plus current health |
Adapter inventory records include provider metadata and additive capability
flags such as supports_backpressure, supports_raw_capture,
supports_fixture_replay, supports_stale_detection, and
supports_latency_metrics when exposed by the native runtime.
engine.adapter_status() also returns additive operational fields: mode,
connection_state, endpoint_redacted, app_name, reconnect_attempt,
subscription_count, sorted subscribed_symbols, queue depth/capacity,
drop/gap counters, stale state, raw-capture utilization, and optional activity
ages. Endpoint output contains only scheme and authority; user information,
paths, queries, and fragments are omitted. Consumers should tolerate future
additive keys and treat null as unavailable rather than zero.
External feed supervision
| Signature | Description |
|---|---|
configure_external_feed(policy) |
Sets stale/sequence policy |
set_external_reconnecting(reconnecting) |
Marks reconnect/degraded state |
external_health_tick() |
Re-evaluates stale status without ingest |
External ingest
| Signature | Description |
|---|---|
ingest_trade(symbol, price, size, aggressor_side, sequence=0, ts_exchange_ns=0, ts_recv_ns=0, quality_flags=DataQualityFlags.NONE) |
Injects one external trade |
ingest_book(symbol, side, level, price, size, action=BookAction.UPSERT, sequence=0, ts_exchange_ns=0, ts_recv_ns=0, quality_flags=DataQualityFlags.NONE) |
Injects one external book update |
Snapshots and metrics
| Signature | Description | Return |
|---|---|---|
book_snapshot(symbol) |
Current book snapshot | dict[str, Any] |
analytics_snapshot(symbol) |
Current analytics snapshot | dict[str, Any] |
derived_analytics_snapshot(symbol) |
Current derived analytics snapshot | dict[str, Any] |
session_candle_snapshot(symbol) |
Current session candle snapshot | dict[str, Any] |
interval_candle_snapshot(symbol, window_ns) |
Current rolling interval candle snapshot | dict[str, Any] |
signal_snapshot(symbol) |
Current signal snapshot | dict[str, Any] |
metrics() |
Runtime metrics | dict[str, Any] |
market_data_persistence_health() |
Production WAL health/backlog | dict[str, Any] |
WAL lifecycle methods are configure_market_data_wal(config),
flush_market_data_wal(), and shutdown_market_data_wal().
book_snapshot(symbol) returns a dictionary with:
venuesymbolbidsaskslast_sequencets_exchange_nsts_recv_ns
The Python wrapper retries automatically if the native snapshot payload is larger than the initial buffer.
session_candle_snapshot(symbol) returns a dictionary with:
openhighlowclosetrade_countfirst_ts_exchange_nslast_ts_exchange_ns
interval_candle_snapshot(symbol, window_ns) returns a dictionary with:
window_nsopenhighlowclosetrade_counttotal_volumevwapfirst_ts_exchange_nslast_ts_exchange_ns
Execution API Reference
Execution objects use typed dataclasses and separate native handles from the analytics runtime.
Execution constants
| Class | Values |
|---|---|
ExecutionSide |
BUY, SELL |
ExecutionOrderType |
MARKET, LIMIT, STOP, STOP_LIMIT |
ExecutionTimeInForce |
DAY, GTC, IOC, FOK, GTD |
Execution dataclasses
| Dataclass | Purpose |
|---|---|
RiskLimits |
Per-route pre-trade limits: kill switch, max quantity, max notional, max open orders, max open notional, price band |
RouteConfig |
Route/account/venue/instrument binding plus RiskLimits |
OrderRequest |
New-order command |
CancelRequest |
Cancel command with new cancel id and original client id |
AmendRequest |
Cancel/replace command |
ExecutionEvent |
Typed native execution event |
ExecutionOrderState |
Current native order state for one client order id |
ExecutionHealth |
Connected/degraded/sequence health snapshot |
ExecutionMetrics |
Submitted/cancelled/amended/events/risk/adapter/recovery counters |
ExecutionWalIntegrityReport |
Offline WAL scan summary for operator diagnostics |
ExecutionSegmentedWalIntegrityReport |
Offline segmented WAL directory scan summary |
ExecutionCheckpointStoreIntegrityReport |
Offline checkpoint store scan summary |
ExecutionRecoveryReplay |
Validated WAL byte/record/sequence range consumed by recovery |
ExecutionRecoveryReport |
Bounded read-only OMS reconstruction summary and resume gates |
ConcurrentExecutionConfig |
Command/report/event-buffer capacities |
ExecutionCommandReport |
Concurrent command result, sequence, result code, and events |
TwapConfig |
Parent ticket, clip bounds, schedule, and slice interval |
AlgoChildPlan |
Owned child id, parent id, due time, and canonical OrderRequest |
AlgoProgress |
Target/released/completed/open quantities and child counters |
TwapExecutionAlgo
| Signature | Description |
|---|---|
TwapExecutionAlgo(config, library_path=None) |
Creates a validated native parent handle |
plan(now_ns, child_order_id, client_order_id, ts_recv_ns) |
Returns AlgoChildPlan or None without advancing progress |
commit_pending() |
Advances released/open quantity after successful OMS submission |
discard_pending() |
Clears an unsubmitted child plan |
record_execution(last_qty, leaves_qty, order_status) |
Folds canonical child execution progress |
progress() |
Returns AlgoProgress |
close() |
Destroys the native handle |
ExecutionEngine
| Signature | Description |
|---|---|
ExecutionEngine(route_or_routes, library_path=None) |
Creates a simulated execution engine for one route or a route list |
start() |
Starts adapter/session |
stop() |
Stops adapter/session |
close() |
Destroys native execution handle |
submit_order(request) |
Submits a new order and returns list[ExecutionEvent] |
cancel_order(request) |
Cancels an order and returns list[ExecutionEvent] |
amend_order(request) |
Amends an order and returns list[ExecutionEvent] |
poll_execution() |
Polls execution adapter and returns list[ExecutionEvent] |
order_state(client_order_id) |
Returns ExecutionOrderState |
execution_health() |
Returns ExecutionHealth |
execution_metrics() |
Returns ExecutionMetrics |
ConcurrentExecutionEngine
| Signature | Description |
|---|---|
ConcurrentExecutionEngine(routes, config=ConcurrentExecutionConfig(), library_path=None) |
Creates a bounded worker |
submit_order(request) |
Queues submit and returns command sequence |
cancel_order(request) |
Queues cancel and returns command sequence |
amend_order(request) |
Queues amend and returns command sequence |
poll_execution() |
Queues poll and returns command sequence |
try_recv_report() |
Returns ExecutionCommandReport or None without blocking |
stop() |
Queues worker stop and returns command sequence |
Top-level execution helpers
| Signature | Description |
|---|---|
inspect_execution_wal(path, library_path=None) |
Inspects a single execution WAL file without creating an execution engine |
inspect_execution_segmented_wal(root, library_path=None) |
Inspects a segmented execution WAL directory without creating an execution engine |
inspect_execution_checkpoint_store(root, library_path=None) |
Inspects an execution checkpoint store directory without creating an execution engine |
inspect_execution_recovery(wal_root, checkpoint_root=None, require_checkpoint=True, library_path=None) |
Reconstructs OMS state from existing roots without mutating them |
Recovery integrity diagnostics
Use inspect_execution_wal() and inspect_execution_segmented_wal() before
recovery drills, after crash restart, or in an operations health check. Both
helpers read bytes outside the order path and return counts, byte position,
optional sequence range, checksum/sequence failure counts, and validity flags.
Use the segmented helper for production rotated WAL roots.
Use inspect_execution_checkpoint_store() with the same restart workflow to
validate checkpoint files before selecting a restart point. It reports
discovered, valid, and invalid checkpoint counts, total checkpoint bytes, and
the latest valid checkpoint id, covered WAL sequence, and creation timestamp.
Corrupt checkpoint files do not raise when the root can be listed; they return a
report with valid == False so operators can inspect the failure and fall back
to the latest valid checkpoint. Missing or unreadable roots raise the mapped
native I/O error.
After the integrity checks, call inspect_execution_recovery() to prove that
the selected checkpoint and WAL tail can reconstruct deterministic OMS state.
The default requires a valid checkpoint. Pass require_checkpoint=False only
for a deliberate full-WAL replay; legacy command-only frames cannot safely
recreate missing orders and therefore fail closed. The helper performs no
writes, opens no venue session, and returns no order identifiers. A successful
report still requires venue reconciliation and keeps submissions disabled.
from orderflow import (
inspect_execution_checkpoint_store,
inspect_execution_recovery,
inspect_execution_segmented_wal,
inspect_execution_wal,
)
single = inspect_execution_wal("execution-wal/wal-000000000001.ofwal")
segmented = inspect_execution_segmented_wal("execution-wal")
checkpoints = inspect_execution_checkpoint_store("execution-checkpoints")
if not single.valid or not segmented.valid or not checkpoints.valid:
raise RuntimeError("unsafe execution recovery inputs")
if checkpoints.latest_checkpoint_id is None:
raise RuntimeError("no valid checkpoint available")
recovery = inspect_execution_recovery(
"execution-wal",
checkpoint_root="execution-checkpoints",
)
if not recovery.venue_reconciliation_required or recovery.submissions_enabled:
raise RuntimeError("invalid fail-closed recovery gates")
# Reconcile recovery.open_orders against venue/drop-copy truth before the host
# creates or resumes any live execution engine.
Usage Patterns
Poll-only flow (no callback)
from orderflow import DataQualityFlags, Engine, EngineConfig, Symbol, StreamKind
with Engine(EngineConfig(instance_id="poll-only")) as eng:
sym = Symbol("CME", "ESM6", 10)
eng.subscribe(sym, StreamKind.ANALYTICS, callback=None)
eng.poll_once(DataQualityFlags.NONE)
snap = eng.analytics_snapshot(sym)
print("delta", snap.get("delta"))
Callback flow
from orderflow import Engine, EngineConfig, Symbol, StreamKind
def on_analytics(ev: dict) -> None:
print("analytics event:", ev)
with Engine(EngineConfig(instance_id="cb-flow")) as eng:
sym = Symbol("CME", "ESM6", 10)
eng.subscribe(sym, StreamKind.ANALYTICS, callback=on_analytics)
eng.poll_once()
External ingest + quality gating
from orderflow import (
BookAction,
DataQualityFlags,
Engine,
EngineConfig,
ExternalFeedPolicy,
Side,
Symbol,
StreamKind,
)
sym = Symbol("BINANCE", "BTCUSDT", depth_levels=20)
with Engine(EngineConfig(instance_id="external-ingest")) as eng:
eng.configure_external_feed(
ExternalFeedPolicy(stale_after_ms=2_000, enforce_sequence=True)
)
eng.subscribe(sym, StreamKind.HEALTH, callback=lambda ev: print("health:", ev))
eng.ingest_book(sym, Side.BID, 0, 62500000, 1000, BookAction.UPSERT, sequence=1)
eng.ingest_trade(sym, 62510000, 200, Side.ASK, sequence=2)
eng.poll_once(DataQualityFlags.NONE)
Operational Notes
- callbacks fire during
poll_once(...)andingest_*calls. - callback handlers should remain non-blocking.
- snapshot APIs decode runtime JSON and return Python
dict. OrderflowStateError("engine is closed")meansclose()was already called.
Troubleshooting
FileNotFoundError: Orderflow shared library not found
- build native runtime (
cargo build -p of_ffi_c) or provide explicit path. - verify
ORDERFLOW_LIBRARY_PATHpoints to the correct platform library.
OrderflowArgError from subscribe/ingest
- validate symbol fields (
venue,symbolnot empty). - validate enum-like integer constants (
Side,BookAction,StreamKind).
No callback events
- ensure subscription callback is not
None. - call
poll_once(...)regularly if using adapter-driven mode.
Documentation and Links
- Project docs: https://github.com/gregorian-09/orderflow/tree/main/docs
- Binding guide: https://github.com/gregorian-09/orderflow/tree/main/docs/bindings/python.md
- Handbook: https://github.com/gregorian-09/orderflow/tree/main/docs/handbook
- Changelog: https://github.com/gregorian-09/orderflow/blob/main/CHANGELOG.md
Metadata
Release files for orderflow-gregorian09 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| orderflow_gregorian09-0.5.0.tar.gz | 53.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| orderflow_gregorian09-0.5.0-py3-none-manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
Total release size: 784.8 kB
Release files / orderflow_gregorian09-0.5.0.tar.gz
| Download URL | orderflow_gregorian09-0.5.0.tar.gz |
|---|---|
| Size | 53.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1d838e6ba4019ad9c2c35323addd1bd8b56cf640091c68f7daf057fbbc27efe5
|
|
BLAKE2b-256 checksum How to use checksums |
a40d02a3c49266205f69138fd0d0d5ff179778f57b767ea7cc577a2605e61ad7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / orderflow_gregorian09-0.5.0-py3-none-manylinux2014_x86_64.whl
| Download URL | orderflow_gregorian09-0.5.0-py3-none-manylinux2014_x86_64.whl |
|---|---|
| Size | 731.7 kB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
c33436916c349b8abfc8c71f0feab0f024568ba8d2efb8da38a12e7b0bb05feb
|
|
BLAKE2b-256 checksum How to use checksums |
a0da3a9615ee0da8362581056cff45bdd9dd6afd10194b3ea155c9cd2d6f36fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|