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

    Function priceRelative

    • Price Relative — the ratio of column to benchmark, bar by bar:

      ${output} = column / benchmark
      

      Appends one column, with no period and no warm-up: it is the only study in the package that reads a single row, so every row emits (bar 0 included) wherever both inputs exist. A rising line means column is outperforming, falling means the benchmark is — the level is arbitrary (it carries the two instruments' price units), which is why the line is read for its slope and why performanceIndex exists to normalise it against a starting point.

      ChartIQ lists this under two names — Price Relative and Relative Strength (comparative) — and they are one implementation, which is what ships here under the unambiguous name. Neither is Wilder's Relative Strength Index: rsi is a single-series momentum oscillator bounded 0..100, this is an unbounded two-series ratio, and the collision of names is the single most common confusion in the corpus. If you want RSI, call rsi.

      Join the benchmark in first and name its column:

      const wide = TimeSeries.joinMany([bars, spy.rename({ close: 'spy' })], {
      type: 'inner',
      });
      priceRelative(wide, { column: 'close', benchmark: 'spy' });

      See correlation's docstring for the reasoning (aligning two bar clocks is align/joinMany's job, not a study's). A missing benchmark column throws.

      • No TA-Lib function, so the oracle is a pandas replication, with the inverted ratio (benchmark / column) measured as the separation — the one substitution that leaves the curve's shape recognisable and every value wrong.
      • A zero benchmark reads undefined, and the guard is LIVE. Unlike the flat-window cases in correlation and beta, the numerator here is not forced to zero with the denominator, so 5 / 0 is Infinity — and withColumn throws on a non-finite value rather than recording it as a gap. The guard sits at the study's output, which is what makes it observable (the #703 rule: a guard upstream of a window kernel is absorbed and dies; one at the output is load-bearing). Unreachable on prices, reachable when benchmark is another study's output that crosses zero, and unit-tested there. A negative benchmark still produces a number — === 0, not <= 0, the percentChangeValues rule, because a ratio against a negative level is defined if unusual and clamping it would invent a rule.
      • Scale-EQUIVARIANT, not invariant. Multiplying column by k multiplies the reading by k; multiplying benchmark by k divides it by k. Both are pinned as property tests, as identities rather than as "the numbers changed" — this is the one study in the family that is not scale-invariant, and a test that asserted invariance would have passed on a study that had normalised the ratio away.
      • A missing cell in either column blanks that row and nothing else — a window kernel's recovery rule with a window of one.
      • benchmark must differ from column: the ratio would be 1 everywhere.

      Type Parameters

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

      Parameters

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