Skip to content

Helpers

The devkit ships the reusable pieces a strategy worker needs. All are first-in-org implementations.

CloudEvent mappers (Virtufin.Strategy.DevKit.Events)

MarketEventJson / PositionEventJson map CloudEvent payloads to the event ADTs, defining the canonical wire contract:

CloudEvent type Maps to
virtufin.market.TickReceived MarketEvent.TickReceived
virtufin.market.OrderBookReceived MarketEvent.OrderBookReceived
virtufin.market.CandleClosed RichMarketEvent.CandleClosed
virtufin.market.VWAPComputed RichMarketEvent.VWAPComputed
virtufin.market.VolatilityEstimate RichMarketEvent.VolatilityEstimate
virtufin.position.Opened / Updated / Closed / Flipped PositionEvent.*
virtufin.position.UpdatedAttributed RichPositionEvent.UpdatedAttributed

Payloads are camelCase JSON; amounts are plain JSON numbers (parsed exactly via decimal); timestamps are RFC 3339. Unknown types return null (wildcard noise); a known type with a malformed payload throws.

Portfolio fold (Virtufin.Strategy.DevKit)

PortfolioState is the first concrete IPortfolioState; PortfolioAlgebra is the first IAlgebra<IPositionEvent, TState>. It folds position events with set semanticsOpened.Quantity, Updated.NewQuantity and Flipped.NewQuantity set the absolute holding, Closed zeroes it, and UpdatedAttributed applies a delta. Quantities are tracked as integer cardinals at PortfolioState.QuantityPrecision (8), rescaling events at other precisions via DecimalAmount.ToCardinal(int).

Trade-action enrichment (Virtufin.Strategy.DevKit.Events)

TradeActionEnricher maps the raw TradeAction ADT exhaustively to RichTradeAction (strategy id, venue, latency budget). TradeActionJson encodes the enriched action as the bridge's response payload shape. Adding a case to the ADT is a compile error here until mapped.

Moving average (Virtufin.Strategy.DevKit.Indicators)

SimpleMovingAverage is an immutable incremental SMA: Push returns a new instance (safe inside IStrategyState records); Value is null until the window is full. Pure decimal, no Virtufin dependencies.

Amount conversion

Fixed-point conversion lives in DecimalAmount itself (Virtufin.Core 0.4.0+): From(decimal, int) (exact), FromCardinal(long, int), ToDecimal(), and ToCardinal(int) (precision rescale). AmountJson (in .Events) is only the JSON wire-mapping layer: ReadAmount/ReadOptionalAmount parse JSON numbers into DecimalAmount at AmountJson.WirePrecision (8), and Write emits the exact decimal back to JSON.

Config resolution (Virtufin.Strategy.DevKit)

ConfigResolution reads per-instance config from CloudEvent extension attributes only, failing loudly on invalid values.