Skip to content

Warmup Periods

Every Wickra indicator returns None (Rust), None (Python), or null (Node) for its first few inputs while it gathers enough data to produce a defined value. The number of inputs an indicator needs before it emits its first non-empty value is its warmup period, surfaced everywhere as warmup_period() / warmupPeriod().

After the first emission, the indicator never goes back to a "no value yet" state — it has rolled its state forward and will produce a steady value on every subsequent update(). Calling reset() returns to the warming-up state, equivalent to a freshly constructed instance.

How to read the formula column

The formulas below are taken verbatim from the warmup_period() methods in crates/wickra-core/src/indicators/<name>.rs. The "Inputs at first emission" column says, in 1-indexed terms, which update() call returns the first Some/non-NaN value. They are the same number; "first emission index" in 0-indexed terms is warmup_period − 1.

Single-output indicators

The rows are keyed by constructor, not by indicator name. Vwap appears twice — once for the cumulative Vwap::new() and once for the finite-window RollingVwap::new(period) — because the two share the indicator name Vwap (see Indicators-Overview) but have different warmup periods. That is the only such pair; every other row is one canonical indicator.

IndicatorConstructorFormulawarmup_period() for shown argsInputs at first emission
SmaSma::new(14)period1414th
EmaEma::new(14)period1414th
WmaWma::new(14)period1414th
DemaDema::new(14)2 * period - 12727th
TemaTema::new(14)3 * period - 24040th
HmaHma::new(14)period + round(sqrt(period)).max(1) - 11717th
KamaKama::new(10, 2, 30)er_period + 11111th
RsiRsi::new(14)period + 11515th
CciCci::new(20)period2020th
RocRoc::new(12)period + 11313th
WilliamsRWilliamsR::new(14)period1414th
MfiMfi::new(14)period1414th
TrixTrix::new(15)3 * period - 14444th
AwesomeOscillatorAwesomeOscillator::new(5, 34)slow_period3434th
AtrAtr::new(14)period1414th
PsarPsar::new(0.02, 0.02, 0.20)constant 222nd
ObvObv::new()constant 111st
VwapVwap::new()constant 111st
RollingVwapRollingVwap::new(20)period2020th
SmmaSmma::new(14)period1414th
TrimaTrima::new(20)period2020th
ZlemaZlema::new(14)lag + period (lag = (period − 1) / 2)2020th
T3T3::new(5, 0.7)6 * period - 52525th
VwmaVwma::new(20)period2020th
AlmaAlma::new(9, 0.85, 6.0)period99th
McGinleyDynamicMcGinleyDynamic::new(10)period1010th
FramaFrama::new(16)period1616th
VidyaVidya::new(14, 9)cmo_period + 11010th
JmaJma::new(14, 0.0, 2)constant 111st
EvwmaEvwma::new(20)period2020th
MomMom::new(10)period + 11111th
CmoCmo::new(14)period + 11515th
TsiTsi::new(25, 13)long + short3838th
PmoPmo::new(35, 20)constant 222nd
StochRsiStochRsi::new(14, 14)rsi_period + stoch_period2828th
UltimateOscillatorUltimateOscillator::new(7, 14, 28)max(short, mid, long) + 12929th
RviRvi::new(10)period1010th
PgoPgo::new(14)period1414th
SmiSmi::new(5, 3, 3)period + d_period + d2_period − 299th
LaguerreRsiLaguerreRsi::new(0.5)constant 111st
ConnorsRsiConnorsRsi::new(3, 2, 100)max(period_rsi+1, period_streak+2, period_rank+1)101101st
InertiaInertia::new(14, 20)rvi_period + linreg_period − 13333rd
PpoPpo::new(12, 26)slow2626th
DpoDpo::new(20)max(period, period / 2 + 2)2020th
CoppockCoppock::new(14, 11, 10)max(roc_long, roc_short) + wma_period2424th
AroonOscillatorAroonOscillator::new(14)period + 11515th
MassIndexMassIndex::new(9, 25)2 * ema_period + sum_period - 24141st
NatrNatr::new(14)period1414th
StdDevStdDev::new(20)period2020th
UlcerIndexUlcerIndex::new(14)2 * period - 12727th
HistoricalVolatilityHistoricalVolatility::new(20, 252)period + 12121st
BollingerBandwidthBollingerBandwidth::new(20, 2.0)period2020th
PercentBPercentB::new(20, 2.0)period2020th
AtrTrailingStopAtrTrailingStop::new(14, 3.0)atr_period1414th
AdlAdl::new()constant 111st
VolumePriceTrendVolumePriceTrend::new()constant 111st
ChaikinMoneyFlowChaikinMoneyFlow::new(20)period2020th
ChaikinOscillatorChaikinOscillator::new(3, 10)slow1010th
ForceIndexForceIndex::new(13)period + 11414th
EaseOfMovementEaseOfMovement::new(14)period + 11515th
TypicalPriceTypicalPrice::new()constant 111st
MedianPriceMedianPrice::new()constant 111st
WeightedCloseWeightedClose::new()constant 111st
LinearRegressionLinearRegression::new(14)period1414th
LinRegSlopeLinRegSlope::new(14)period1414th
AcceleratorOscillatorAcceleratorOscillator::classic()ao_slow + signal_period - 13838th
BalanceOfPowerBalanceOfPower::new()constant 111st
ChoppinessIndexChoppinessIndex::new(14)period1414th
VerticalHorizontalFilterVerticalHorizontalFilter::new(28)period + 12929th
TrueRangeTrueRange::new()constant 111st
ChaikinVolatilityChaikinVolatility::new(10, 10)ema_period + roc_period2020th
ZScoreZScore::new(20)period2020th
LinRegAngleLinRegAngle::new(14)period1414th
RviVolatilityRviVolatility::new(10)2 * period - 11919th
ParkinsonVolatilityParkinsonVolatility::new(20, 252)period2020th
GarmanKlassVolatilityGarmanKlassVolatility::new(20, 252)period2020th
RogersSatchellVolatilityRogersSatchellVolatility::new(20, 252)period2020th
YangZhangVolatilityYangZhangVolatility::new(20, 252)period + 12121st
AdxrAdxr::new(14)3 * period - 14141st
TiiTii::new(60, 30)sma_period + dev_period - 18989th

