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

    Function negativeVolumeIndex

    • Negative Volume Index (Paul Dysart, popularised by Norman Fosback, Stock Market Logic 1976) — a cumulative index that compounds a bar's return only when that bar's volume was lower than the previous bar's.

      NVI[0] = start                                   (1000 by convention)
      NVI[i] = volume[i] < volume[i−1]
      ? NVI[i−1] × (1 + (close[i] − close[i−1]) / close[i−1])
      : NVI[i−1]

      The premise is Dysart's: the "smart money" trades on quiet days and the crowd on busy ones, so the line built from quiet days alone is read as the informed side of the tape. positiveVolumeIndex is the same construction on the busy days.

      Appends one column (nvi by default). Like obv there is no period — there is no window to size — and no warm-up: bar 0 carries start.

      • A flat volume holds. volume[i] === volume[i−1] compounds on neither index. Fosback's rule is a strict comparison on each side, so an unchanged volume is neither a "down-volume" nor an "up-volume" bar. That is worth stating because the obvious implementation — < for NVI and >= for PVI — silently makes the two indices partition every bar and gives PVI a bar Fosback does not give it.
      • start is a base, not data. 1000 is Fosback's; some vendors use 100, and some chart a 0-based percent form (100 · (index/start − 1)), which is a different column — the index is multiplicative, so a 0 start would be 0 forever, and start rejects it. It scales the whole line, so the study is invariant to it in shape.
      • The return is a simple price return, close[i]/close[i−1] − 1, on whichever column is named — this is a ratio index, not a sum, so there is no × volume term anywhere (contrast priceVolumeTrend, which is the volume-weighted cousin).

      TA-Lib has no NVI/PVI, so the oracle is a pandas replication, with cases separating it from the two nearby misreadings: compounding on a flat volume, and compounding the wrong side.

      • Scale-invariant in both inputs. Multiplying every price by k leaves the index unchanged (the return is a ratio); multiplying every volume by k leaves it unchanged (only the comparison is read). Both are asserted as property tests.
      • A zero previous close makes the return undefined, and an index that cannot be continued reads undefined from that bar onwards rather than inventing a level. The guard is live because the division is at the output.
      • A missing close or volume re-bases the index. Per the K6 gap rule ([PND-SFOLD], kernels/fold.ts) the machine resets: the gap bar is undefined and the next complete bar restarts at start. That is a deliberate difference from obv, which propagates to the end, and the difference is what the level means. OBV accumulates volume — a quantity with units, where the distance between two points is the reading — so a hole makes every later level wrong. NVI accumulates returns from an arbitrary base, so re-basing after a hole loses only the base, and the shape from there on is exactly right. A caller who needs one continuous index across a hole fills before running it.

      Type Parameters

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

      Parameters

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