jonnify·bcs /bcs/trading/engine

B8.1 · The Engine — the trading corpus, docs/trading/

Two questions: in what order, and what it means.

The match path answers exactly two questions, and they are different. In what order, and at what cost of admission — a question of sequencing and overload, answered by a Disruptor-style ingress: EchoCache.Ring, real umbrella source at echo/apps/echo_cache/lib/echo_cache/ring.ex, a bounded buffer whose publish/2 answers :ok or :dropped with the drop counted. What a command means when it meets a book — a question of decision, answered by a functional Decider: decide and evolve, pure, events out. The Ring exists, is tested, and is hardened; what is PROPOSED is the trading engine on top of it — the Book and the Decider — never the substrate.

The Ring is shipped Elixir, hardened by the rung-gated EchoMQ program (docs/echo_mq/emq.roadmap.md); its committed behavior is also on the B4.3 record (bcs_rung_4_3_check.out, PASS 6/6), and every ring figure is verbatim from there. What is PROPOSED is only the trading engine — the Exchange.* suite (docs/trading/) — taught as design because it has run no rung, with no match or fill number invented.

Three shapes, narrowed to the engine. Select a shape to read the primitive it is served by — the engine fills the first; the second and third are its neighbours.
cmd command evt event work work
readout · Select a shape to read the primitive it is served by. The engine occupies the command seat — the Ring's ingress draining a pure Decider; the event log and the work lanes are its neighbours.
§1

The three dives

fixed by the chapter spec · the trading corpus

The engine is one module in three dives — the ingress seat, the pure core, and the order book whose priority falls out of the id law. The ring each dive quotes is committed; the Book, the Decider, and the order book are PROPOSED design objects, taught as design and never as a measured result.

The module hands forward inside the capstone: B8.2 · The Log and the Ledger — the journal the Decider's facts land in, Chapter 4.4's posture as B8.2's subject; then B8.3 · Strategies as Deciders and B8.4 · Fan-Out and the Scale-Out. Those modules and the Exchange.* objects this engine names are PROPOSED design, not routes.

§2

Three shapes, one wire

docs/trading/trading.md

A trading platform has four jobs that pull in different directions: sequence commands per instrument under a single writer; hold a latency budget in microseconds on the match path; stay durable and auditable — every fill a fold over facts; and fan out and follow up. The classic failure is answering all four with one primitive: a queue pressed into a log, a log into a bus, a bus carrying objects. The design rule is the opposite — three messaging shapes, each served by the primitive built for it. The engine fills the first seat and reads into the second.

ShapeCarriesServed by (as-built unless marked PROPOSED)
Commandone ordered command stream per instrument, one writerEchoCache.Ring ingress → Exchange.Book (PROPOSED) draining a pure Decider; sequence is branded mint order
Eventfacts emitted once, read by many, replayablethe claim-check bus (Appendix G) for fan-out; the Journal (B4.4) then per-instrument stream lanes for the log
Workretriable follow-ups: settlement, risk, reportingEchoMQ.Jobs / Lanes / Consumer — fair per-venue lanes (B3.4)
The master invariant. One instrument's book is mutated by exactly one process — the sole drainer of that instrument's Ring — and its state is reconstructable as a fold over an append-only event log. Sequence is mint order. Every primitive keeps its role: the queue is never a log, the log is never a fan-out bus, the bus never carries an object. Nothing on a hot path runs heavier than regular-scheduler work.
§3

The seat — the ring, real and hardened

echo/apps/echo_cache/lib/echo_cache/ring.ex · B4.3 record

The engine invents nothing under the hot path. The Disruptor seat is EchoCache.Ring — real, shipped Elixir at echo/apps/echo_cache/lib/echo_cache/ring.ex, whose surface is publish/2 (:ok, or :dropped with the drop counted when full), occupancy/1 (tail minus head), stats/1 (the counter snapshot plus occupancy, max_batch, and capacity), stop/1, and start_link/1. Its moduledoc states it in the house's own words: "This is the Disruptor's shape translated to the BEAM — sequences, preallocated slots, batched consumption — standing beside the bus's park-don't-poll: both replace discovery with arrival." The Ring, the bus, and the cache are the convergence target of the rung-gated EchoMQ program (/echomq, docs/echo_mq/emq.roadmap.md), and the trading platform is named there as the program's downstream consumer — "the proposed Exchange.* suite standing on exactly this tree; the program's named consumer." The Ring's committed behavior is on the B4.3 record, a source-labelled slice quoted verbatim:

content/echo_data/runtimes/elixir/bcs_rung_4_3_check.out · the Ring's committed behaviorfrozen
header: Valkey on 6390 | Elixir 1.14.0 OTP 25 | schedulers 1
G1 surface ok -- the ring's surface is whole -- publish, occupancy, stats, stop, a generic one-batch apply function -- and the declaration tells the truth: the broadcast table carries its ring name and capacity 512 in the directory, the :none table carries nil, and a fresh ring stands at occupancy 0
G4 full ok -- the bound held its shape: 64 accepted, 136 refused with :dropped and counted -- never blocked, never overwritten -- then the release drained all 64 and publish 201 landed and applied: a storm bends the lane's at-most-once contract no further than the contract already bends
G3 occupancy ok -- mid-storm the gauge read 600 of 4096 and drained to exactly 0; priced, the ring moved 100000 items in 99 ms -- 1005116 items per second end to end on one scheduler, inside the derived band, largest batch 200, nothing dropped
PASS 6/6

The full six-gate record is frozen in the dive that teaches the seat (B8.1.1). The Ring's numbers are real; the trading engine's are not yet — the match latency, the throughput, the fill counts of the Exchange.* suite that drains this Ring do not exist, and so they appear nowhere on these pages. The engine's first such number lands when its first rung's harness runs.

§4

The Disruptor's provenance

docs/trading/trading.patterns.md · Fowler

LMAX's published architecture centers a Business Logic Processor that runs in memory by event sourcing and handles "6 million orders per second on a single thread" (Fowler), surrounded by ring buffers where producers claim slots, a single writer applies in batches, and consumers chase a sequence. The figure is external and quoted with its attribution; the trading engine claims no such number, because it has run no rung yet. The engine takes the principles — the bounded buffer with an explicit overload answer, the single writer applying in batches, sequence as the coordination primitive, journaling beside the hot path — not the Java mechanics. What transfers and what the BEAM deliberately does not copy is the subject of dive 1.

§5

The doors

the sibling courses
§6

References

sources · related

Sources

Related