Skip to content

ShadowExecutor

Shadow-mode order executor for the scenarios spec's SHADOW_* worlds (managed JIT, application/x-dotnet-dll), built on virtufin-execution-devkit.

Behaviour

Wraps SimulatedExecutor in Virtufin.Base.Execution.ObserveOnlyExecutor: every order is filled by the same deterministic full-fill-at-limit-price logic SimulatedExecutor uses (same limitations too -- market orders throw), and the resulting Trade Lifecycle Events publish exactly as they would from a real deployment, so downstream position-derivation and dashboards work unmodified.

ObserveOnlyExecutor genuinely calls its wrapped executor and returns whatever it produces -- it does not intercept or suppress calls. That's why this worker wraps the simulator, not a live executor: wrapping a real exchange-routing executor would still submit real orders. Wrapping the simulator is what keeps shadow mode capital-safe.

Subscribes to sc.<scenarioid>.trading.order.submitted for whichever scenario(s) it shadows -- same topic shape as any other executor worker.

Packaging note (unverified)

This worker's nupkg carries two assemblies in lib/<tfm>/ (ShadowExecutorWorker.dll and, since it project-references SimulatedExecutor, SimulatedExecutorWorker.dll) rather than the usual one. This assumes virtufin-workmanager's WorkerNupkgLoader resolves sibling assemblies in the same lib/<tfm>/ directory at load time; that hasn't been verified against a real deployment. If loading fails with a missing-assembly error, that's the first thing to check.

Deploy

cd ShadowExecutor
python3 scripts/build_managed.py --csproj src/Virtufin.Worker.ShadowExecutor/Virtufin.Worker.ShadowExecutor.csproj
python3 scripts/publish.py --worker-nupkg /tmp/worker-out/Virtufin.Worker.ShadowExecutor.nupkg
python3 scripts/create_worker.py --api-client-host localhost --api-client-port 5002

Edit config/config.json's topics (or pass --topic, repeatable) to the scenario(s) this instance should shadow first -- the default is a placeholder.

Package

Virtufin.Worker.ShadowExecutor on the private Gitea NuGet feed; CI publishes via .github/workflows/shadowexecutor-nuget.yaml.