UNPKG

openalgo-charts

Version:

From-scratch, dependency-free canvas charting engine for OpenAlgo: professional-grade interactive rendering, advanced on-chart trading, and a one-call widget tier that adds the toolbar, drawing rail, dialogs and shortcuts.

1,164 lines 61.1 kB
import { IndicatorDescriptor, ChartDataContext, IndicatorSettings, Bar, IndicatorInput, IndicatorPlot, IndicatorLevel } from 'openalgo-charts';

declare const SMA: IndicatorDescriptor;
declare const WMA: IndicatorDescriptor;
declare const EMA: IndicatorDescriptor;
declare const BOLLINGER: IndicatorDescriptor;
declare const VWAP: IndicatorDescriptor;
declare const SUPERTREND: IndicatorDescriptor;
declare const PARABOLIC_SAR: IndicatorDescriptor;
declare const ICHIMOKU: IndicatorDescriptor;
/**
 * HalfTrend — a trend-following level that only moves against the trend once
 * the opposing side of the range genuinely gives way, so it holds flat through
 * noise where a moving average would wobble.
 *
 * Two state machines run at once. `trend` is what is drawn; `nextTrend` is which
 * flip is currently *armed*. While a down-flip is armed the indicator tracks the
 * running maximum of the `amplitude`-bar low; the flip only fires when the mean
 * high drops under that maximum **and** the bar closes below the previous bar's
 * low. The up-flip is the mirror. Requiring both a mean crossing and a close
 * beyond the prior bar's extreme is what keeps the level still.
 *
 * On a flip the new level starts from the level the other side ended on, which
 * is why the line steps rather than jumping to price. `channelDeviation` half-ATR
 * bands ride the level as a channel, and the flip bar is marked half an ATR
 * inside the channel.
 *
 * Original implementation written from the algorithm's published behaviour, per
 * ARCHITECTURE.md §0.1 — not ported from any third-party source.
 */
declare const HALFTREND: IndicatorDescriptor;

declare const RSI: IndicatorDescriptor;
declare const MACD: IndicatorDescriptor;
declare const STOCHASTIC: IndicatorDescriptor;
declare const ADX: IndicatorDescriptor;
declare const CCI: IndicatorDescriptor;
declare const MFI: IndicatorDescriptor;
declare const ATR: IndicatorDescriptor;
/**
 * CM Williams Vix Fix — a synthetic VIX from price alone.
 *
 * `wvf` is how far the current low sits below the highest close of the lookback,
 * as a percentage: a spike means capitulation. The signal is not the level but
 * the *breakout* — `wvf` piercing its own Bollinger upper band, or the top
 * percentile of its recent range — so the histogram carries two colours and the
 * bands are what it is measured against.
 */
declare const WILLIAMS_VIX_FIX: IndicatorDescriptor;

/**
 * Tier-1 volume indicators, computed from the chart's own OHLCV.
 * Part of the lazy `openalgo-charts/indicators` tier.
 */

declare const VOLUME: IndicatorDescriptor;
declare const OBV: IndicatorDescriptor;
declare const ADL: IndicatorDescriptor;

/**
 * The source is hard-coded to `close` in the reference (`source = close`,
 * not an `input`), so there is no source setting to expose.
 */
declare const ALMA: IndicatorDescriptor;
/**
 * `2 * ema - ema(ema)`. The second pass runs over a series that is already NaN
 * for its own warmup, which is what pushes the first plotted bar out to
 * `2 * length - 2`, see `emaOfGapped`.
 */
declare const DEMA: IndicatorDescriptor;
declare const HMA: IndicatorDescriptor;
declare const ENVELOPE: IndicatorDescriptor;
declare const DONCHIAN: IndicatorDescriptor;
/**
 * Two stacked extremes: an ATR-padded high/low band, then the running extreme of
 * *that* over `q` bars, which is what keeps each stop monotone through a pullback.
 * The second pass is NaN-strict (`extremeStrict`), so nothing prints until the
 * whole `q`-bar window is past the ATR warmup, bar `p + q - 2`.
 *
 * The long stop is padded off the lowest **low**, which is the published
 * definition and what the short stop mirrors. The reference implementation takes
 * both extremes over the high series (it never reads a low at all), so the two
 * long stops disagree by roughly the average high-low range while the short
 * stops agree to the last bit. Measured, deliberate, and left alone: matching it
 * would move a stop line for every existing user onto a reading that the
 * published definition of this stop contradicts.
 */
declare const CHANDE_KROLL_STOP: IndicatorDescriptor;
/**
 * The reference imports an external helper library and calls `an external `chandelier()` helper`, whose
 * body is not in the reference file. This is the published definition of that stop:
 * the highest high of the window pulled down by `mult` ATRs, and its mirror.
 */
declare const CHANDELIER_EXIT: IndicatorDescriptor;
/**
 * Bands centred on the regression **endpoint**, not on a moving average of price:
 * the fitted line's value at the newest bar of the window, pushed out by
 * `errors` standard errors, and only then smoothed. The middle plot is that
 * smoothed endpoint, so it is not the same line as a plain regression curve.
 * All three legs are smoothed independently, which is why the first bar of each
 * lands at `(periods - 1) + (averagePeriods - 1)`.
 */
declare const STANDARD_ERROR_BANDS: IndicatorDescriptor;
/**
 * Two independent legs, a mean of highs and a mean of lows, each with its own
 * length and its own plot-time displacement. Not a mean of the close with a
 * spread around it, and simple throughout: there is no smoothing method here.
 */
declare const MA_CHANNEL: IndicatorDescriptor;
/**
 * Hull Suite: one hull average plotted twice, the second copy displaced two
 * bars. The band is therefore the average against its own recent past rather
 * than a second study, and "the first plot is above the second" is exactly the
 * rising condition, which is what lets a plain two-colour fill carry the trend.
 *
 * Three variations are offered because they trade lag against smoothness
 * differently, and two quirks of the published definition are preserved rather
 * than tidied: the Thma branch is handed half the length the other two get, and
 * the intermediate lengths truncate while only the outer square root rounds.
 * Anyone reading this beside the study they already run needs the same line.
 *
 * Deliberately not offered, because nothing here could back them: a line
 * thickness input (`style.lineWidth` is static and there is no width settings
 * key), a band transparency input (`opacity` is a fixed number on the fill spec,
 * not a settings key), and a higher-timeframe mode (`calc` is handed the chart's
 * own bars and has no way to request another resolution).
 */
declare const HULL_SUITE: IndicatorDescriptor;
declare const OVERLAY_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Aroon — how recently the window made its extreme, as a percentage of the
 * window.
 *
 * `highestbars` answers "how many bars back is the high" as a **negative
 * offset**, `0` meaning the current bar. The whole study is that offset mapped
 * onto 0..100, so the sign convention is load-bearing: a fresh high gives
 * `100 * (0 + length) / length` = exactly 100, and a high at the far edge of
 * the window gives 0. Note the window is `length + 1` bars, not `length` —
 * the reference counts the gaps between bars, not the bars.
 */
declare const AROON: IndicatorDescriptor;
/**
 * Aroon Oscillator — Aroon Up minus Aroon Down, so a single line through zero.
 *
 * The reference colours the *line* by sign and shades it to a hidden zero plot. This
 * library's line renderer has no per-bar colour (only histogram and column
 * honour `colorBy`), so the sign is carried by the band instead, which is what
 * actually reads on a chart. `zero` is a value column with no plot, exactly as
 * the reference `display.none` zero plot is: it exists only to give the fill a
 * second edge.
 */
