Skip to content

Chaining indicators

Chaining lets you calculate an indicator of indicators — for example an SMA of an ADX, or an RSI of OBV. Instead of feeding raw bars into a single indicator, you feed the results of one indicator into the next.

csharp
// RSI of On-Balance Volume
IReadOnlyList<RsiResult> results = bars
    .ToObv()
    .ToRsi(14);

You can also start a chain from a chosen price field with Use(CandlePart):

csharp
// EMA of the HL2 price (average of high and low)
IReadOnlyList<EmaResult> results = bars
    .Use(CandlePart.HL2)
    .ToEma(20);

How it works

Chaining works through the IReusable interface. Any result that implements IReusable exposes a single representative Value, which the next indicator consumes as its input series:

  • Chainable inputs — most indicators accept a reusable series, so they can take either raw bars or another indicator's results.
  • Chainable outputs — a result type is chainable only when it implements IReusable (it exposes a Value). Indicators that produce multiple primary outputs (e.g. bands or channels) may not be chainable as a source.

See Creating custom indicators to make your own indicators chainable.

Chaining in each style

Chaining is available in all three indicator styles; the concept is the same, but the mechanics differ:

  • Batch (Series) — chain extension methods fluently (bars.ToObv().ToRsi(14)). The standard, default approach.
  • Buffer lists — feed one buffer list's results into another as values arrive. Unlike the other styles, this chaining is orchestrated by you, not the library: you decide when to pass each result onward.
  • Stream hubs — subscribe one hub to another so chained indicators update automatically as new bars stream in.

See also