indicator-stream
StreamHub indicator development
Provider selection
| Provider Base | Input | Output | Use Case |
|---|---|---|---|
ChainHub<IReusable, TResult> |
Single value | IReusable | Chainable indicators |
ChainHub<IQuote, TResult> |
OHLCV | IReusable | Quote-driven, chainable output |
QuoteProvider<IQuote, TResult> |
OHLCV | IQuote | Quote-to-quote transformation |
StreamHub<TProviderResult, TResult> |
Any hub result | Any result | Compound hubs (internal hub dependency) |
Performance requirements
Target: StreamHub ≤ 1.5x slower than Series.
Forbid O(n²) recalculation — rebuild entire history on each tick:
// WRONG
for (int k = 0; k <= i; k++) { subset.Add(cache[k]); }
var result = subset.ToIndicator();
O(1) incremental update:
// CORRECT
_avgGain = ((_avgGain * (period - 1)) + gain) / period;
Use RollingWindowMax/Min utilities instead of O(n) linear scans.
RollbackState pattern
Override when maintaining stateful fields.
The base class computes restoreIndex via IndexBefore before calling this method.
restoreIndex is the last ProviderCache index to preserve, or -1 to reset everything.
protected override void RollbackState(int restoreIndex)
{
_window.Clear();
if (restoreIndex < 0) return;
int startIdx = Math.Max(0, restoreIndex + 1 - LookbackPeriods);
for (int p = startIdx; p <= restoreIndex; p++)
_window.Add(ProviderCache[p].Value);
}
Replay up to restoreIndex (inclusive). The item at the rollback timestamp is recalculated via normal processing.
Testing requirements
- Inherit
StreamHubTestBase - Abstract method (compile error if missing):
ToStringOverride_ReturnsExpectedName() - Implement ONE observer interface:
ITestChainObserver(most indicators — chain input): inheritsITestQuoteObserver, addsChainObserver_ChainedProvider_MatchesSeriesExactly()ITestQuoteObserver(direct quote input only):QuoteObserver_WithWarmupLateArrivalAndRemoval_MatchesSeriesExactly(),WithCachePruning_MatchesSeriesExactly()
- If hub acts as chain provider, also implement
ITestChainProvider:ChainProvider_MatchesSeriesExactly()
Required implementation
- Source code:
src/**/{IndicatorName}.StreamHub.csfile exists- Uses appropriate provider base (ChainHub or QuoteProvider)
- Validates parameters in constructor; calls Reinitialize() as needed
- Implements O(1) state updates; avoids O(n²) recalculation
- Overrides RollbackState() when maintaining stateful fields
- Overrides ToString() with concise hub name
- Unit testing:
tests/indicators/**/{IndicatorName}.StreamHub.Tests.csexists- Inherits StreamHubTestBase with correct test interfaces
- Comprehensive rollback validation present
- Verifies Series parity
- Catalog registration: Registered in
Catalog.Listings.cs - Performance benchmark: Add to
tools/performance/Perf.Stream.cs - Public documentation: Update
docs/indicators/{IndicatorName}.md - Regression tests: Add to
tests/indicators/**/{IndicatorName}.Regression.Tests.cs - Migration guide: Update
docs/migration.mdfor notable and breaking changes from v2
Examples
-
Chain:
src/e-k/Ema/Ema.StreamHub.cs -
Complex state:
src/a-d/Adx/Adx.StreamHub.cs -
Rolling window:
src/a-d/Chandelier/Chandelier.StreamHub.cs -
Compound hub:
src/s-z/StochRsi/StochRsi.StreamHub.cs
Constraints
- O(n²) recalculation is forbidden; all updates must be O(1)
RollbackState(int restoreIndex)receives the last index to preserve (-1= reset all); replay is inclusive ofrestoreIndex, exclusive of the rollback timestamp- Series parity required: results must be numerically identical to StaticSeries
More from daveskender/stock.indicators
indicator-buffer
Implement BufferList incremental indicators with efficient state management. Use for IIncrementFromChain or IIncrementFromQuote implementations. Covers interface selection, constructor patterns, and BufferListTestBase testing requirements.
17indicator-catalog
Create and register indicator catalog entries for automation. Use for Catalog.cs files, CatalogListingBuilder patterns, parameter/result definitions, and PopulateCatalog registration.
17testing-standards
Testing conventions for Stock Indicators. Use for test naming (MethodName_StateUnderTest_ExpectedBehavior), FluentAssertions patterns, precision requirements, and test base class selection.
16performance-testing
Benchmark indicator performance with BenchmarkDotNet. Use for Series/Buffer/Stream benchmarks, regression detection, and optimization patterns. Target 1.5x Series for StreamHub, 1.2x for BufferList.
15code-completion
Quality gates checklist for completing code work before finishing implementation cycles
14indicator-series
Implement Series-style batch indicators with mathematical precision. Use for new StaticSeries implementations or optimization. Series results are the canonical reference—all other styles must match exactly. Focus on cross-cutting requirements and performance optimization decisions.
13