Skip to content

C# Examples

C# examples demonstrate connectivity to all three Virtufin services.

Client package

Package What it is
Virtufin.Api.Client The API gateway client: State, pub/sub, and every gateway service (workmanager, websocketmanager, ...) through dynamic dispatch
Virtufin.*.DevKit The worker devkits (Worker, Behavior, MarketData, Indicator, Strategy, Execution) the notebooks and dotnet/workers/ build on

The notebooks get all of them from the one Virtufin.Examples.Notebooks package (below). In a project of your own, dotnet add package Virtufin.Api.Client from the Virtufin feed (Installation).

Verso notebooks

Most C# examples are Verso notebooks in dotnet/: the devkits end to end (market data, indicator, strategy, executor), the published engines chained into a pipeline, the live platform pipelines, and tours of Virtufin.Core/Base. The README lists them all and covers installing Verso and the registry credentials. Run one headlessly with verso run <notebook> from dotnet/.

Every notebook loads exactly one package:

#!nuget Virtufin.Examples.Notebooks *

Virtufin.Examples.Notebooks is a dependencies-only package (dotnet/notebook-packages/). It lists every package the notebooks use, with its whole dependency closure, at one consistent set of the latest versions. Verso resolves each #!nuget line on its own and can load two versions of the same assembly from two lines (CS1503/CS0508/CS1705), so don't add #!nuget lines next to it. To use another package, add it to the BOM's Directory.Packages.props. CI publishes a new BOM version when its closure changes.

Central Package Management

The example worker projects in dotnet/workers/ pin their versions in dotnet/workers/Directory.Packages.props (kept current by Renovate):

<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<PackageVersion Include="Virtufin.Indicator.DevKit" Version="..." />

Key Patterns

// The context: a name in ~/.config/virtufin/api/contexts.toml, set at the top of the notebook.
const string ContextName = "demo";

// host, port, tls and apiKey come from the context's entry (platform.cs resolves them).
var api = new ApiClient(context.Host, context.Port, context.Tls, context.ApiKey);
dynamic gateway = api;   // gateway services resolve at the call site

// WebSocketManager through the gateway
var connected = await gateway.websocketmanager.Connect(new Dictionary<string, object?>
{
    ["url"] = "wss://stream.binance.com:9443/ws/btcusdt@kline_1m",   // Binance's symbol for BTC_USDT
    ["auto_reconnect"] = true,
});
await gateway.websocketmanager.StartPublish(new Dictionary<string, object?>
{
    // act.exchange.binance.candle.update, from the naming library (names.cs in examples/dotnet)
    ["id"] = connected["id"]!.ToString(), ["topic"] = NotebookNames.CandleUpdateTopic(),
});

// State: a service the gateway registers ("statestore" on demo and local)
await api.SaveStateAsync("statestore", "x.notebook.my-key", "{\"hello\":\"virtufin\"}");
var (value, etag) = await api.GetStateAsync("statestore", "x.notebook.my-key");

dotnet/platform.cs wraps this for the notebooks: Platform.ConnectAsync(ContextName) resolves the context, deploys workers and connections, and CleanupAsync removes everything the notebook created.