Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

One Bar to One Broker Action

The representative operation is a fresh one-minute bar that produces an entry signal and eventually changes broker exposure.

1. The coordinator establishes the topology

launch_fleet creates a bounded SignalBatch channel, one bounded state-update channel per engine, and prebuilt command channels for executors. It then spawns one signal engine per instrument and one singleton router.

Source: fleet_coordinator.rs:82

The coordinator does not create broker clients. Executors are already running because broker construction, credentials, and connection policy belong to the binary’s setup phase.

2. A signal engine observes a new bar

run_signal_engine polls SharedBarStore, ignores already processed bars, updates session state and indicators, then asks StrategyRunner for actions. The strategy runner is locked only around evaluation and released before the next asynchronous channel send.

Source: signal_engine.rs:282

Even an empty action vector becomes a SignalBatch; executors still need bar ticks for maintenance such as end-of-day flatten checks.

3. The bounded send applies pressure

The engine awaits signal_tx.send(batch). Capacity is 64. If the singleton router falls behind, producers eventually suspend instead of building an unbounded queue of stale decisions. If every receiver is gone, the engine exits successfully.

4. The router chooses a destination

run_signal_router uses tokio::select! to alternate between new signal batches and executor state feedback. route_batch applies isolated, broadcast, or shared-dispatch topology, subscriptions, policy allocation, copy routing, duplicate claims, and entry guardrails.

Source: signal_router.rs:216, route_batch

The result is not a direct broker call. It is an ExecutorCommand::ProcessSignals sent to the chosen deployment’s bounded command channel.

5. One account executor serializes mutation

The executor receives the command, resolves or creates a ContractRuntimeState in its HashMap, rejects off-scope work, drops stale exposure-increasing actions, and deduplicates entry intent IDs.

Source: account_executor.rs:2322

Only this task mutates its broker client and per-contract position state. That single-writer rule is more important than whether Tokio happens to poll the task on one thread or another.

6. Generic action handling reaches a concrete broker

handle_bar_actions accepts Option<&mut (impl BrokerClient + Send)>. It runs capacity and risk checks, calculates allowed size, records attempts, and calls generic order helpers. At compile time, impl BrokerClient becomes the actual ProjectX, Rithmic, paper, or test client type.

Source: actions.rs:833, entry path

7. Observed state closes the loop

After an entry attempt, the executor accelerates reconciliation. Broker positions—not the mere fact that an order request returned—determine the account’s observed exposure. Position changes become ExecutorStateUpdate messages, which the router fans back to all engines for synthetic position tracking.

The complete operation is therefore a loop:

bar → proposal → routed command → guarded action → broker observation → feedback