Table of Contents

Class IndicatorExtensions

Namespace
Virtufin.Core.Behavior
Assembly
Virtufin.Core.dll

Pure combinators over IIndicator<TSelf, TSample, TValue> — the foldable counterparts of SignalExtensions's map/zip (domain spec §10.4). An indicator's current value can't be derived from another indicator's value alone the way a plain ISignal<T> can, because the combinator itself must stay foldable — it needs an Add(TSample) that threads new samples into the wrapped indicator(s). Each combinator therefore returns a small concrete wrapper type (not just the IIndicator<TSelf, TSample, TValue> interface) so the self-referential TSelf constraint has something nameable to bind to, and so the result can itself be composed further.

public static class IndicatorExtensions
Inheritance
IndicatorExtensions
Inherited Members

Remarks

Two tiers beyond Map/Combine:

Methods

Adapt<TSelf, TSample, TValue, TExternal>(IIndicator<TSelf, TSample, TValue>, Func<TExternal, TSample>)

Derive an indicator that accepts a different incoming type, decoding each one into the wrapped indicator's sample type before folding — e.g. the gateway for building an indicator directly from a CloudEvent (see Virtufin.Worker.DevKit's FromCloudEvent, downstream, where the CloudEvents dependency actually lives).

public static AdaptedIndicator<TSelf, TSample, TValue, TExternal> Adapt<TSelf, TSample, TValue, TExternal>(this IIndicator<TSelf, TSample, TValue> indicator, Func<TExternal, TSample> decode) where TSelf : IIndicator<TSelf, TSample, TValue>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

decode Func<TExternal, TSample>

Converts an incoming TExternal into the sample type the wrapped indicator consumes.

Returns

AdaptedIndicator<TSelf, TSample, TValue, TExternal>

Type Parameters

TSelf
TSample
TValue
TExternal

The external type the derived indicator's Add(TSample) now accepts.

Combine<TLeft, TRight, TSample, TL, TR, TResult>(IIndicator<TLeft, TSample, TL>, IIndicator<TRight, TSample, TR>, Func<TL, TR, TResult>)

Derive an indicator by fanning one incoming sample out to two indicators of the same sample type and combining their current values (e.g. a fast/slow moving-average spread for a golden-cross signal).

public static CombinedIndicator<TLeft, TRight, TSample, TL, TR, TResult> Combine<TLeft, TRight, TSample, TL, TR, TResult>(this IIndicator<TLeft, TSample, TL> left, IIndicator<TRight, TSample, TR> right, Func<TL, TR, TResult> f) where TLeft : IIndicator<TLeft, TSample, TL> where TRight : IIndicator<TRight, TSample, TR>

Parameters

left IIndicator<TLeft, TSample, TL>

The left source indicator.

right IIndicator<TRight, TSample, TR>

The right source indicator.

f Func<TL, TR, TResult>

Pure function combining both current values.

Returns

CombinedIndicator<TLeft, TRight, TSample, TL, TR, TResult>

Type Parameters

TLeft

The left indicator's concrete type.

TRight

The right indicator's concrete type.

TSample

The sample type both indicators consume.

TL

The left indicator's value type.

TR

The right indicator's value type.

TResult

The derived indicator's value type.

Remarks

Realises the zip combinator (§10.4).

Lag<TSelf, TSample, TValue>(IIndicator<TSelf, TSample, TValue>, int)

Derive an indicator whose value is the source's value from n samples back — e.g. the building block for return computations (Virtufin.Base.Behavior.Returns).

public static LagIndicator<TSelf, TSample, TValue> Lag<TSelf, TSample, TValue>(this IIndicator<TSelf, TSample, TValue> indicator, int n) where TSelf : IIndicator<TSelf, TSample, TValue>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

n int

How many samples back to look. Must be positive.

Returns

LagIndicator<TSelf, TSample, TValue>

Type Parameters

TSelf
TSample
TValue

Exceptions

ArgumentOutOfRangeException

n is not positive.

Map<TSelf, TSample, TValue, TResult>(IIndicator<TSelf, TSample, TValue>, Func<TValue, TResult>)

Derive an indicator whose value is a pure function of another indicator's current value (e.g. an SMA in price units mapped to bps).

public static MappedIndicator<TSelf, TSample, TValue, TResult> Map<TSelf, TSample, TValue, TResult>(this IIndicator<TSelf, TSample, TValue> indicator, Func<TValue, TResult> f) where TSelf : IIndicator<TSelf, TSample, TValue>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

f Func<TValue, TResult>

Pure function from the source value to the derived value.

Returns

MappedIndicator<TSelf, TSample, TValue, TResult>

Type Parameters

TSelf

The source indicator's concrete type.

TSample

The sample type both indicators consume.

TValue

The source indicator's value type.

TResult

