Class SimpleMovingAverage<TTime, TValue>
Time-windowed simple moving average. "Simple" describes the averaging method (uniformly-weighted mean), not the implementation — count-based windowing is the special case where samples happen to arrive at a regular cadence, so this is windowed by time in general.
public sealed class SimpleMovingAverage<TTime, TValue> : IIndicator<SimpleMovingAverage<TTime, TValue>, TimestampedSample<TTime, TValue>, TValue>, ISignal<TValue> where TTime : IComparable<TTime> where TValue : IAdditionOperators<TValue, TValue, TValue>, ISubtractionOperators<TValue, TValue, TValue>, IDivisionOperators<TValue, TValue, TValue>
Type Parameters
TTimeThe sample time type.
TValueThe sample/average value type.
- Inheritance
-
SimpleMovingAverage<TTime, TValue>
- Implements
-
ISignal<TValue>
- Inherited Members
Remarks
Immutable: Add(TimestampedSample<TTime, TValue>) returns a new instance, safe to carry inside
an IStrategyState record without mutation. Backed by an
ImmutableQueue<T> of in-window samples (append at back,
evict from front, peek front — O(1) amortized per operation), with a
running sum maintained incrementally rather than resummed on every
Value read.
Properties
Count
Number of samples currently inside the window.
public int Count { get; }
Property Value
Value
The current signal value.
public TValue Value { get; }
Property Value
- TValue
Exceptions
- InvalidOperationException
No samples have been added yet.
Methods
Add(TimestampedSample<TTime, TValue>)
Fold one more sample in, returning the updated indicator.
public SimpleMovingAverage<TTime, TValue> Add(TimestampedSample<TTime, TValue> sample)
Parameters
sampleTimestampedSample<TTime, TValue>The new observation.
Returns
- SimpleMovingAverage<TTime, TValue>
A new indicator instance reflecting
sample.
Empty(Func<int, TValue>, Func<TTime, TTime, bool>)
Construct an empty average with no samples yet.
public static SimpleMovingAverage<TTime, TValue> Empty(Func<int, TValue> fromCount, Func<TTime, TTime, bool> isExpired)
Parameters
fromCountFunc<int, TValue>Converts a sample count into a
TValuedivisor — reusable across every Add(TimestampedSample<TTime, TValue>) call, since the in-window count varies under time-based windowing (e.g. fordecimal:count => (decimal)count).isExpiredFunc<TTime, TTime, bool>Called as
isExpired(oldestSampleTime, newestTime)during eviction to decide whether the oldest in-window sample has fallen out of the window (e.g. for DateTimeOffset:(old, latest) => (latest - old) > windowDuration).
Returns
- SimpleMovingAverage<TTime, TValue>