declare const AROON_OSCILLATOR: IndicatorDescriptor;
/**
 * Awesome Oscillator — the gap between a fast and a slow midpoint average.
 *
 * The reference hard-codes 5 and 34 and exposes no inputs, so neither does this: the
 * two periods are the definition of the study, not a preference. Colour is the
 * second half of the signal — green while the histogram is building against the
 * previous bar, red while it is fading — and that is a per-bar decision, hence
 * `colorBy` on one column rather than two plots that would each carry holes.
 * On the first printed bar the previous value is `na`, and the reference `na <= 0` is
 * false, so it starts green.
 */
declare const AWESOME_OSCILLATOR: IndicatorDescriptor;
/**
 * Balance of Power — where the close finished inside the bar's range, relative
 * to where it opened. No smoothing and no inputs; the reference is one line.
 *
 * A zero-range bar makes this 0/0, which is `na` in the reference, so it draws a gap
 * rather than a spike.
 */
declare const BALANCE_OF_POWER: IndicatorDescriptor;
/**
 * Chande Momentum Oscillator — the same up/down split as RSI, but as a plain
 * ratio of summed moves instead of a Wilder average, so it swings the full
 * -100..100 rather than compressing towards the middle.
 *
 * `change` is `na` on the first bar, so the first published value is the one
 * backed by `length` real changes: index `length`, not `length - 1`. The sums
 * are therefore taken over the series from bar 1 onwards, which also keeps the
 * running total in `rollingSum` from ever touching a NaN — one NaN would poison
 * it for the rest of the series, because subtracting it back out when it leaves
 * the window does not undo it.
 */
declare const CHANDE_MOMENTUM: IndicatorDescriptor;
/**
 * Coppock Curve — a weighted average of two rates of change, one long and one
 * short. Both `roc` terms must have a value before the WMA has anything to
 * chew on, so the first print lands at `longRoCLength + wmaLength - 1`.
 */
declare const COPPOCK_CURVE: IndicatorDescriptor;
/**
 * Detrended Price Oscillator — price against a moving average taken from half a
 * cycle ago, which strips the trend and leaves the cycle.
 *
 * `barsback = period/2 + 1` indexes a series, so it has to be a whole number:
 * the reference integer division truncates, and this floors, which agrees for both odd
 * and even lengths (21 -> 11, 20 -> 11).
 *
 * The `centered` mode is the awkward one. the reference computes `close[barsback] - ma`
 * and then draws it with `offset = -barsback`, i.e. shifted back in time.
 * Plots here have no per-plot offset, so the shift is folded into the column
 * itself: the value drawn at bar `i` is the one the reference computed on bar
 * `i + barsback`, which reduces to `close[i] - ma[i + barsback]`. The picture
 * matches the reference platform exactly, including the fact that the centered line stops
 * `barsback` bars short of the right edge. The non-centered mode needs no such
 * trick and is implemented straight.
 */
declare const DPO: IndicatorDescriptor;
/**
 * Fisher Transform — squash the position of `hl2` inside its recent range into
 * -1..1, then run it through the inverse hyperbolic tangent so the tails
 * stretch out and turning points become sharp.
 *
 * Two recursions, each carrying two thirds / one half of the previous bar. The
 * clamp to +/-0.999 is not cosmetic: at exactly +/-1 the log blows up, so the
 * the reference `round_` is what keeps the series finite. Both recursions read the
 * previous bar through `nz`, so a missing previous value counts as 0 — which
 * happens on the first printed bar and again after any bar that produced `na`.
 * A flat window (`high_ == low_`) is not one of those: the range divide is
 * floored at 0.001, so the ratio is 0, the bar still prints, and both
 * recursions carry on.
 *
 * `Trigger` is simply `fish1[1]`, so it lags Fisher by exactly one bar.
 */
declare const FISHER_TRANSFORM: IndicatorDescriptor;
/**
 * The Connors "updown" streak: how many consecutive bars price has risen or
 * fallen, signed. An unchanged close resets it to 0; a rise continues a
 * positive run or starts a new one at +1; a fall mirrors that.
 *
 * Exported because it is the one piece of Connors RSI worth testing on its own
 * — the rest is three well-known series averaged.
 *
 * Bar 0 is deliberately -1, not 0. In the reference `close == close[1]` and
 * `close > close[1]` are both false against `na`, so the first bar falls into
 * the down branch with `nz(ud[1])` reading 0, which yields -1.
 */
declare function connorsStreak(values: readonly number[]): number[];
/**
 * Connors RSI — the mean of three unrelated readings of the same bar: how
 * overbought price is (a short RSI), how stretched the up/down streak is (an
 * RSI of the streak itself), and where today's one-bar return sits in its own
 * recent distribution (a percent rank).
 *
 * Averaging only works if all three have a value, and the percent rank is the
 * slow one: `roc(close, 1)` is `na` on bar 0, and `percentrank` compares
 * the current value against the previous `lenroc` of them, so the first
 * complete reading is at index `lenroc + 1` — 101 on defaults. Running the rank
 * over the series from bar 1 is what keeps that `na` out of the window.
 */
declare const CONNORS_RSI: IndicatorDescriptor;
declare const OSCILLATOR_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Bollinger Bands %b: where the source sits inside its own bands, rescaled so
 * the lower band is 0 and the upper is 1. Unbounded on purpose: the reading
 * only becomes interesting once it leaves 0..1, which is why the pane declares
 * no fixed range.
 */
declare const BOLLINGER_PERCENT_B: IndicatorDescriptor;
/**
 * Bollinger BandWidth: the band spread as a percentage of the basis, so it is
 * comparable across instruments and across price levels.
 *
 * The two companion plots are rolling extremes **of the bandwidth itself**, not
 * of price: they turn "is this narrow?" from a judgement call into a comparison
 * against the last N bars of the same series.
 */
declare const BOLLINGER_BANDWIDTH: IndicatorDescriptor;
/**
 * BBTrend: a short and a long Bollinger set compared band for band. When the
 * short set's lower band has pulled further from the long set's lower band than
 * the two upper bands have separated, the short-term range is expanding
 * downward and the reading is negative; the reverse is positive. Normalised by
 * the short basis so it reads as a percentage.
 */
declare const BB_TREND: IndicatorDescriptor;
/**
 * Choppiness Index: how much ground the bar-by-bar travel covers compared with
 * the net range it produced. A market that retraces everything spends the full
 * `length` bars of true range inside one range and reads near 100; a trend
 * covers the same range in a fraction of the travel and reads low.
 *
 * the reference writes the numerator as `sum(atr(1), length)`. `atr(1)` is
 * `rma(tr, 1)`, which is the true range itself, so this is a plain rolling sum
 * of true range, including bar 0, where the reference true range is `high - low`.
 */
declare const CHOPPINESS_INDEX: IndicatorDescriptor;
/**
 * Historical Volatility: the annualised standard deviation of log returns.
 *
 * the reference derives the annualisation divisor from the chart's timeframe:
 * `per = timeframe.isintraday or (timeframe.isdaily and multiplier == 1) ? 1 : 7`.
 * A descriptor here is handed bars and settings and nothing else. It cannot
 * see the timeframe, and guessing one from bar spacing would silently change
 * the plot on a gappy or irregular series. So `per` is an input: leave it at 1
 * for intraday and daily charts, set it to 7 for weekly and above, which is
 * exactly the branch the reference takes.
 */