Family 05: Bands & Channels (scalar input, scalar projection)

These rows track the single-output Bands & Channels — MaEnvelope, AccelerationBands, StarcBands, AtrBands, HurstChannel, LinRegChannel, StandardErrorBands all emit a multi-output struct (upper / middle / lower). They are listed in the multi-output section below for completeness; their warmup is included here only so the single-output reader does not have to jump:

IndicatorWarmup formula
MaEnvelopeperiod
LinRegChannelperiod
StandardErrorBandsperiod (constructor enforces period >= 3)

Multi-output indicators

These indicators emit several values at once (a struct in Rust, a tuple in Python, an object in Node) and every column / field transitions from "not ready" to "ready" together — there are no rows that have a signal but no macd, for example.

IndicatorConstructorFormulawarmup_period() for shown argsInputs at first emissionOutputs
MacdIndicatorMacdIndicator::new(12, 26, 9)slow + signal - 13434thmacd, signal, histogram
BollingerBandsBollingerBands::new(20, 2.0)period2020thupper, middle, lower, stddev
StochasticStochastic::new(14, 3)k_period + d_period - 11616thk, d
AdxAdx::new(14)2 * period2828thplus_di, minus_di, adx
AroonAroon::new(14)period + 11515thup, down
KstKst::classic()longest roc_i + sma_i + signal − 15353rdkst, signal
AlligatorAlligator::new(13, 8, 5)max(jaw, teeth, lips)1313thjaw, teeth, lips
KeltnerKeltner::new(20, 10, 2.0)ema_period.max(atr_period)2020thupper, middle, lower
DonchianDonchian::new(20)period2020thupper, middle, lower
VortexVortex::new(14)period + 11515thplus, minus
SuperTrendSuperTrend::new(10, 3.0)atr_period1010thvalue, direction
ChandelierExitChandelierExit::new(22, 3.0)period2222ndlong_stop, short_stop
ChandeKrollStopChandeKrollStop::new(10, 1.0, 9)atr_period + stop_period - 11818thstop_long, stop_short
MaEnvelopeMaEnvelope::new(20, 0.025)period2020thupper, middle, lower
AccelerationBandsAccelerationBands::new(20, 0.001)period2020thupper, middle, lower
StarcBandsStarcBands::new(6, 15, 2.0)max(sma_period, atr_period)1515thupper, middle, lower
AtrBandsAtrBands::new(14, 3.0)period1414thupper, middle, lower
HurstChannelHurstChannel::new(10, 0.5)period1010thupper, middle, lower
LinRegChannelLinRegChannel::new(20, 2.0)period2020thupper, middle, lower
StandardErrorBandsStandardErrorBands::new(21, 2.0)period2121stupper, middle, lower
DoubleBollingerDoubleBollinger::new(20, 1.0, 2.0)period2020thupper_outer, upper_inner, middle, lower_inner, lower_outer
TtmSqueezeTtmSqueeze::new(20, 2.0, 1.5)period2020thsqueeze, momentum
FractalChaosBandsFractalChaosBands::new(2)2k + 1 + first fractal of each kind≥ 5first bar with both fractals confirmedupper, lower
VwapStdDevBandsVwapStdDevBands::new(2.0)first bar with non-zero volume11stupper, middle, lower, stddev
RwiRwi::new(14)period1414thhigh, low
WaveTrendWaveTrend::classic()2 * channel + average + signal - 34242ndwt1, wt2

