DaveSkender

indicator-buffer

@DaveSkender/indicator-buffer
DaveSkender
1,166
265 forks
Updated 1/18/2026
View on GitHub

Implement BufferList incremental indicators with efficient state management. Use for IIncrementFromChain or IIncrementFromQuote implementations. Covers interface selection, constructor patterns, and BufferListTestBase testing requirements.

Installation

$skills install @DaveSkender/indicator-buffer
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Path.github/skills/indicator-buffer/SKILL.md
Branchv3
Scoped Name@DaveSkender/indicator-buffer

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: indicator-buffer description: Implement BufferList incremental indicators with efficient state management. Use for IIncrementFromChain or IIncrementFromQuote implementations. Covers interface selection, constructor patterns, and BufferListTestBase testing requirements.

BufferList indicator development

Interface selection

All BufferList implementations support IQuote inputs from the base class. The interface determines what additional input types are supported:

InterfaceAdditional InputsUse CaseExamples
IIncrementFromChainIReusable, (DateTime, double)Chainable single-value indicatorsSMA, EMA, RSI
IIncrementFromQuote(none - only IQuote)Requires OHLCV propertiesStoch, ATR, VWAP

Constructor pattern

public class MyIndicatorList : BufferList<MyResult>, IIncrementFromChain
{
    private readonly Queue<double> _buffer;

    // Primary constructor (parameters only)
    public MyIndicatorList(int lookbackPeriods)
    {
        ArgumentOutOfRangeException.ThrowIfLessThan(lookbackPeriods, 1);
        LookbackPeriods = lookbackPeriods;
        _buffer = new Queue<double>(lookbackPeriods);
    }

    // Chaining constructor (parameters + quotes)
    public MyIndicatorList(int lookbackPeriods, IReadOnlyList<IQuote> quotes)
        : this(lookbackPeriods) => Add(quotes);
}

Buffer management

Use extension methods from BufferListUtilities:

  • _buffer.Update(capacity, value) - Standard rolling buffer
  • _buffer.UpdateWithDequeue(capacity, value) - Returns dequeued value for sum adjustment

Note: Future refactor planned to rename BufferListUtilities to BufferListExtensions for .NET idiomatic naming.

State management

Use Clear() to reset all internal state:

public override void Clear()
{
    base.Clear();
    _buffer.Clear();
    _bufferSum = 0;
}

Testing constraints

  • Inherit BufferListTestBase (NOT TestBase)
  • Implement test interface matching increment interface:
    • IIncrementFromChainITestChainBufferList
    • IIncrementFromQuoteITestQuoteBufferList
  • Verify exact Series parity with bufferResults.IsExactly(seriesResults) (NOT Should().Be())
  • All 5 base class tests pass (incremental adds, batching, constructor chaining, Clear(), auto-pruning)

Required implementation

  • Source code: src/**/{IndicatorName}.BufferList.cs file exists
    • Inherits BufferList<TResult> and implements correct increment interface
    • Two constructors: primary + chaining via : this(...) => Add(quotes);
    • Uses BufferListUtilities.Update() or UpdateWithDequeue()
    • Clear() resets results and all internal buffers
  • Unit testing: tests/indicators/**/{IndicatorName}.BufferList.Tests.cs exists
    • Inherits BufferListTestBase and implements correct test interface
    • All 5 required tests from base class pass
    • Verifies equivalence with Series results

Anti-patterns to avoid

Manual buffer management (WRONG):

if (_buffer.Count == capacity) _buffer.Dequeue();
_buffer.Enqueue(value);

Use extension methods (CORRECT):

_buffer.Update(capacity, value);

Examples

  • Chain: src/e-k/Ema/Ema.BufferList.cs
  • Quote: src/s-z/Stoch/Stoch.BufferList.cs
  • Complex: src/a-d/Adx/Adx.BufferList.cs

See references/interface-selection.md for interface decision guidance.


Last updated: December 31, 2025