declare const HISTORICAL_VOLATILITY: IndicatorDescriptor;
/**
 * Average Daily Range: the mean high-to-low range over `length` bars. "Daily"
 * is the reference platform's name for it; the calculation is per bar, whatever the chart
 * timeframe is.
 */
declare const AVERAGE_DAILY_RANGE: IndicatorDescriptor;
/**
 * Chop Zone: the slope of a 34-bar EMA, read as an angle and bucketed into a
 * nine-colour ladder from turquoise (steep rise) through yellow (flat) to dark
 * red (steep fall).
 *
 * The plot itself is a constant 1: every bar is the same height and all the
 * information is in the colour. That is not a stylistic choice we can improve
 * on: it is the study. The slope is made comparable across instruments by
 * `span`, which rescales it against the 30-bar range, so the angle means the
 * same thing on a 20-rupee stock and a 20000-point index.
 *
 * `angle` is returned as an unplotted column so `colorBy` can read it; the
 * ladder is a property of the bar, not of the value being plotted.
 */
declare const CHOP_ZONE: IndicatorDescriptor;
/**
 * Chaikin Volatility: the rate of change of a smoothed high-to-low range, so it
 * answers "is the bar getting wider?" rather than "how wide is it?".
 *
 * The smoother is an EMA, not an SMA: an average of ranges reacts to a single
 * wide bar for `periods` bars and then drops it in one step, which prints a
 * spurious second move on the rate of change. Zero is the neutral reading, and
 * a zero denominator (a period of perfectly flat bars) has no rate of change to
 * report, so it stays a gap rather than becoming Infinity.
 */
declare const CHAIKIN_VOLATILITY: IndicatorDescriptor;
/**
 * Standard Deviation: the population standard deviation of the close over
 * `periods` bars, scaled by `deviations` so it can be read as the same band
 * width a Bollinger set would draw.
 */
declare const STANDARD_DEVIATION: IndicatorDescriptor;
/**
 * Standard Error: the residual spread of the closes about the least-squares
 * line fitted through them, which is what makes it an *error* rather than a
 * deviation. Two degrees of freedom go into the fitted slope and intercept, so
 * the divisor is `length - 2` and the input cannot go below 3.
 */
declare const STANDARD_ERROR: IndicatorDescriptor;
declare const VOLATILITY_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Built-in volume studies, ported to descriptor form.
 * Part of the lazy `openalgo-charts/indicators` tier.
 *
 * Each `calc` reproduces the published reference definition numerically, warmup gaps
 * included, so a plot here lines up bar for bar with the same study on
 * the reference platform. Where the published reference definitions differ from this library's own
 * helpers the reference-compatible variant in `./calc` is used: `smaSeededEma`, never the
 * base bundle's `ema`, because the two seed from different windows and would
 * disagree for the first `length` bars of every plot that touches them.
 */

/**
 * Chaikin Money Flow — the money-flow term summed over the window and
 * normalised by the volume traded in that same window, so the reading is a
 * bounded -1..+1 share of participation rather than a raw quantity.
 */
declare const CHAIKIN_MONEY_FLOW: IndicatorDescriptor;
/**
 * Chaikin Oscillator — a MACD of the A/D line.
 *
 * The two EMAs run over the *running total* of the money-flow term (the reference
 * `accdist`), not the per-bar term, so what the oscillator measures is
 * acceleration in accumulation rather than the flow itself.
 */
declare const CHAIKIN_OSCILLATOR: IndicatorDescriptor;
/**
 * Ease of Movement — how far the midpoint travelled per unit of volume, scaled
 * by the bar's range and by a divisor that only exists to bring the number into
 * a readable magnitude.
 */
declare const EASE_OF_MOVEMENT: IndicatorDescriptor;
/**
 * Elder Force Index — the bar's price change weighted by the volume behind it,
 * smoothed. Direction and conviction in one number: a large move on thin
 * volume scores less than a small move the whole market took part in.
 */
declare const ELDER_FORCE_INDEX: IndicatorDescriptor;
/**
 * Net Volume: the bar's own volume, signed by the direction its close took.
 *
 * There is no warmup gap. Bar 0 has no previous close, so neither the up test
 * nor the down test can hold and the reference falls through to its zero arm;
 * an unchanged close lands on that same arm later in the series. Blanking bar 0
 * instead would put a hole in a series that is defined on every other bar.
 */
declare const NET_VOLUME: IndicatorDescriptor;
/** Every the reference platform volume built-in in this module, in picker order. */
declare const FLOW_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Kaufman's Adaptive Moving Average: an EMA whose smoothing constant is chosen
 * bar by bar from how *directed* the recent move was.
 *
 * The efficiency ratio divides the net distance travelled over `erLength` bars by
 * the total path walked to get there. A clean trend covers ground in a straight
 * line and scores near 1, which pulls the smoothing toward the fast alpha and the
 * average onto price; chop retraces itself, scores near 0, and the average all but
 * stops. Squaring the interpolated alpha is what makes that transition abrupt
 * rather than linear, so KAMA sits flat through noise instead of drifting.
 *
 * The reference delegates to `an external `kama()` helper`, whose body is not in the file, so
 * this follows Kaufman's published definition. It first prints at `erLength`, the
 * earliest bar where both legs of the ratio exist, seeded there on the source
 * itself, because there is no prior average to carry forward.
 */
declare const KAMA: IndicatorDescriptor;
/**
 * Keltner Channels: a moving average with volatility rails, where the rail width
 * is a range measure rather than a standard deviation. That is the whole point of
 * the study: Bollinger's bands widen on *dispersion of closes*, Keltner's on how
 * much ground each bar actually covers, so the two disagree exactly when a market
 * gaps or trends in one direction without spreading its closes out.
 *
 * Three rail sources are offered because they answer different questions. ATR (the
 * default) smooths the range over its own `atrlength`, so the rails breathe slowly.
 * True Range uses the raw bar, so a single wide bar throws the rails out on that
 * bar alone. Range is Wilder-smoothed high-minus-low over the channel `length`,
 * ignoring gaps entirely. Each has its own warmup, and the plotted band starts at
 * whichever of the rail and the basis is slower.
 */
declare const KELTNER_CHANNEL: IndicatorDescriptor;
/**
 * Least Squares Moving Average: the endpoint of a least-squares line fitted over
 * the last `length` bars, so unlike an SMA it has no lag against a straight trend:
 * fit a line to a line and you get the line back.
 *
 * `offset` steps back down that same fitted line rather than re-fitting, which is
 * why it can shift the plot without changing its shape. See the x-axis convention
 * on `linreg` in `./calc`: x is 0 at the oldest bar of the window.
 */
declare const LSMA: IndicatorDescriptor;
/**
 * Klinger Oscillator: volume signed by the direction of the typical price, then
 * read as a MACD-style spread of two EMAs. Signing is what separates it from a
 * plain volume study: a heavy bar only counts as accumulation if `hlc3` actually
 * rose, so churn at an unchanged price nets out instead of registering as force.
 *
 * Two chained warmups stack here. The slow leg cannot print before bar 54, so the
 * spread cannot either; the signal EMA then runs over a series that is `na` up to
 * that point and the reference re-seeds it from an SMA, pushing its first bar a further
 * `KLINGER_SIGNAL - 1` out. See `emaOfGapped`.
 */