Family 09 — Trailing Stops (added since 0.2.0)

IndicatorConstructorFormulawarmup for shown argsInputs at first emission
HiLoActivatorHiLoActivator::new(3)period + 144th
VoltyStopVoltyStop::classic() (14, 2.0)atr_period + 11515th
YoyoExitYoyoExit::classic() (14, 2.0)atr_period + 11515th
DonchianStopDonchianStop::classic() (10)period1010th
PercentageTrailingStopPercentageTrailingStop::classic() (5.0)constant 111st
StepTrailingStopStepTrailingStop::classic() (1.0)constant 111st
RenkoTrailingStopRenkoTrailingStop::classic() (1.0)constant 111st

Family 10 — Ehlers / Cycle (DSP)

The Hilbert-chain indicators (Mama / Fama / HilbertDominantCycle / SineWave / AdaptiveCycle) inherit a long warmup from the truncated-Hilbert phase extractor — warmup_period() reports a conservative ~50.

IndicatorConstructorFormulawarmupInputs at first emission
MamaMama::classic() (0.5, 0.05)Hilbert-chain warmup~30~30th
FamaFama::classic() (0.5, 0.05)delegates to Mama~30~30th
FisherTransformFisherTransform::new(10)period1010th
InverseFisherTransformInverseFisherTransform::new(1.0)constant 111st
SuperSmootherSuperSmoother::new(10)constant 2 (pass-through warmup)22nd
HilbertDominantCycleHilbertDominantCycle::new()Hilbert-chain warmup~50~50th
SineWaveSineWave::new()Hilbert-chain warmup~50~50th
DecyclerDecycler::new(20)constant 222nd
DecyclerOscillatorDecyclerOscillator::new(10, 30)constant 222nd
RoofingFilterRoofingFilter::new(10, 48)constant 222nd
CenterOfGravityCenterOfGravity::new(10)period1010th
CyberneticCycleCyberneticCycle::new(10)constant 666th
AdaptiveCycleAdaptiveCycle::new()inherits HilbertDominantCycle~50~50th
EmpiricalModeDecompositionEmpiricalModeDecomposition::new(20, 0.5)period2020th
EhlersStochasticEhlersStochastic::new(20)period + RoofingFilter warmup~70~70th
InstantaneousTrendlineInstantaneousTrendline::new(20)period2020th

Family 11 — Pivots & S/R

IndicatorConstructorFormulawarmupInputs at first emission
ClassicPivotsClassicPivots::new()constant 111st
FibonacciPivotsFibonacciPivots::new()constant 111st
CamarillaCamarilla::new()constant 111st
WoodiePivotsWoodiePivots::new()constant 111st
DemarkPivotsDemarkPivots::new()constant 111st
WilliamsFractalsWilliamsFractals::new()constant 555th (centre bar at index 3)
ZigZagZigZag::new(0.05)constant 222nd (only emits on confirmation)

Family 12 — DeMark

IndicatorConstructorFormulawarmupInputs at first emission
TdSetupTdSetup::classic() (4, 9)lookback + 155th
TdSequentialTdSequential::classic() (4, 9, 2, 13)max(setup_lookback, countdown_lookback) + 155th
TdCountdownTdCountdown::classic() (4, 9, 2, 13)max(setup_lookback, countdown_lookback) + 155th
TdComboTdCombo::classic() (4, 9, 2, 13)max(setup_lookback, countdown_lookback) + 155th
TdLines (TDST)TdLines::new(4, 9)lookback + 1 (NaN until first setup)55th (level emits later)
TdDeMarkerTdDeMarker::new(14)period + 11515th
TdReiTdRei::classic() (5)period + 71212th
TdPressureTdPressure::new(5)period55th
TdRangeProjectionTdRangeProjection::new()constant 111st
TdDifferentialTdDifferential::new()constant 222nd
TdOpenTdOpen::new()constant 222nd
TdRiskLevelTdRiskLevel::new(4, 9)lookback + 1 (NaN until first setup)55th (level emits later)