The derived indicator's value type.

Remarks

Realises the map combinator (§10.4).

Sum<TSelf, TSample, TValue>(IIndicator<TSelf, TSample, TValue>, int)

Derive an indicator that maintains a running sum over the last count values the source indicator held, updated incrementally (add the newest, subtract the evicted-oldest) rather than resummed from scratch on every read.

public static SumIndicator<TSelf, TSample, TValue> Sum<TSelf, TSample, TValue>(this IIndicator<TSelf, TSample, TValue> indicator, int count) where TSelf : IIndicator<TSelf, TSample, TValue> where TValue : IAdditionOperators<TValue, TValue, TValue>, ISubtractionOperators<TValue, TValue, TValue>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

count int

The window size. Must be positive.

Returns

SumIndicator<TSelf, TSample, TValue>

Type Parameters

TSelf
TSample
TValue

Remarks

The O(1)-amortized counterpart of Take(count).Map(window => window.Sum()) — only possible because addition has a cheap inverse (subtraction) to undo an evicted sample; see the type's remarks for algorithms (like Shannon entropy) that don't. The returned Count reports the live in-window count so a caller turning a sum into an average (e.g. a moving average) divides by the right divisor even before the window fills.

Exceptions

ArgumentOutOfRangeException

count is not positive.

Take<TSelf, TSample, TValue>(IIndicator<TSelf, TSample, TValue>, int)

Derive an indicator whose value is the last count values the source indicator held, oldest first. A sliding window re-derived on every Add(TSample) — not LINQ's "stop after N" Take.

public static TakeIndicator<TSelf, TSample, TValue> Take<TSelf, TSample, TValue>(this IIndicator<TSelf, TSample, TValue> indicator, int count) where TSelf : IIndicator<TSelf, TSample, TValue>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

count int

The window size. Must be positive.

Returns

TakeIndicator<TSelf, TSample, TValue>

Type Parameters

TSelf
TSample
TValue

Remarks

Realises the window combinator (§10.4), count-bounded.

Exceptions

ArgumentOutOfRangeException

count is not positive.

TimeWindowSum<TSelf, TSample, TValue, TTime>(IIndicator<TSelf, TSample, TValue>, Func<TSample, TTime>, Func<TTime, TTime, bool>)

The duration-bounded counterpart of Sum<TSelf, TSample, TValue>(IIndicator<TSelf, TSample, TValue>, int) — an O(1)-amortized running sum over a trailing time window.

public static TimeWindowSumIndicator<TSelf, TSample, TValue, TTime> TimeWindowSum<TSelf, TSample, TValue, TTime>(this IIndicator<TSelf, TSample, TValue> indicator, Func<TSample, TTime> timeOf, Func<TTime, TTime, bool> isExpired) where TSelf : IIndicator<TSelf, TSample, TValue> where TValue : IAdditionOperators<TValue, TValue, TValue>, ISubtractionOperators<TValue, TValue, TValue> where TTime : IComparable<TTime>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

timeOf Func<TSample, TTime>

Extracts the observation time from an incoming sample.

isExpired Func<TTime, TTime, bool>

Called as isExpired(oldestTime, latestTime) during eviction to decide whether the oldest in-window observation has aged out.

Returns

TimeWindowSumIndicator<TSelf, TSample, TValue, TTime>

Type Parameters

TSelf
TSample
TValue
TTime

TimeWindow<TSelf, TSample, TValue, TTime>(IIndicator<TSelf, TSample, TValue>, Func<TSample, TTime>, Func<TTime, TTime, bool>)

Derive an indicator whose value is every (time, value) the source indicator held within the trailing window, oldest first — the duration-bounded counterpart of Take<TSelf, TSample, TValue>(IIndicator<TSelf, TSample, TValue>, int).

public static TimeWindowIndicator<TSelf, TSample, TValue, TTime> TimeWindow<TSelf, TSample, TValue, TTime>(this IIndicator<TSelf, TSample, TValue> indicator, Func<TSample, TTime> timeOf, Func<TTime, TTime, bool> isExpired) where TSelf : IIndicator<TSelf, TSample, TValue> where TTime : IComparable<TTime>

Parameters

indicator IIndicator<TSelf, TSample, TValue>

The source indicator.

timeOf Func<TSample, TTime>

Extracts the observation time from an incoming sample.

isExpired Func<TTime, TTime, bool>

Called as isExpired(oldestTime, latestTime) during eviction to decide whether the oldest in-window observation has aged out.

Returns

TimeWindowIndicator<TSelf, TSample, TValue, TTime>

Type Parameters

TSelf
TSample
TValue
TTime

Remarks

Realises the window combinator (§10.4), duration-bounded — the same eviction shape Virtufin.Base.Behavior.SimpleMovingAverage uses internally, generalised into a reusable combinator.