declare const KLINGER_OSCILLATOR: IndicatorDescriptor;
/**
 * Know Sure Thing: four rate-of-change readings taken over lengthening horizons,
 * each smoothed, then summed with weights 1/2/3/4 so the slowest cycle dominates.
 * The point is that a single ROC is a statement about one horizon; KST asks
 * whether short, medium, and long momentum agree, and weights the answer toward
 * the horizon least likely to be noise.
 *
 * Every term carries its own warmup and the sum is only real once the slowest one
 * is. With the defaults that is bar 44, `roclen4 + smalen4 - 1`. The signal SMA
 * then runs over a series with that gap in front of it, so it starts `siglen - 1`
 * bars later again; `sma` in `./calc` refuses any window holding a warmup slot,
 * which is what makes both boundaries fall where the reference puts them.
 */
declare const KNOW_SURE_THING: IndicatorDescriptor;
/**
 * Linear Regression Slope: the gradient of the least-squares line fitted over the
 * last `periods` closes, in price per bar.
 *
 * It asks a different question from LSMA, which plots where that same line ends.
 * Dropping the level and keeping only the gradient is what lets the study say
 * that an advance is still an advance but no longer as steep, at a bar where
 * price itself is making a new high. Zero is the whole reading: above it the fit
 * rises, below it the fit falls.
 *
 * The x axis is unit-spaced and the reference scales the result by nothing, so
 * the answer is per bar rather than per window. Only that spacing matters: a
 * least-squares slope is unchanged by shifting x, so running x from 1 to
 * `periods` (the reference's own convention, newest bar highest) and running it
 * from 0 give the identical number.
 */
declare const LINREG_SLOPE: IndicatorDescriptor;
declare const ADAPTIVE_INDICATORS: readonly IndicatorDescriptor[];

/**
 * `close` is hard-coded in the reference (`sma(close, ...)`, not an
 * `input`), so there is no source setting to expose.
 *
 * The long length defaults to 26, not 21: the reference pairs 9 against 26. A
 * saved chart that never set the length explicitly draws a slower line now.
 */
declare const MA_CROSS: IndicatorDescriptor;
/**
 * McGinley Dynamic — an average whose smoothing constant is itself a function of
 * how far price has run from the line, so it tightens in a trend and loosens in
 * a range instead of lagging by a fixed number of bars.
 *
 * Recursive, and the reference seeds it from `ema(source, length)` for as long as its
 * own previous value is `na`: the first printed bar is therefore `length - 1`,
 * where the EMA first prints, and the recursion takes over from the bar after.
 * `close` is hard-coded in the reference (`source = close`), so there is no
 * source setting.
 */
declare const MCGINLEY_DYNAMIC: IndicatorDescriptor;
/**
 * Median — the nearest-rank 50th percentile of the source, banded by ATR and
 * shaded against its own EMA. The percentile is a real member of the window
 * rather than an interpolation (see `percentileNearestRank`), so on an
 * even-length window it is the upper of the two middles, not their mean.
 *
 * The EMA is chained onto the percentile series, so it inherits that series'
 * warmup and first prints at `2 * length - 2` — see `emaOfGapped`.
 */
declare const MEDIAN: IndicatorDescriptor;
/**
 * Moving Average Ribbon — four independent averages on one overlay, so the
 * spacing between them reads as trend strength and their order as trend
 * direction. Every lane picks its own kernel, source, and length.
 *
 * the reference hides a lane by setting `display.none` on the plot; here a hidden lane
 * returns an all-null column, which draws nothing and keeps autoscale clean.
 */
declare const MA_RIBBON: IndicatorDescriptor;
/**
 * Triple EMA — `3 * (ema1 - ema2) + ema3`, which cancels the lag of a linear
 * trend exactly rather than merely reducing it.
 *
 * Three chained EMAs, each running over a series that is already `na` for its
 * own warmup, so the first printed bar is `3 * length - 3` and not `length - 1`
 * — see `emaOfGapped`. `close` is hard-coded in the reference, so there is no
 * source setting.
 */
declare const TEMA: IndicatorDescriptor;
/**
 * Time Weighted Average Price — the running mean of the source since the anchor,
 * the volume-blind sibling of VWAP. Where VWAP asks what the average traded
 * price was, TWAP asks what the average quoted price was, so a thin bar counts
 * for exactly as much as a heavy one.
 *
 * Anchor substitution: the reference takes an `input.timeframe` (default `1D`) and resets
 * on `timeframe.change(anchor)`, which needs a resolution resolver a chart
 * library does not have. The `session` option resets on the exchange's own
 * trading day, read back from the bar gaps exactly as the VWAP descriptor
 * anchors, and `continuous` never resets. The option used to be labelled
 * "Session (IST day)"; it names no zone now because it hardcodes none.
 */
declare const TWAP: IndicatorDescriptor;
/**
 * Volume Weighted Moving Average — an SMA whose window is weighted by volume,
 * so the bars that actually traded set the level. Identical to an SMA when
 * volume is flat, and `na` on any window whose volume sums to zero, which is
 * what a feed with no volume produces.
 */
declare const VWMA: IndicatorDescriptor;
/**
 * Williams Alligator — three Wilder-smoothed medians of differing speed, each
 * displaced forward in time. The lines braid when the market has nothing to say
 * and fan out in order once a trend takes hold.
 *
 * the reference `smma` is `na(smma[1]) ? sma(src, length) : (smma[1] * (length - 1)
 * + src) / length`, which is Wilder's RMA to the letter, so `rma` reproduces it
 * exactly and first prints at `length - 1`.
 *
 * Lengths default to 21 / 13 / 8, not to Williams' original 13 / 8 / 5: the
 * reference runs the slower set, and the offsets 8 / 5 / 3 are shared by both,
 * so only the smoothing lengths move. A saved chart that never set them draws
 * three slower lines now.
 *
 * The three plots carry `offset = 8 / 5 / 3`. A plot offset is not available
 * per-plot here, so the displacement is applied to the values instead: the value
 * computed on bar `i` is returned in slot `i + offset`, which leaves `offset`
 * leading nulls and puts the shifted tail in the last `offset` slots. A line
 * therefore first prints at `length - 1 + offset`.
 */
declare const ALLIGATOR: IndicatorDescriptor;
/**
 * Smoothed Moving Average, Wilder's smoother over a plain price source. Its
 * alpha is `1 / length` where an EMA of the same length uses `2 / (length + 1)`,
 * so it lags further and turns only once a run of closes has genuinely shifted
 * the level, which is the point: it is the noise filter, not the fast line.
 *
 * The reference `smma` is the recursion `rma` already implements, seeded from
 * the simple average of the first `length` values, so it first prints at
 * `length - 1` and needs no code of its own here.
 */
declare const SMMA: IndicatorDescriptor;
/**
 * T3 Average, that generalised double average applied three times over. The
 * result reads as smooth as a long moving average while turning close to as
 * early as a short one, which no single exponential average of either length
 * does.
 *
 * Warmup is the thing to get right here, and it is deeper than the length
 * suggests. One layer is two chained averages, and the layers nest three deep,
 * so the longest term is six averages of averages. Each is chained onto a series
 * that is already `na` for its own warmup and so starts `length - 1` bars after
 * the one it reads (see `emaOfGapped`), which puts the first printed bar at
 * `6 * (length - 1)`: index 24 at the default length of 5, not index 4.
 *
 * Highlighting is a colour on one line, not a second plot: the line is
 * continuous either way and only its paint changes, so a break in the colour
 * must not become a break in the series.
 */