Family 13 — Ichimoku & Charts

IndicatorConstructorFormulawarmupInputs at first emission
IchimokuIchimoku::classic() (9, 26, 52, 26)senkou_b_period + displacement - 17777th
HeikinAshiHeikinAshi::new()constant 111st

Family 14 — Candlestick Patterns

All single-bar patterns warm up in 1; 2-bar patterns in 2; 3-bar patterns in 3. Pattern-shape only — combine with a trend filter for actionable signals.

IndicatorConstructorFormulawarmupInputs at first emission
DojiDoji::default()constant 111st
HammerHammer::new()constant 111st
InvertedHammerInvertedHammer::new()constant 111st
HangingManHangingMan::new()constant 111st
ShootingStarShootingStar::new()constant 111st
MarubozuMarubozu::default()constant 111st
SpinningTopSpinningTop::new(0.3)constant 111st
EngulfingEngulfing::new()constant 222nd
HaramiHarami::new()constant 222nd
PiercingDarkCloudPiercingDarkCloud::new()constant 222nd
TweezerTweezer::new(0.001)constant 222nd
MorningEveningStarMorningEveningStar::new()constant 333rd
ThreeSoldiersOrCrowsThreeSoldiersOrCrows::new()constant 333rd
ThreeInsideThreeInside::new()constant 333rd
ThreeOutsideThreeOutside::new()constant 333rd

Family 15 — Risk / Performance

Some risk metrics take a single f64 (returns / equity), others take an (asset, benchmark) pair.

IndicatorConstructorFormulawarmupInputs at first emission
SharpeRatioSharpeRatio::new(20, 0.0)period2020th
SortinoRatioSortinoRatio::new(20, 0.0)period2020th
CalmarRatioCalmarRatio::new(20)period2020th
OmegaRatioOmegaRatio::new(20, 0.0)period2020th
MaxDrawdownMaxDrawdown::new(252)constant 111st
AverageDrawdownAverageDrawdown::new(20)period2020th
DrawdownDurationDrawdownDuration::new()constant 111st
PainIndexPainIndex::new(20)period2020th
ValueAtRiskValueAtRisk::new(100, 0.95)period100100th
ConditionalValueAtRiskConditionalValueAtRisk::new(100, 0.95)period100100th
ProfitFactorProfitFactor::new(20)period2020th
GainLossRatioGainLossRatio::new(20)period2020th
RecoveryFactorRecoveryFactor::new()constant 111st
KellyCriterionKellyCriterion::new(100)period100100th
TreynorRatioTreynorRatio::new(50, 0.0)period5050th
InformationRatioInformationRatio::new(50)period5050th
AlphaAlpha::new(50, 0.0)period5050th

Family 16 — Market Profile

All three require manual reset() at session boundaries.

IndicatorConstructorFormulawarmupInputs at first emission
ValueAreaValueArea::new(20, 50, 0.70)period2020th
InitialBalanceInitialBalance::classic() (12)period1212th (then locks)
OpeningRangeOpeningRange::classic() (6)period66th (then locks; live breakout_distance)

Family 17 — Microstructure

Non-OHLCV indicators over the order book and trade tape. Most are stateless or fixed-window; Footprint accumulates until reset().

IndicatorConstructorFormulawarmupInputs at first emission
OrderBookImbalanceTop1OrderBookImbalanceTop1::new()constant 111st snapshot
OrderBookImbalanceTopNOrderBookImbalanceTopN::new(5)constant 111st snapshot
OrderBookImbalanceFullOrderBookImbalanceFull::new()constant 111st snapshot
MicropriceMicroprice::new()constant 111st snapshot
QuotedSpreadQuotedSpread::new()constant 111st snapshot
DepthSlopeDepthSlope::new()constant 111st snapshot
SignedVolumeSignedVolume::new()constant 111st trade
CumulativeVolumeDeltaCumulativeVolumeDelta::new()constant 111st trade (reset per session)
TradeImbalanceTradeImbalance::new(20)window2020th trade
EffectiveSpreadEffectiveSpread::new()constant 111st trade-quote
RealizedSpreadRealizedSpread::new(10)horizon + 11111th trade-quote
KylesLambdaKylesLambda::new(50)window + 15151st trade-quote
FootprintFootprint::new(0.5)constant 111st trade (reset per bar)

