Toolchain · 30 decisions across 7 layers

The toolchain,
and what it
ruled out.

A stack list without rejections is a list of things that were available. This is the record of decisions — what was selected at each layer of the corpus, and what was turned down for it. The reasoning is the part that survives when the specific tool is eventually replaced.

0

Selections on the record

0

Layers, boundary to boundary

0

Languages in production

0

Systems the stack has carried

01 — Languages

One per job, chosen at the boundary

The corpus runs nine languages in production. That is not eclecticism — each boundary was drawn where a measured cost justified crossing it.

  • Python

    Modelling, pipelines, orchestration

    Chosen Every dependency that matters in machine learning and scientific computing ships wheels for it. It is where the ecosystem is, and arguing with that costs more than it saves.

    Instead of Rewriting numerical stacks in a faster language is how you introduce bugs, not how you remove dependencies.

  • Rust

    Application shells, real-time cores

    Chosen Where a dropped frame is a defect. The terminal shell must stay responsive with a live feed attached, and a garbage-collected runtime cannot promise that.

    Instead of Electron: proven at version one, and proven to have a ceiling once a chart surface, a terminal and a 3D view share a frame budget.

  • C++

    Indicator hot paths

    Chosen Rolling volatility and channel extremes, bound in-process. The boundary is drawn at measured cost — everything else stays readable.

    Instead of Rewriting whole strategies in C++ would make them faster and unmaintainable, and the strategies are not the bottleneck.

  • R

    Econometric research

    Chosen Decades of statistical libraries with peer-reviewed implementations. It runs as a service so its process lifetime is nobody else’s problem.

    Instead of Reimplementing time-series econometrics in Python to avoid a second runtime trades a dependency for a correctness risk.

  • JavaScript

    Interfaces

    Chosen Plain JavaScript with no transpilation where the surface is small. No bundler means no lockfile drift and nothing between the source and the browser.

    Instead of TypeScript is used where a data model is shared across a team; it is overhead on a single-operator interface with no public API.

  • SQL · WGSL · Shell

    Data, shaders, glue

    Chosen Each is the native language of its layer. Querying through an ORM abstraction, or drawing through a wrapper, costs the thing you went there for.

    Instead of Abstractions over SQL make the easy queries shorter and the hard ones impossible.

02 — Machine learning

Small trainable surface, strong pretrained base

Label scarcity is the binding constraint in every domain here, so the architecture is chosen to need as few labels as possible rather than to be as large as possible.

  • PyTorch + Lightning

    Training

    Chosen Lightning supplies loops, checkpointing and mixed precision for free at these model sizes, which is most of the boilerplate and none of the interesting part.

    Instead of JAX was rejected on ecosystem friction with the geometry stack; TensorFlow on research reuse.

  • Self-supervised pretraining

    Representation learning

    Chosen Unlabelled sensor data is abundant and labelled data is measured in minutes. Pretraining first is the only route that respects that ratio.

    Instead of Supervised training from scratch needs orders of magnitude more labelled data than any realistic study produces.

  • QLoRA on a small spine

    Language generation

    Chosen A compact instruction-tuned model with a low-rank adapter fits in consumer VRAM and trains in hours, not weeks.

    Instead of Full fine-tuning of a large model buys fluency that was never the constraint, at a cost that was.

  • llama.cpp · quantised weights

    Serving

    Chosen Overnight batch work has no latency requirement, so CPU-capable inference removes a GPU from the production path entirely.

    Instead of A GPU serving stack is the right answer for interactive inference and the wrong one for a nightly queue.

  • Retrieval before generation

    Document systems

    Chosen Content is retrieved and ranked from a governed corpus before any prose exists. The corpus is the authority; the model is the writer.

    Instead of Generation-first with citations attached afterwards produces fluent text and unverifiable claims.

03 — Estimation & geometry

Computed, never generated

Geometry, arithmetic and constraint satisfaction are solved by deterministic machinery. A language model that emits a coordinate is a language model producing a confident guess.

  • Factor-graph smoothing

    Trajectory estimation

    Chosen Heterogeneous constraints — odometry, heading, barometric floor, dock priors, loop closures — combine in one optimisation with principled uncertainty out the other side.

    Instead of A filter processes measurements once and cannot revisit them; a smoother uses the whole shift, which is exactly what a batch pipeline can afford.

  • Learned heteroscedastic odometry

    Motion model

    Chosen The network predicts displacement and its own uncertainty, so the optimiser knows which segments to trust.

    Instead of A fixed noise model treats a confident stride and an ambiguous one identically, which corrupts the whole graph.

  • Deterministic vector rendering

    Map output

    Chosen Maps render from a validated schema, so the geometry in the artifact is the geometry that was computed.

    Instead of Raster or model-drawn output cannot be checked against its source, which makes it undisplayable under the evidence rule.