declare const T3: IndicatorDescriptor;
declare const AVERAGE_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Momentum: the rawest reading there is, today's price against the price `len`
 * bars ago. No smoothing, no normalisation, so the scale is the instrument's
 * own and only the sign and the slope carry meaning.
 */
declare const MOMENTUM: IndicatorDescriptor;
/**
 * Rate Of Change: the same comparison as Momentum, expressed as a percentage of
 * the older price so readings are comparable across instruments and across time.
 *
 * A zero reference price makes the ratio undefined, which is drawn upstream as a
 * gap rather than as an infinite spike; the `roc` helper already returns NaN.
 */
declare const ROC: IndicatorDescriptor;
/**
 * Percentage Price Oscillator: MACD rewritten as a percentage of the slow
 * average, so the histogram of a 20 dollar stock and a 2000 dollar index can be
 * read on the same axis.
 *
 * Both the oscillator and its signal take a selectable EMA/SMA shape, and the
 * signal is a MA of the PPO rather than of price, so it inherits the PPO's own
 * warmup on top of its own: on defaults the oscillator prints from bar 25 and
 * the signal and histogram from bar 33.
 */
declare const PPO: IndicatorDescriptor;
/**
 * TRIX: the one-bar rate of change of a triple-smoothed log price.
 *
 * Working in logs is what makes the output a pure percentage rate (scaled by
 * 10000, so a reading of 100 is one percent per bar) independent of price
 * level, and three EMAs in series strip nearly everything that is not the
 * underlying trend, which is why it crosses zero so cleanly and so late.
 *
 * That lateness is the cost: each EMA starts `length - 1` bars after its input,
 * and `change` adds one more, so the first print is at `3 * length - 2`
 * (bar 52 on the default 18).
 */
declare const TRIX: IndicatorDescriptor;
/**
 * True Strength Index: the double-smoothed one-bar change divided by the
 * double-smoothed size of that change.
 *
 * Dividing by the smoothed magnitude is what bounds the study to -100..100 and
 * makes it read as "what fraction of recent movement went one way": a run of
 * unbroken up bars gives exactly +100 because the numerator and denominator are
 * then the same series.
 */
declare const TSI: IndicatorDescriptor;
/**
 * SMI Ergodic Indicator: Blau's Ergodic, which is TSI plotted against its own
 * EMA signal. Same maths as True Strength Index, different default lengths (20
 * and 5 rather than 25 and 13), so it turns much faster.
 *
 * The source script draws no horizontal lines here, and none are declared:
 * adding a zero line would be a nicer chart but a different one.
 */
declare const SMI_ERGODIC_INDICATOR: IndicatorDescriptor;
/**
 * SMI Ergodic Oscillator: the gap between the Ergodic and its signal, drawn as
 * a histogram. The same relationship the Indicator shows as two lines, reduced
 * to the one number that crosses zero.
 */
declare const SMI_ERGODIC_OSCILLATOR: IndicatorDescriptor;
/**
 * Stochastic Momentum Index: Stochastic measured from the *midpoint* of the
 * range instead of from its low.
 *
 * That single change is what re-centres the study on zero and lets it say which
 * half of the range price is in, rather than only how high in it. Both the
 * distance from the midpoint and the range itself are double-smoothed before
 * being divided, which is why the reading is far steadier than a raw %K.
 *
 * A bare `highest(lengthK)` / `lowest(lengthK)` upstream defaults to `high` and
 * `low`, not to the source of the surrounding expression, so the window really
 * is a high/low range and not a close-only one.
 */
declare const SMI: IndicatorDescriptor;
declare const STRENGTH_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Negative Volume Index — the price path compounded across only the bars where
 * volume fell.
 */
declare const NVI: IndicatorDescriptor;
/**
 * Positive Volume Index — the same construction as NVI over the complementary
 * set of bars, the ones where volume rose.
 */
declare const PVI: IndicatorDescriptor;
/**
 * Price Volume Trend — a running total of each bar's percentage price change
 * weighted by the volume behind it.
 *
 * The distinction from On-Balance Volume is the weighting: OBV adds the whole
 * bar's volume on any up close, so a 0.1 percent drift and a 5 percent gap
 * count the same. PVT scales the contribution by how far price actually moved.
 */
declare const PVT: IndicatorDescriptor;
/**
 * Percentage Volume Oscillator — MACD's construction applied to volume instead
 * of price, expressed as a percentage of the slow average.
 *
 * The percentage normalisation is the point: raw volume differences are not
 * comparable across symbols or across a decade of one symbol, whereas "the fast
 * average is 12 percent above the slow one" is.
 */
declare const PVO: IndicatorDescriptor;
/**
 * Mass Index — how much the range is expanding relative to its own recent
 * expansion, summed over a window.
 *
 * The ratio of a 9-bar EMA of the range to a 9-bar EMA of *that* is near 1 while
 * volatility is steady and rises as the range widens, so the sum reads as
 * "volatility has been building for a while" rather than "this bar was wide".
 * The nested EMA is the parity trap in this file: its input is already `na` for
 * the first 8 bars, and the reference reseeds past that rather than propagating it, which
 * is why the plot starts two warmups plus a window deep.
 */
declare const MASS_INDEX: IndicatorDescriptor;
/**
 * Ulcer Index — the root-mean-square percentage drawdown from the window's
 * running high.
 *
 * Standard deviation treats an upside surprise as risk; this only counts the
 * distance below the recent peak, and squaring before averaging makes one deep
 * drawdown weigh more than several shallow ones. The reading is therefore a
 * measure of how uncomfortable holding the instrument was, not of how much it
 * moved, and it is 0 on any series that only rises.
 */
declare const ULCER_INDEX: IndicatorDescriptor;
/** Every descriptor in this module, in picker order. */
declare const INDEX_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Stochastic RSI — where RSI sits inside its own recent range, which turns a
 * slow-moving oscillator into a fast one.
 *
 * The reference passes `rsi1` in as all three arguments of `stoch`, so the window
 * is the RSI's high and low rather than price's, and every warmup adds to the
 * one before it: 14 bars for the RSI, 14 more before the stochastic window is
 * full of real RSI values, then two SMAs. First `K` lands at index 29 on the
 * defaults and `D` two bars later.
 */
declare const STOCHASTIC_RSI: IndicatorDescriptor;
/**
 * Williams Percent Range — the distance from the window's high down to the
 * close, as a percentage of the window. The sign convention is the whole point:
 * a close at a fresh window high is exactly 0 and one at the window low is
 * exactly -100, so the scale runs -100..0 rather than 0..100.
 *
 * The high and low come from `high` and `low` (the reference single-argument
 * `highest`/`lowest`), while the numerator reads the `source` input, so
 * the three do not have to agree.
 */
declare const WILLIAMS_PERCENT_R: IndicatorDescriptor;
/**
 * Ultimate Oscillator — buying pressure over true range, measured across three
 * horizons at once and weighted 4:2:1 so the fast window leads without the
 * slower two losing their vote.
 *
 * `high_`/`low_` reach back to the previous close, so bar 0 has no value: the reference
 * `max(high, na)` is `na`, and that bar contributes to neither sum. Summing
 * from bar 1 is what keeps it out — `rollingSum` keeps a running total, and one
 * NaN in a running total never comes back out. With the default 28-bar window
 * the first print is therefore at index 28, not 27.
 */
