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.