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 semantics — Opened.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.