declare const ULTIMATE_OSCILLATOR: IndicatorDescriptor;
/**
 * Relative Vigor Index — the bar's body over its range, on the theory that a
 * rising market closes near its high. Both halves are smoothed by `swma`
 * (the fixed 4-bar 1/2/2/1 kernel) before being summed, so a single wide bar
 * cannot swing the reading on its own.
 *
 * Warmup stacks: 3 bars for the `swma`, `length` more for the sum (index 12 on
 * the defaults), then 3 more for the signal's own `swma`.
 *
 * The reference `offset` input displaces both plots. The library has no per-plot
 * offset, so it is a real shift of the columns instead — see `shifted`.
 */
declare const RELATIVE_VIGOR_INDEX: IndicatorDescriptor;
/**
 * Relative Volatility Index — RSI's arithmetic applied to volatility instead of
 * price: how much of the recent standard deviation arrived on up bars.
 *
 * Two details are easy to get wrong. The `length` input is the standard
 * deviation's window only; the smoothing length is a hard-coded 14 in the reference
 * and stays 14 whatever `length` is set to. And the two smoothed series are not
 * clean: `change(src) <= 0 ? 0 : stddev` yields a real `0` on down bars but
 * `na` on up bars while the standard deviation is still warming up, so the EMA's
 * seed has to wait for a 14-bar window with no holes in it. That makes the first
 * printed bar `length + 12` on a one-way market rather than a fixed index.
 */
declare const RELATIVE_VOLATILITY_INDEX: IndicatorDescriptor;
/**
 * Woodies CCI — a 14-bar CCI drawn twice, as a colour-coded histogram and as a
 * line, with a fast "turbo" CCI over the top. The pair is the method: the turbo
 * line crossing the slow one is the trigger, and the histogram's colour says
 * whether the trend is established enough to take it.
 *
 * The colour is a five-bar state, not a level — `cci14[5] .. cci14[1]` all on
 * one side of zero — so it belongs to `colorBy` rather than to a second plot.
 * Note the fallback branch: with no established run, the reference paints a negative
 * reading teal and a positive one red, which is the opposite of the run colours.
 * That is what the built-in ships, and parity beats tidiness here.
 */
declare const WOODIES_CCI: IndicatorDescriptor;
/**
 * Pring's Special K: twelve rates of change from twelve different horizons, each
 * smoothed and weighted, added into one line. Short-, intermediate- and
 * long-term momentum in a single reading, which is why its turns are read as
 * complete-cycle signals rather than as entries.
 *
 * Every term has to have a value before the sum does, so the slowest one sets
 * the warmup; the reference itself refuses to run on a chart with fewer than 725
 * bars.
 */
declare const SPECIAL_K: IndicatorDescriptor;
declare const RANGE_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Vortex Indicator: how much of the window's total travel was spent reaching up
 * versus reaching down.
 *
 * Both movement terms straddle a bar boundary (`high` against the previous
 * `low`), so bar 0 has no term at all: it is missing there, and so is any
 * rolling-sum window containing it. Summing from bar 1 and shifting the answer
 * forward one bar is how that hole stays out of the running total, and it is why
 * the first printed value lands at index `length` rather than at `length - 1`
 * like the denominator does.
 */
declare const VORTEX: IndicatorDescriptor;
/**
 * Volatility Stop: a trailing stop an ATR multiple away from the running
 * extreme of the source, which flips side when price closes through it.
 *
 * The recursion is the whole study, so it is reproduced term for term. Three
 * details are load-bearing:
 *   - while the ATR is still warming there is no band to scale, and the formula
 *     falls back to the bar's own true range, unmultiplied, so the stop exists
 *     from bar 0;
 *   - the stop only ever ratchets *towards* price in the live direction, which
 *     is what makes it a stop rather than a band;
 *   - a flip resets the running extreme to the current source and recomputes the
 *     stop from it, so the level jumps once and then resumes ratcheting.
 *
 * The published study draws one cross-style plot whose colour switches with the
 * trend. This library has no per-bar line colour, so the level is split across
 * two null-gated plots exactly as Supertrend and HalfTrend do, and the crosses
 * are stood in for by markers-only dots (as Parabolic SAR does).
 */
declare const VOLATILITY_STOP: IndicatorDescriptor;
/**
 * Trend Strength Index: the correlation between price and the passage of time.
 *
 * A perfectly straight rising line correlates +1 with the bar index and a
 * straight fall correlates -1, so the reading is "how close to a straight line
 * has this been", not "how fast". Being a correlation it is bounded to -1..1,
 * hence the declared range.
 *
 * Pearson correlation is invariant under shifting either input, so counting the
 * position within the supplied bars, rather than from the start of all history,
 * changes nothing.
 *
 * The published study paints gradient fills between the line and zero, which
 * this library cannot express (a fill needs two plot edges and one flat colour).
 * The two colour inputs it spends on those gradients tint the +1 / -1 bands here
 * instead, so they still mean bullish and bearish.
 */
declare const TREND_STRENGTH_INDEX: IndicatorDescriptor;
/**
 * Williams Fractals: the pivot highs and lows the alligator is built around.
 *
 * The study is entirely shapes: two of them, and not one line. A descriptor
 * still needs a series for the marker layer to hang off,
 * so `fractals` is declared and returns an all-null column: it draws nothing and
 * contributes nothing to autoscale, it exists to own the markers. The two signal
 * columns beside it carry the price each shape is anchored to, which is what
 * makes the markers testable without re-deriving them.
 *
 * A fractal at bar `p` is only known at bar `p + n`, which is why the study
 * draws it `n` bars back. The columns follow that: the signal sits on the
 * candidate bar, and the last `n` bars can never carry one, being unconfirmed.
 */
declare const WILLIAMS_FRACTALS: IndicatorDescriptor;
/**
 * RSI Divergence Indicator: the RSI, plus a labelled plate wherever a fresh RSI
 * pivot disagrees with the price pivot beside it.
 *
 * Four signal classes, each comparing the newest oscillator pivot with the one
 * before it and the price at both:
 *   - regular bullish: oscillator higher low against a lower price low;
 *   - hidden bullish: oscillator lower low against a higher price low;
 *   - regular bearish: oscillator lower high against a higher price high;
 *   - hidden bearish: oscillator higher high against a lower price high.
 *
 * The bookkeeping is all "the previous pivot", said three ways: a pivot low of
 * the oscillator fires on the bar that *confirms* it, `lbR` bars after it
 * happened; the value-when lookup reads a series as it stood at the pivot before
 * this one; and the range gate counts the bars since that previous pivot,
 * rejecting pairs closer together than `rangeLower` or further apart than
 * `rangeUpper`. The gate counts from the found flag delayed one bar, so the
 * pivot being confirmed right now is not counted as its own predecessor.
 *
 * Every comparison is fed a missing value until a second pivot exists, and those
 * comparisons are false, so nothing fires before then without an explicit guard.
 *
 * Not reproduced: the four connector plots, which join consecutive pivot
 * readings and go transparent when the divergence does not hold. They need a
 * line drawn between two isolated points and a per-bar line colour, neither of
 * which this library's line renderer has. The labels carry the same information.
 */