Additional Volume indicators

IndicatorConstructorFormulawarmupInputs at first emission
AdOscillatorAdOscillator::new()constant 222nd
AnchoredVwapAnchoredVwap::new()1 post-anchorn/a1st bar after set_anchor()
KvoKvo::classic() (34, 55, 13)slow + signal - 16767th
MarketFacilitationIndexMarketFacilitationIndex::new()constant 111st
NviNvi::new()constant 222nd
PviPvi::new()constant 222nd
TsvTsv::new(18)period + 11919th
VzoVzo::new(14)period + 11515th
VolumeOscillatorVolumeOscillator::new(14, 28)slow2828th
DemandIndexDemandIndex::new(20)period + 12121st

Additional Price Statistics indicators

IndicatorConstructorFormulawarmupInputs at first emission
VarianceVariance::new(20)period2020th
CoefficientOfVariationCoefficientOfVariation::new(20)period2020th
SkewnessSkewness::new(20)period2020th
KurtosisKurtosis::new(20)period2020th
StandardErrorStandardError::new(20)period2020th
RSquaredRSquared::new(20)period2020th
MedianAbsoluteDeviationMedianAbsoluteDeviation::new(20)period2020th
AutocorrelationAutocorrelation::new(50, 1)period5050th
HurstExponentHurstExponent::new(100, 4)period100100th
PearsonCorrelationPearsonCorrelation::new(50)period5050th
BetaBeta::new(50)period5050th
PairwiseBetaPairwiseBeta::new(50)period + 15151st
PairSpreadZScorePairSpreadZScore::new(30, 20)beta_period + z_period − 14949th
LeadLagCrossCorrelationLeadLagCrossCorrelation::new(20, 10)window + 2·max_lag4040th
CointegrationCointegration::new(30, 1)period3030th
RelativeStrengthABRelativeStrengthAB::new(20, 14)max(ma_period, rsi_period + 1)2020th
SpearmanCorrelationSpearmanCorrelation::new(50)period5050th
DetrendedStdDevDetrendedStdDev::new(20)period2020th

Additional Price Oscillators

IndicatorConstructorFormulawarmupInputs at first emission
ApoApo::new(12, 26)slow2626th
AwesomeOscillatorHistogramAwesomeOscillatorHistogram::new(5, 34)slow + 13535th
CfoCfo::new(14)period1414th
ZeroLagMacdZeroLagMacd::classic() (12, 26, 9)ZLEMA-chain warmup5050th
ElderImpulseElderImpulse::classic()slow + signal - 13434th
StcStc::classic() (23, 50, 10)slow + cycle + 16161st

"Off-by-one" cases worth memorising

A few indicators look like they should warm up at period but in fact need period + 1 inputs. The reason is always the same — they consume diffs or previous-close differences, not the prices themselves, and the very first input has nothing to diff against.

  • Rsi::new(period) warmup is period + 1. RSI is based on Wilder's smoothing over per-tick gains and losses. With 14 prices you only have 13 diffs; you need 15 prices to compute 14 diffs and seed avg_gain / avg_loss. The Rust unit test that pins this is warmup_period_is_period_plus_one:
    rust
    let rsi = Rsi::new(14).unwrap();
    assert_eq!(rsi.warmup_period(), 15);
  • Roc::new(period) warmup is period + 1. ROC compares the current price to the price period bars ago; that comparison only makes sense starting at input period + 1.
  • Aroon::new(period) warmup is period + 1. Aroon scans a period + 1-bar window to find the bars-since-high and bars-since-low.
  • Kama::new(er_period, ...) warmup is er_period + 1. Kaufman's efficiency ratio needs er_period differences, which costs one extra bar.

Cross-checking from your own code

The cleanest way to verify any of these from your application code is the indicator's own warmup_period():

rust
use wickra::{Indicator, MacdIndicator};
let macd = MacdIndicator::classic();   // (12, 26, 9)
assert_eq!(macd.warmup_period(), 34);
python
import wickra as ta
assert ta.MACD(12, 26, 9).warmup_period() == 34
javascript
const wickra = require('wickra');
const sma = new wickra.SMA(20);
console.log(sma.warmupPeriod());   // -> 20

(Since wickra@0.2.1, warmupPeriod() is exposed on every Node and WASM class — single- and multi-output — alongside update(), reset() and isReady(). Consult bindings/node/index.d.ts for the authoritative TypeScript surface.)

See also