BL-TR-001: System Architecture
BIJECTIVE LABS
BL-TR-001: System Architecture
Status: RELEASED
Classification: PUBLIC
Revision: 1
Date: 2026-09-07
1. What this system is for
It is a measurement plant. Every number in this record came out of it, and its design was driven by that purpose rather than by throughput.
Two properties mattered more than speed.
Additive strategy attachment. A new hypothesis can be attached as an isolated process reading shared state, placing no orders, without touching anything already running. That property converted the research rate from one hypothesis at a time to several, and it was the most valuable thing the first programme built.
A decision path that does not round-trip through storage. State that a strategy reads on every tick lives in memory in the process that computes it.
2. Topology
Venue websocket feeds
|
INGRESS (Rust) L2 book, trades, liquidations, derivative tickers
| reconnect, health, latency instrumentation
+---- publishes --> cache (hot keys) and time-series store (raw buffer)
|
STATE (Rust) per-instrument state behind a read-write lock,
| in memory, no round trip on the decision path
|
COMPUTE (Rust) order-flow imbalance at L1 and L5, volume-synchronised
| toxicity, trade pressure, cumulative delta,
| liquidation intensity, regime simulation
| results cached back into state
|
STRATEGY (Rust) entries and exits priced by walking the recorded book
|
RISK GATE (Rust) position, notional and loss caps; quote validation
|
+-- order queue --> EXECUTION (Python)
private websocket fill watcher, position tracker
|
STATE AND ORDER MANAGEMENT (Python)
| time-series writer and reader, cache command and query
| split, session and subscription management
|
RISK (Python) the ten-gate funnel in BL-TR-004
|
OBSERVABILITY (Python) audit trail, event store, health, metrics, snapshotsA single orchestrator process loads the compiled Rust component as a native extension and starts each engine as an independently cancellable task. The two languages run in one process rather than as separate services, so the handoff is a function call rather than a network hop.
3. Why the split falls where it does
Rust holds everything on the tick path: ingestion, state, feature computation, strategy evaluation, and the first risk gate. Python holds everything on the slower paths: order lifecycle, persistence, portfolio risk, and observability.
The boundary is not about speed for its own sake. It is that the tick path has a tight loop over a large number of instruments with shared mutable state, which is the case where a language with enforced ownership earns its cost, and the slower paths are where the ability to change something quickly matters more than the microseconds.
The one place the boundary is crossed on the trading path is the order queue. Orders are published to a queue and a Python watcher handles fills over the venue's private websocket. The measured cost of that hop is 0.094 milliseconds at the median and 0.267 at the 99th percentile, against an order round trip of 5 to 6 milliseconds, so the crossing is roughly two percent of the path.
4. Scale
| Component | Lines |
|---|---|
| Python | 28,802 |
| Rust | 15,713 |
| Research instruments | 20,647 across 105 scripts |
| Tests | 6,611 across 65 files, 716 test functions |
The largest single Rust subsystem is the maker engine at 3,673 lines, covering
the quoting loop, order management, four-tier inventory caps, toxicity filtering
and the trigger-based quoting variant. It is complete, wired, and disabled by
configuration, because the verdict against it was economic rather than technical.
Its decision cores are published as
05_INSTRUMENTS/strategies/rust/src/maker_core.rs and its trigger-based variant
as 05_INSTRUMENTS/strategies/rust/src/vacuum_capture.rs; the order manager
and the run loop are not, per BL-IS-017 section 5.
5. What is live, dormant and archived
The repository distinguishes three states and the distinction is documented rather than inferred.
Live. Ingestion, state, compute, risk, execution, observability, and the taker path.
Dormant, code complete. Every strategy family that reached implementation and was then closed. The maker engine, the cross-sectional families, cointegration, trend following, cash and carry, open-interest accumulation, accumulation and distribution. Each is feature-flagged off with a documented verdict beside the flag.
Archived. A multi-exchange universe filter predating the rolling-universe work, retained because it addresses a problem the current code does not.
Closed strategies were not deleted. Their source is the evidence that the verdict
was reached honestly, and it is what a reader with a different envelope re-runs.
The decision cores are being published for that purpose under
05_INSTRUMENTS/strategies/, on the schedule in BL-IS-017. What is published
is the decision logic and its tests; the run loop, the transport and the engine
types stay here, because none of them is needed to check a verdict.
6. Research substrate, kept separate
The research code has no entry point in the orchestrator, and that separation is deliberate.
The causal primitives used by the second programme live in their own modules with their own tests, driven exclusively by the instrument scripts. The read-only recorder for the second venue is likewise separate, with a zero-order guarantee enforced at the process level rather than by configuration.
Research code that can reach an execution path is research code that will eventually reach one. Keeping the wiring absent is stronger than keeping a flag set to false.
7. Deployment
Containerised, with the cache, the time-series store, and the metrics and dashboard stack alongside the trading process. Shadow strategies run as sidecar containers rather than as threads inside the main process, which is what makes the non-disturbance invariant enforceable: restarting a research sidecar cannot touch a running strategy's accumulated sample.
That invariant was written down after a four-variable redesign broke a working configuration and no post-mortem could say which of the four did it.
8. Test posture, stated honestly
The research core is densely tested and the operational system is not.
| Area | Posture |
|---|---|
| Research primitives and instruments | Tests written before the measurement; suite grew from 506 to 694 across the second programme |
| Strategy families | Test-driven throughout, cited per commit |
| Operational Python | Roughly 57 percent of modules carry no coverage, including parts of the live execution path |
| Continuous integration | None configured; tests run when someone runs them |
| Two stress test files | Import a module that was deleted and fail at collection |
The asymmetry was correct in one direction and is a debt in the other. Testing the research core first was right, because a wrong number there produces a wrong verdict and a wrong verdict propagates. Leaving the execution path thin is a debt rather than a decision, and it is recorded here rather than left for a reader to discover.
An honest architecture document says where the coverage is not.
9. What the dependency structure actually shows
The description above is the intended design. This section is what a mechanical scan of the source finds, which is a different kind of evidence and worth separating.
A deterministic parse of 344 source files across the trading system, the research primitives and the instrument set yields 5,563 symbols and 10,821 dependency edges. Ranking symbols by how many other symbols touch them:
| Rank | Symbol | Edges |
|---|---|---|
| 1 | Cache state | 76 |
| 2 | Async cache adapter | 65 |
| 3 | Time-series writer | 42 |
| 4 | Moving-block bootstrap interval | 40 |
| 5 | Accumulation shadow strategy | 38 |
| 6 | Orchestrator entry point | 37 |
| 7 | Research-only assertion | 36 |
| 8 | Change log | 36 |
| 9 | Metrics collector | 35 |
| 10 | Turnover fraction | 34 |
The top three are unsurprising. State and persistence are the most connected components of any trading system, and their position confirms the split described in section 3 rather than telling us anything new.
Three of the remaining seven are worth reading closely, because each one independently corroborates a claim this record makes elsewhere on documentary evidence alone.
A statistical inference primitive is the fourth most connected symbol in the
codebase. The moving-block bootstrap interval sits above the orchestrator
entry point and above every strategy. BL-IS-001 argues that correlation-aware
inference is mandatory rather than preferred on this substrate. The dependency
graph shows a programme that acted on that: almost everything which produces a
number routes through it.
The zero-order assertion is the seventh most connected symbol. BL-TR-003
claims the shadow guarantee is structural rather than configured. A guard that
36 other symbols call is structural. A configuration flag would appear once.
Turnover accounting is tenth. R-01 requires net from day one, and cost
accounting being this deeply wired is what compliance with that rule looks like
from the inside.
None of these three were designed to be prominent. They became prominent because the rules that produced them were enforced, and a scan that knows nothing about the rules found them anyway.
The scan is deterministic and used no language model. It carries 1,255 dangling-endpoint edges, references out to symbols outside the scanned scope, and 490 edges collapsed where the same pair is referenced from several lines. Both are consequences of scoping to a subset and of collapsing a multigraph, and neither affects the ranking above.
10. What a reader should take from this
Two things generalise beyond this codebase.
Separate the tick path from everything else, and put the shared mutable state on the fast side. The design that made the research rate possible was not the language choice; it was that a new strategy could read the same in-memory state without a round trip and without touching an existing consumer.
Keep research wiring absent rather than disabled. A flag is a decision somebody can change. A missing import is not.
11. Cross-references
BL-TR-002 the data substrate. BL-TR-003 the shadow harness. BL-TR-004 the
risk framework. BL-FM-002 sections 4 and 5 for the latency and cadence this
plant produced. BL-IS-000 for the instruments it feeds.
Copyright (c) 2026 Bijective Labs. All rights reserved.