declare const RSI_DIVERGENCE: IndicatorDescriptor;
/**
 * Consolidation and Breakout: a mother bar's range, the inside bars that keep it
 * alive, and the bar that finally leaves it.
 *
 * This one is a state machine rather than a formula. A single index is carried
 * from bar to bar: the bar whose high and low currently define the range. Every
 * later bar whose *body* (open to close, wicks ignored) sits inside that range
 * extends the consolidation, and the first body to escape it becomes the new
 * mother.
 *
 * The two reads of that index straddle the reassignment, and that ordering is
 * the study:
 *   - the breakout tests read the range as it stood *before* this bar could
 *     claim it, which is what makes a breakout a statement about the old range;
 *   - the plotted range and the inside-bar tint read it *after*, so a bar that
 *     breaks out is already the new mother and is correctly left untinted.
 * One bar therefore both fires a marker and opens the next consolidation.
 * Collapsing the two into one read shifts every signal by a bar, which still
 * looks plausible on a chart, so `tests/study-consolidation.test.ts` pins the
 * breaking bar itself.
 *
 * Bar 1 is excluded from the inside test by the definition: with the carried
 * index seeded at 0, bar 1 would otherwise be measured against a range that has
 * had no chance to be broken.
 *
 * Not reproduced: the thickness control the published definition puts on the two
 * range lines. `style.lineWidth` is static here and no settings key stands
 * behind it, so the control would move nothing. The lines are fixed at 2.
 */
declare const CONSOLIDATION_BREAKOUT: IndicatorDescriptor;
declare const SIGNAL_INDICATORS: readonly IndicatorDescriptor[];

declare const CPR: IndicatorDescriptor;
declare const ALPHATREND: IndicatorDescriptor;
declare const RANGE_ANALYSIS: IndicatorDescriptor;
declare const STUDY_INDICATORS: readonly IndicatorDescriptor[];

declare const WAVETREND: IndicatorDescriptor;
declare const WAVETREND_INDICATORS: readonly IndicatorDescriptor[];

declare const SEASONALITY: IndicatorDescriptor;
declare const SEASONALITY_INDICATORS: readonly IndicatorDescriptor[];

/**
 * Pure calculation helpers shared by the Tier-1 indicator descriptors
 * (`openalgo-charts/indicators`). Every function returns an array the same
 * length as its input, with `NaN` in warmup slots — the line renderer breaks
 * across non-finite points and autoscale skips them, so a warmup gap draws as
 * nothing rather than as a spike to zero.
 *
 * `ema`, `rsi`, `atr`, `trueRange`, and `supertrend` are NOT re-implemented
 * here — they ship in the base bundle and the tier imports them from it.
 */
/** Simple moving average. First value lands at index `period - 1`. */
declare function sma(values: readonly number[], period: number): number[];
/** Linearly weighted moving average (most recent bar carries weight `period`). */
declare function wma(values: readonly number[], period: number): number[];
/**
 * Wilder's smoothing (RMA): seed with the SMA of the first `period` values,
 * then `(prev * (period - 1) + v) / period`. The basis of RSI, ATR, and ADX.
 */
declare function rma(values: readonly number[], period: number): number[];
/** Rolling population standard deviation over `period`. */
declare function stdev(values: readonly number[], period: number): number[];
/** Rolling maximum over `period` bars. */
declare function highest(values: readonly number[], period: number): number[];
/** Rolling minimum over `period` bars. */
declare function lowest(values: readonly number[], period: number): number[];
/** NaN → null, so a warmup slot serialises as an explicit gap. */
declare function nulls(values: readonly number[]): (number | null)[];
/**
 * the reference `ema`: seeded with the **SMA of the first `period` values**, NaN
 * before that. The base bundle's `ema` seeds from `values[0]` and emits from
 * index 0 instead, so the two disagree for roughly the first `period` bars and
 * converge after. Anything reproducing a reference platform plot needs this one.
 */
declare function smaSeededEma(values: readonly number[], period: number): number[];
/** the reference `change(src, n)`: `src - src[n]`. NaN for the first `n` bars. */
declare function change(values: readonly number[], n?: number): number[];
/** the reference `roc`: `100 * (src - src[n]) / src[n]`. NaN for the first `n` bars. */
declare function roc(values: readonly number[], n: number): number[];
/**
 * the reference `dev`: mean **absolute** deviation from the SMA over `period` — not
 * a standard deviation. CCI's 0.015 constant is calibrated against this.
 */
declare function dev(values: readonly number[], period: number): number[];
/**
 * the reference `percentrank`: the percentage of the **previous** `period` values
 * that are less than or equal to the current one. The current bar is the
 * subject of the comparison, not part of the window, so the first answer lands
 * at index `period`.
 */
declare function percentRank(values: readonly number[], period: number): number[];
/** the reference `alma`: Gaussian-weighted MA, `offset` 0..1 and `sigma` > 0. */
declare function alma(values: readonly number[], period: number, offset: number, sigma: number): number[];
/** the reference `vwma`: `sma(src * volume, len) / sma(volume, len)`. */
declare function vwma(values: readonly number[], volumes: readonly number[], period: number): number[];
/**
 * the reference `highestbars` / `lowestbars`: the **offset** to the extreme bar
 * in the window, `0` for the current bar and `-(period - 1)` for the oldest.
 * Aroon is built entirely out of these, and the sign convention is why.
 */
declare function highestBars(values: readonly number[], period: number): number[];
declare function lowestBars(values: readonly number[], period: number): number[];
/** the reference `sum`: rolling sum over `period` bars. NaN during warmup. */
declare function rollingSum(values: readonly number[], period: number): number[];
/** the reference `cum`: running total from the first bar. Non-finite terms count as 0. */
declare function cumulative(values: readonly number[]): number[];
/**
 * the reference `linreg`: the least-squares regression line fitted over the last
 * `period` values, evaluated `offset` bars back from its right-hand end.
 *
 * x runs 0 (oldest bar in the window) to period-1 (current bar), so the value
 * at the current bar is `intercept + slope * (period - 1)`. A positive `offset`
 * steps back down that line, which is how LSMA's offset input shifts the plot
 * without recomputing the fit.
 */
declare function linreg(values: readonly number[], period: number, offset?: number): number[];
/** the reference `swma`: the fixed 4-bar symmetrically weighted average, 1/2/2/1 over 6. */
declare function swma(values: readonly number[]): number[];
/**
 * the reference `stoch(source, high, low, length)`. Note the three series are
 * independent: Stochastic RSI passes the RSI in for all three, which is why
 * this cannot just take bars.
 */
declare function stoch(source: readonly number[], high: readonly number[], low: readonly number[], period: number): number[];
/**
 * the reference `percentile_nearest_rank`. The nearest-rank method returns an
 * actual member of the window rather than interpolating between two, so a
 * 50th percentile over an even-length window is the upper of the two middles,
 * not their mean. That difference is visible on Median's default length of 3.
 */
declare function percentileNearestRank(values: readonly number[], period: number, percentage: number): number[];
/** the reference `correlation`: Pearson correlation of two series over `period`. */
declare function correlation(a: readonly number[], b: readonly number[], period: number): number[];
/** the reference `cci`: `(src - sma) / (0.015 * dev)`, where `dev` is the mean absolute deviation. */
declare function cci(values: readonly number[], period: number): number[];
/**
 * the reference `pivothigh` / `pivotlow`. A pivot is confirmed `right` bars
 * after it happens, so the answer lands on the confirming bar and refers to the
 * value `right` bars back. Comparisons are strict on both sides, so a tie is
 * not a pivot.
 */
