Skip to content

Overview

A strategy in Virtufin is the pair of morphisms (decide, execute) modelled coalgebraically (see the behaviour spec). This devkit provides the execute bridge: the consumer half of the loop virtufin-strategy-devkit's StrategyWorkerBase produces the decide half of.

In plain terms: decide watches the market and its own holdings and submits orders; execute is the separate, downstream process that actually places (or simulates) those orders and reports back what happened. The two are connected by CloudEvents on the pubsub-topics spec's trading topics, not a function call in the same process -- that's a deliberate architectural choice, not an implementation detail that could just as well have been a direct call. A strategy worker and an executor worker can be scaled, deployed, and restarted independently, and the same executor can serve any number of strategies that happen to submit orders into the same scenario.

The executor

execute is an IExecutor<TState, TAction, TEvent> (Virtufin.Core):

public interface IExecutor<TState, TAction, TEvent>
    where TState : IExecutionState
    where TAction : ITradeAction
    where TEvent : ITradeEvent<TAction>
{
    TState Initial { get; }
    Task<(TState NextState, TEvent Event)> ExecuteAsync(TState state, TAction action);
}
  • TState — the executor's own hidden state (empty for a deterministic simulator, a PRNG seed for a slippage model, connection state for a live venue integration).
  • TAction / TEvent — fixed to RichTradeAction/TradeEvent by ExecutorWorkerBase<TState> (see Bridge) -- every executor in this org drives the same trade ADTs, only the state varies.

Virtufin.Base.Execution (in virtufin-dotnet) provides four implementations: DeterministicExecutorBase (pure, synchronous fills), SlippageExecutorBase (adds a slippage distribution), LiveExecutorBase (genuinely async -- routes to a real exchange), and ObserveOnlyExecutor (a decorator: wraps another executor, records what it produced without altering the call).

Before wiring a strategy to a live executor (act), see the strategy devkit's testing guidance: unit-test, backtest, then shadow-trade with an ObserveOnlyExecutor-wrapped worker (see virtufin-execution-engines's ShadowExecutor) before ever setting strategy.world = act. This devkit doesn't certify an executor as safe to trade with real capital -- it only provides the plumbing.