@pond-ts/financial API Reference
    Preparing search index...

    Function twiggsMoneyFlow

    • Twiggs Money Flow (Colin Twiggs) — Chaikin Money Flow rebuilt on the bar's true range and on Wilder's exponential smoothing:

      trueHigh = max(high, prevClose)      trueLow = min(low, prevClose)

      flow = volume · ((close − trueLow) − (trueHigh − close))
      / (trueHigh − trueLow)

      ${output} = wilder(flow, period) / wilder(volume, period)

      Appends one column, bounded −1 … +1 on real bars (the per-bar close location is, and this is a ratio of two smoothings of it against its own weight), undefined until the smoothing is seeded. Above zero is net accumulation, below zero net distribution — the same reading chaikinMoneyFlow gives, on a different measurement of the bar.

      Both studies are Σ(close-location · volume) / Σ volume. Twiggs' two corrections are exactly the two terms this package can name:

      1. The range is the TRUE range, max(high, prevClose) to min(low, prevClose) (trueRangeBoundsValues), not the bar's own high − low. A bar that gapped away from the previous close covers ground its own span does not show, and CMF scores such a bar as though the gap never happened — a gap-down bar that then closes at its own high reads +1 (maximum accumulation) on Chaikin's range and something much closer to neutral on Twiggs'. This is the same argument trueRangeValues makes for ATR over plain range, applied to a money flow.
      2. The averaging is exponential, not a flat window. CMF weights the twentieth bar back exactly as much as today's and then drops it off a cliff; Wilder's recursion decays it. That also means TMF has no window to fall out of: an interior gap ends the reading (below), where CMF recovers period bars later.

      The two are therefore different readings, not a reparametrisation. Measured on the package's oracle input at period 21, TMF and chaikinMoneyFlow({ period: 21 }) sit 0.1494 apart at their widest on a TMF spanning −0.0279 … 0.1493 (scripts/oracle/generate.py) — wider than the whole reading, on a fixture whose bars gap frequently. At period 5 the gap is 0.3514 on a range of −0.1629 … 0.3555.

      The corpus flags Twiggs Money Flow as F-AMBIG on the smoothing, and it is the real fork. This ships Wilder's exponential form — wilderValues, α = 1/period, seeded on the mean of the first period terms — which is the algorithm published on Twiggs' own site (Incredible Charts, Twiggs Money Flow), where the smoothing is described as an exponential moving average with the 1/n constant Wilder's indicators use. Two other forms circulate:

      • A window sum, Σ flow / Σ volume over period bars. That is chaikinMoneyFlow on the true range rather than Twiggs' study; measured on the oracle input at period 21 it sits 0.0706 away from what ships (on a range of −0.0279 … 0.1493), so the choice is visible rather than cosmetic, and the generator asserts the separation.
      • A span EMA, α = 2/(period+1). Same family, faster decay; a caller who wants it can smooth flow and volume themselves. It is not offered as an option here because "which exponential average" is not a knob this study has — it is which definition you are computing, and a maType option would quietly make one study into three.

      Bar 0 has no previous close, so it has no true range and no flow. The smoothing therefore starts at bar 1 and the first reading lands on bar period (one later than a plain window study's period − 1).

      The volume that goes into the denominator is blanked wherever flow is before it is smoothed. That is not tidiness: wilderValues steps its seed over a leading run of gaps, so a missing high on bar 1 would shift the numerator's seed window without shifting the denominator's, and the ratio would then be a numerator over period bars divided by a denominator over a different period bars. It is the #710 lesson (two smoothings of two columns must blank the same bars) and it is pinned by a test.

      • A zero smoothed volume → undefined. The division is at the output, so the guard is live: a window of genuinely zero-volume bars has nothing to weight by, and nothing forces the numerator to zero with it (a redirected volume can be negative on some bars and cancel). Without the guard the reading would be ±Infinity, which withColumn rejects outright.
      • A flat true range (trueHigh === trueLow — a halted bar that also did not move from the previous close) contributes 0 to the numerator and its volume to the denominator, exactly as clvValues' flat-bar rule says, pulling the reading toward zero.
      • An interior gap ends the reading, because Wilder's recursion has no state to carry across a hole — the same asymmetry atr and rsi have and chaikinMoneyFlow does not. A leading run of gaps only shifts the seed.
      • Invariant under scaling volume, and under any affine change of price — it is a ratio of a weighted mean of a bounded ratio; the price terms are differences, so a constant added to every price cancels in numerator and denominator alike (the previous close shifts with the bar). All three are pinned as property tests.

      Type Parameters

      • S extends SeriesSchema
      • const Output extends string = "tmf"

      Parameters

      Returns TimeSeries<
          readonly [S[0], ValueColumnsForSchema<S>, OptionalNumberColumn<Output>],
      >