04 — Quantitative & trading

One implementation, live and historical

The seam between research and execution is where retail systems fail. Everything here is arranged so that seam does not exist.

  • Shared strategy objects

    Research/execution parity

    Chosen The identical strategy and risk-manager instances run in the live loop and in the backtester. There is no second implementation to drift.

    Instead of A separate research implementation is faster to write and guarantees a divergence nobody notices until it costs money.

  • Event-driven replay

    Backtesting

    Chosen The engine cannot tell whether it is reading a live feed or a historical one, so anything a strategy cannot get from the event stream is something the backtest could not have known either.

    Instead of Vectorised backtesting is fast and quietly permits lookahead that no live system could reproduce.

  • Layered conviction sizing

    Risk

    Chosen Position size is a function of a multi-factor conviction score under drawdown breakers and cooldowns.

    Instead of Fixed fractional sizing treats a marginal setup and a strong one identically.

  • Kill switch · watchdog · auto-flatten

    Operational safety

    Chosen The features that produce no return. An engine that dies must not leave a position open behind it.

    Instead of Nothing. This layer has no acceptable alternative.

05 — Data & storage

Boring, typed, and priced for idle

Storage decisions are made against the cost model and the failure model, in that order. Both are more durable than any feature requirement.

  • PostgreSQL

    Relational core

    Chosen Transactional, well understood, and rich enough that the interesting logic can live in queries rather than in application loops.

    Instead of Document stores were rejected wherever the data is genuinely relational, which is nearly everywhere here.

  • A jobs table, not a broker

    Work queues

    Chosen Row-level locking with skip-locked is transactional, observable in the same database as everything else, and one fewer service to operate.

    Instead of A dedicated queue is correct at thousands of jobs an hour and unnecessary overhead at a hundred a night.

  • Serverless SQL with auto-pause

    Scale-to-zero systems

    Chosen Chosen specifically for idle economics, accepting weaker native geospatial handling and filling the gap with a dedicated mapping service.

    Instead of A richer geospatial engine that cannot pause breaks the cost model that justified the architecture.

  • Dataset and model versioning

    Reproducibility

    Chosen Weights and the data that produced them are versioned together on zero-egress storage, so any published figure traces to an exact input.

    Instead of Large-file versioning without dataset semantics stores the bytes and loses the lineage.

06 — Interfaces & delivery

Static where possible, native where necessary

The interface layer is chosen by what the surface actually has to do, which is usually far less than the default answer assumes.

  • Static generation

    Sites and documents

    Chosen Content that changes when the author changes it does not need a server. Pages are generated from a data corpus at build time and served as files.

    Instead of A CMS and a runtime add operational surface for content with one editor.

  • Queue and worker

    Long jobs

    Chosen Minute-scale analysis cannot live behind a request. Jobs enqueue, a worker drains, and transient failures re-queue rather than failing the user.

    Instead of Synchronous request-response turns a rate limit into a lost job and a timeout into a support ticket.

  • Native GPU shells

    Real-time desktop

    Chosen Where a live chart, a terminal and a 3D view share one frame budget, the shell has to render through the platform graphics API.

    Instead of A wrapped web runtime was measured against this requirement and failed it.

  • Model Context Protocol

    Agent tooling

    Chosen A new capability becomes a server rather than a fork. Slower for the first integration and dramatically cheaper by the tenth.

    Instead of Bespoke integrations multiply, and each one is a place for behaviour to diverge.

07 — Discipline

What makes the rest of it checkable

The tools that produce nothing visible and prevent most of the expensive failures.

  • Typed I/O boundaries

    Correctness

    Chosen Validation at the edges of every pipeline stage, so a source that changes shape fails loudly at ingestion rather than silently at the model.

    Instead of Trusting upstream schemas is how a pipeline learns the sensor instead of the task.

  • Structured logging

    Operability

    Chosen Logs that can be queried rather than read. A long pipeline will fail partway through, and the question is always which record and which stage.

    Instead of Printed strings are unusable at the point you actually need them.

  • Property-based testing

    Signal and geometry code

    Chosen Invariants over generated inputs catch the edge cases that hand-written examples do not, which is most of them in DSP and closure code.

    Instead of Example-based tests confirm the cases the author already thought of.

  • Resumable stages

    Pipelines

    Chosen Every stage re-runnable without corrupting what came before, because rate limits, layout changes and exhausted quotas are certainties.

    Instead of Designing for a clean single pass produces a pipeline that is nursed rather than operated.

The rule underneath all of it

Every boundary here was drawn
at a measured cost.

None of these are permanent. They are the current answers, each with the reasoning attached, so that when one stops being right the replacement is an argument rather than a preference.