declare function pivotHigh(values: readonly number[], left: number, right: number): number[];
declare function pivotLow(values: readonly number[], left: number, right: number): number[];
/** the reference `barssince`: bars elapsed since `cond` was last true, NaN before the first. */
declare function barsSince(cond: readonly boolean[]): number[];
/**
 * the reference `valuewhen(cond, source, occurrence)`: the value of `source` the
 * n-th most recent time `cond` was true, counting the current bar. Occurrence 0
 * is the latest.
 */
declare function valueWhen(cond: readonly boolean[], source: readonly number[], occurrence: number): number[];

/**
 * Tier-2 contract — indicators whose data is **not** derived from the chart's
 * OHLCV: open interest, cumulative volume delta, PCR, an external analytics
 * feed. Where a Tier-1 descriptor is a pure `calc(bars, settings)`, a Tier-2
 * descriptor owns a fetch / subscribe / merge lifecycle and its own series.
 *
 * `createTier2Indicator` wraps that lifecycle into an ordinary
 * `IndicatorDescriptor`, so the chart runtime, the settings model, panes,
 * levels, and removal all work identically — there is no second runtime.
 *
 * The alignment rule is deliberate and worth knowing: external points carry
 * their own timestamps, which rarely match bar times. Each bar takes the most
 * recent external point **at or before** that bar's time (last-known-value,
 * never interpolated and never forward-looking), and bars before the first
 * point are `null`.
 */

/** One external observation: a timestamp plus a value per plot key. */
interface Tier2Point {
    /** UTC seconds. */
    time: number;
    values: Readonly<Record<string, number | null>>;
}
interface Tier2Context {
    /** Host identity when supplied. Indicator settings remain independent. */
    dataContext?: Readonly<ChartDataContext>;
    /** Cancelled when this request is obsolete or the instance is removed. */
    signal?: AbortSignal;
    settings: Readonly<IndicatorSettings>;
    /** The chart's current source bars — use for the requested time window. */
    bars: readonly Bar[];
    /** UTC seconds of the first and last source bar (0 when there are none). */
    from: number;
    to: number;
}
interface Tier2Descriptor {
    id: string;
    name: string;
    category?: string;
    placement: 'onchart' | 'pane';
    inputs: readonly IndicatorInput[];
    plots: readonly IndicatorPlot[];
    /** A host/provider can explicitly decline data it cannot supply. */
    supports?(ctx: Tier2Context): boolean;
    /** Load the series for the current window. */
    fetch(ctx: Tier2Context): Promise<readonly Tier2Point[]>;
    /**
     * Optional live subscription. Call `push` with each incoming point; return an
     * unsubscribe function.
     */
    subscribe?(ctx: Tier2Context, push: (point: Tier2Point) => void): () => void;
    /**
     * Settings keys that invalidate the fetched data when they change (symbol,
     * exchange, resolution). Changing anything else only re-runs alignment.
     */
    refetchOn?: readonly string[];
    levels?(settings: Readonly<IndicatorSettings>): readonly IndicatorLevel[];
    range?(settings: Readonly<IndicatorSettings>): {
        min: number;
        max: number;
    } | null;
}
/**
 * Wrap a Tier-2 descriptor as a normal `IndicatorDescriptor`.
 *
 * ```ts
 * export const OPEN_INTEREST = createTier2Indicator({
 *   id: 'open-interest', name: 'Open Interest', placement: 'pane',
 *   inputs: [{ key: 'symbol', type: 'text', label: 'Symbol', default: '' }],
 *   plots: [{ key: 'oi', type: 'line', title: 'OI' }],
 *   refetchOn: ['symbol'],
 *   fetch: async ({ settings, from, to }) => loadOi(settings.symbol, from, to),
 * });
 * registerIndicator(OPEN_INTEREST);
 * ```
 */
declare function createTier2Indicator(d: Tier2Descriptor): IndicatorDescriptor;

declare const INDICATORS_TIER: "indicators";
/** Every built-in descriptor, in picker order. */
declare const BUILTIN_INDICATORS: readonly IndicatorDescriptor[];
/**
 * Register every built-in indicator. Called as a side effect on import, and
 * exported so bundlers that aggressively tree-shake a bare side-effect import
 * can call it explicitly. Idempotent.
 */
declare function registerBuiltinIndicators(): void;

export { ADAPTIVE_INDICATORS, ADL, ADX, ALLIGATOR, ALMA, ALPHATREND, AROON, AROON_OSCILLATOR, ATR, AVERAGE_DAILY_RANGE, AVERAGE_INDICATORS, AWESOME_OSCILLATOR, BALANCE_OF_POWER, BB_TREND, BOLLINGER, BOLLINGER_BANDWIDTH, BOLLINGER_PERCENT_B, BUILTIN_INDICATORS, CCI, CHAIKIN_MONEY_FLOW, CHAIKIN_OSCILLATOR, CHAIKIN_VOLATILITY, CHANDELIER_EXIT, CHANDE_KROLL_STOP, CHANDE_MOMENTUM, CHOPPINESS_INDEX, CHOP_ZONE, CONNORS_RSI, CONSOLIDATION_BREAKOUT, COPPOCK_CURVE, CPR, DEMA, DONCHIAN, DPO, EASE_OF_MOVEMENT, ELDER_FORCE_INDEX, EMA, ENVELOPE, FISHER_TRANSFORM, FLOW_INDICATORS, HALFTREND, HISTORICAL_VOLATILITY, HMA, HULL_SUITE, ICHIMOKU, INDEX_INDICATORS, INDICATORS_TIER, KAMA, KELTNER_CHANNEL, KLINGER_OSCILLATOR, KNOW_SURE_THING, LINREG_SLOPE, LSMA, MACD, MASS_INDEX, MA_CHANNEL, MA_CROSS, MA_RIBBON, MCGINLEY_DYNAMIC, MEDIAN, MFI, MOMENTUM, NET_VOLUME, NVI, OBV, OSCILLATOR_INDICATORS, OVERLAY_INDICATORS, PARABOLIC_SAR, PPO, PVI, PVO, PVT, RANGE_ANALYSIS, RANGE_INDICATORS, RELATIVE_VIGOR_INDEX, RELATIVE_VOLATILITY_INDEX, ROC, RSI, RSI_DIVERGENCE, SEASONALITY, SEASONALITY_INDICATORS, SIGNAL_INDICATORS, SMA, SMI, SMI_ERGODIC_INDICATOR, SMI_ERGODIC_OSCILLATOR, SMMA, SPECIAL_K, STANDARD_DEVIATION, STANDARD_ERROR, STANDARD_ERROR_BANDS, STOCHASTIC, STOCHASTIC_RSI, STRENGTH_INDICATORS, STUDY_INDICATORS, SUPERTREND, T3, TEMA, TREND_STRENGTH_INDEX, TRIX, TSI, TWAP, type Tier2Context, type Tier2Descriptor, type Tier2Point, ULCER_INDEX, ULTIMATE_OSCILLATOR, VOLATILITY_INDICATORS, VOLATILITY_STOP, VOLUME, VORTEX, VWAP, VWMA, WAVETREND, WAVETREND_INDICATORS, WILLIAMS_FRACTALS, WILLIAMS_PERCENT_R, WILLIAMS_VIX_FIX, WMA, WOODIES_CCI, alma, barsSince, cci, change, connorsStreak, correlation, createTier2Indicator, cumulative, dev, highest, highestBars, linreg, lowest, lowestBars, nulls, percentRank, percentileNearestRank, pivotHigh, pivotLow, registerBuiltinIndicators, rma, roc, rollingSum, sma, smaSeededEma, stdev, stoch, swma, valueWhen, vwma, wma };