DaveSkender

indicator-catalog

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

Create and register indicator catalog entries for automation. Use for Catalog.cs files, CatalogListingBuilder patterns, parameter/result definitions, and PopulateCatalog registration.

Installation

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

Details

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

Usage

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

Verify installation:

skills list

Skill Instructions


name: indicator-catalog description: Create and register indicator catalog entries for automation. Use for Catalog.cs files, CatalogListingBuilder patterns, parameter/result definitions, and PopulateCatalog registration.

Indicator catalog development

File structure

  • Catalog: src/{category}/{Indicator}/{Indicator}.Catalog.cs
  • Location: Same directory as {Indicator}.Models.cs

Builder pattern

public static partial class Ema
{
    /// <summary>
    /// EMA Common Base Listing
    /// </summary>
    internal static readonly IndicatorListing CommonListing =
        new CatalogListingBuilder()
            .WithName("Exponential Moving Average")
            .WithId("EMA")
            .WithCategory(Category.MovingAverage)
            .AddParameter<int>("lookbackPeriods", "Lookback Period",
                description: "Number of periods for the EMA calculation",
                isRequired: true, defaultValue: 20, minimum: 2, maximum: 250)
            .AddResult("Ema", "EMA", ResultType.Default, isReusable: true)
            .Build();

    /// <summary>
    /// EMA Series Listing
    /// </summary>
    internal static readonly IndicatorListing SeriesListing =
        new CatalogListingBuilder(CommonListing)
            .WithStyle(Style.Series)
            .WithMethodName("ToEma")
            .Build();

    /// <summary>
    /// EMA Stream Listing
    /// </summary>
    internal static readonly IndicatorListing StreamListing =
        new CatalogListingBuilder(CommonListing)
            .WithStyle(Style.Stream)
            .WithMethodName("ToEmaHub")
            .Build();

    /// <summary>
    /// EMA Buffer Listing
    /// </summary>
    internal static readonly IndicatorListing BufferListing =
        new CatalogListingBuilder(CommonListing)
            .WithStyle(Style.Buffer)
            .WithMethodName("ToEmaList")
            .Build();
}

Method naming conventions

StylePatternExample
SeriesTo{IndicatorName}ToEma
StreamTo{IndicatorName}HubToEmaHub
BufferTo{IndicatorName}ListToEmaList

Critical: .WithMethodName() must be in style-specific listings, NOT in CommonListing.

Required parameter patterns

  • Use AddParameter<T>() for basic types (int, double, bool)
  • Use AddEnumParameter<T>() for enum types
  • Use AddDateParameter() for DateTime parameters
  • Use AddSeriesParameter() for IReadOnlyList<T> where T : IReusable
  • MUST set minimum and maximum for all numeric parameters

Required result patterns

  • dataName MUST match property name in Models file exactly
  • Set isReusable: true ONLY for property mapping to IReusable.Value
  • ISeries models: ALL results MUST have isReusable: false
  • Exactly ONE result with isReusable: true per IReusable indicator

Categories

CategoryExamples
MovingAverageEMA, SMA, HMA, TEMA
OscillatorRSI, Stochastic, MACD
PriceChannelBollinger Bands, Keltner
TrendADX, Aroon, Parabolic SAR
VolumeOBV, Chaikin Money Flow
VolatilityATR, Standard Deviation

Registration

Add to src/_common/Catalog/Catalog.Listings.cs in PopulateCatalog():

_catalog.Add(Ema.SeriesListing);
_catalog.Add(Ema.StreamListing);
_catalog.Add(Ema.BufferListing);

Register in alphabetical order by indicator name.

Testing

Create tests/indicators/{folder}/{Indicator}/{Indicator}.Catalog.Tests.cs:

[TestClass]
public class EmaCatalogTests : TestBase
{
    [TestMethod]
    public void EmaSeriesListing()
    {
        var listing = Ema.SeriesListing;
        listing.Name.Should().Be("Exponential Moving Average");
        listing.Style.Should().Be(Style.Series);
        listing.MethodName.Should().Be("ToEma");
    }
}

Prohibited patterns

  • .WithMethodName() in CommonListing (MUST be in style-specific listings)
  • ❌ Wrong indicator method name (breaks extension method discovery)
  • isReusable: true for ISeries models (violates interface contract)
  • ❌ Multiple isReusable: true results (ambiguous Value mapping)

Last updated: December 31, 2025