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