Documentation, examples and further information of the ta4j project
This project is maintained by ta4j Organization
Forecast indicators estimate a future return or price distribution using only information available at a decision index. The 0.23.1 API makes the distribution’s numeric domain, horizon, and provenance explicit.
Use them for probabilistic filters, sizing, risk limits, chart overlays, and out-of-sample research. Do not treat a quantile as a guaranteed target or use a horizon that does not match the strategy’s execution and holding period.
For reusable state contracts and feature schemas, see Forecast State Estimation. Applications upgrading from 0.23.0 should read Migration and Version Compatibility.
For detailed analog and rolling calibration tuning, see Forecast Projection Models.
BarSeries series = ...;
LogReturnIndicator returns = new LogReturnIndicator(series);
ReturnForecastStateIndicator<ReturnForecastState> state =
new EwmaReturnForecastStateIndicator(returns);
ForecastProjectionIndicator prices =
new MonteCarloPriceForecastIndicator(state, 5);
int index = series.getEndIndex();
Forecast forecast = prices.getValue(index);
if (forecast.isStable()) {
Num downside = forecast.quantile(0.05);
Num median = forecast.median();
Num upside = forecast.quantile(0.95);
}
Indicator<Num> medianSeries = prices.median();
Indicator<Num> downsideSeries = prices.quantile(0.05);
MonteCarloPriceForecastIndicator infers the price source when the state uses LogReturnIndicator. It converts every simulated cumulative return to a terminal price before calculating any moment or quantile. Mean, median, standard deviation, and quantiles therefore describe the same empirical price paths.
The shortest constructor uses a 30-observation EWMA state, one or five bars as requested, 1,000 paths, a 252-return lookback, seed 42, standardized empirical shocks, constant path volatility, and quantiles 0.05, 0.25, 0.5, 0.75, and 0.95.
LogReturnIndicator returns = new LogReturnIndicator(series);
ReturnForecastStateIndicator<ReturnForecastState> states =
new EwmaReturnForecastStateIndicator(returns);
AnalogReturnProjectionIndicator<ReturnForecastState> analog =
new AnalogReturnProjectionIndicator<>(states, 5);
ReturnForecastProjectionIndicator calibrated =
RollingConformalForecastProjectionIndicator
.cumulativeLogReturnBuilder(analog, returns)
.build();
Forecast result = calibrated.getValue(series.getEndIndex());
Analog projection uses only post-warm-up candidates whose complete five-bar outcomes have matured, fits feature standardization from historical candidates only, and reports selected neighbors as empirical support. The conformal wrapper remains unavailable until at least 30 valid historical forecasts mature and the finite-sample coverage rank is attainable, then widens lower and upper quantiles while preserving the analog mean, median, standard deviation, support, and semantic return-projection contract.
Every Forecast is Num-only and contains:
| API | Meaning |
|---|---|
decisionIndex() / index() |
Index where the forecast was made. |
horizon() |
Number of bars represented by the outcome distribution. |
support() |
Unavailable, Empirical(count), or Analytic(assumption). |
sampleCount() |
Empirical represented-value count; zero for analytic or unavailable support. |
mean(), median(), standardDeviation() |
Coherent distribution summary values. |
quantiles() |
Immutable configured probability-to-value map. |
quantile(p) |
Configured quantile, or NaN.NaN when valid p is absent. |
isStable() |
Whether the summary is available and usable. |
All built-in projections return a non-null forecast whose decision index and horizon match the query and getHorizon(). Point adapters return NaN.NaN if that contract is violated, if the forecast is unavailable, or if the requested quantile is absent.
Forecast.ofSamples(...) is the shortest empirical factory. It retains finite samples, normalizes them to the first retained sample’s NumFactory, and reports retained count as empirical support. For analytic or externally summarized distributions, use the builder:
Forecast forecast = Forecast.builder(
index,
horizon,
series.numFactory(),
ForecastSupport.analytic("normal-residual"))
.mean(mean)
.median(median)
.standardDeviation(standardDeviation)
.quantiles(quantiles)
.build();
The builder requires finite mean, median, and non-negative standard deviation. It normalizes all values through the declared factory and validates ordered quantiles, median/0.5 agreement, zero-dispersion equality, and one-value empirical coherence. Use Forecast.unstable(index, horizon) when a valid summary cannot be produced.
Use forecast.scale(factor) or forecast.affine(scale, offset) only for mathematically affine domain changes. Negative scaling reverses quantile probabilities and standard deviation uses the absolute scale. Nonlinear transforms such as price * exp(logReturn) must be applied to samples before summarization or modeled as an explicitly named analytic approximation.
Custom return-state estimators often cannot expose an inferable source price. Supply it explicitly and tune the price projection directly:
ClosePriceIndicator close = new ClosePriceIndicator(series);
ReturnForecastStateIndicator<? extends ReturnMomentState> state = ...;
MonteCarloPriceForecastIndicator prices =
MonteCarloPriceForecastIndicator.builder(close, state)
.horizon(5)
.iterationCount(5_000)
.lookbackBarCount(504)
.seed(7L)
.shockModel(MonteCarloReturnProjectionIndicator.ShockModel.STANDARDIZED_EMPIRICAL)
.volatilityUpdateMode(MonteCarloReturnProjectionIndicator.VolatilityUpdateMode.EWMA)
.volatilityDecayFactor(0.97)
.quantiles(0.01, 0.05, 0.5, 0.95, 0.99)
.build();
| Setting | Default | Operator intent |
|---|---|---|
horizon(...) |
1 |
Match the forecast label and holding period. |
iterationCount(...) |
1_000 |
Increase for smoother tails after measuring latency. |
lookbackBarCount(...) |
252 |
Choose the historical regime represented by shocks. |
seed(...) |
42 |
Keep fixed for reproducible research and operations. |
shockModel(...) |
STANDARDIZED_EMPIRICAL |
Preserve recent residual shape at current state volatility. |
volatilityUpdateMode(...) |
CONSTANT |
Use EWMA only when path-dependent volatility is intentional. |
volatilityDecayFactor(...) |
0.94 |
Path EWMA persistence when updates are enabled. |
quantiles(...) |
five defaults | Request only tails consumed by rules or reports. |
Shock model choices:
| Model | Behavior | Use when |
|---|---|---|
HISTORICAL_BOOTSTRAP |
Samples raw historical returns. | Recent realized scale and shape should be preserved directly. |
STANDARDIZED_EMPIRICAL |
Samples standardized residuals and applies state drift/volatility. | Current scale plus empirical tail shape is desired. |
NORMAL |
Samples standard-normal shocks. | A transparent parametric baseline is appropriate. |
MonteCarloReturnProjectionIndicator exposes the same builder settings when the required output is cumulative log return rather than price.
Use LognormalApproximationPriceForecastIndicator only when you have a log-return summary but not terminal paths and explicitly accept moment matching:
ReturnForecastProjectionIndicator returns = ...;
ForecastProjectionIndicator prices =
LognormalApproximationPriceForecastIndicator
.builder(new ClosePriceIndicator(series), returns)
.quantiles(0.05, 0.5, 0.95)
.build();
It fits one coherent lognormal distribution from source mean and standard deviation, recomputes all requested quantiles, and reports ForecastSupport.analytic("lognormal-moment-match"). This is not an empirical adapter and should not be presented as exact Monte Carlo output.
Use it when only moments are available and the lognormal assumption is acceptable. Do not use it when terminal samples are available, returns are not logarithmic, or tail shape is central to the decision.
EwmaReturnForecastStateIndicator consumes a semantic ReturnIndicator in ReturnRepresentation.LOG and emits ReturnForecastState, which wraps canonical ReturnMoments.
EwmaReturnForecastStateIndicator state =
new EwmaReturnForecastStateIndicator(
returns,
60,
0.97,
EwmaReturnForecastStateIndicator.DriftMode.ZERO);
| Setting | Default | Effect |
|---|---|---|
initializationBarCount |
30 |
Valid observations required before stable state. |
decayFactor |
0.94 |
Higher values react more slowly. |
driftMode |
ZERO |
ROLLING_MEAN uses EWMA mean as simulated drift. |
Prefer zero drift unless a rolling drift assumption has earned its place in out-of-sample testing.
RoughVolatilityForecastStateIndicator is the constructor-first rich-state path:
RoughVolatilityForecastStateIndicator rough =
new RoughVolatilityForecastStateIndicator(returns);
RoughVolatilityForecastState state = rough.getValue(index);
It reuses canonical EWMA moments and composes HurstExponentIndicator over the logarithmic volatility proxy, then applies the rough model’s [0.01, 0.49] bound. Population dispersion of that proxy and five cumulative horizon variances complete the default state. The representation-bound ForecastFeatureExtractors.roughVolatility() schema exposes [mean, volatility, roughness_hurst, vol_of_vol] for models that intentionally use those diagnostics. See Forecast State Estimation for advanced tuning, exact field semantics, warm-up, recovery, and when to prefer the smaller EWMA state.
OnlineChangePointForecastStateIndicator is the constructor-first regime-uncertainty path:
OnlineChangePointForecastStateIndicator changePoints =
new OnlineChangePointForecastStateIndicator(returns);
OnlineChangePointForecastState state = changePoints.getValue(index);
The default filter expects a 100-observation regime, retains run lengths through 252, reports five typed posterior summaries, and becomes stable after 20 consecutive valid returns. recentChangeProbability() aggregates complete-posterior mass over run lengths zero through five, and recentChangeWindow() carries that boundary with the state. It is intentionally different from P(runLength = 0), which equals the constant hazard before tail truncation and can increase slightly after truncation and renormalization, but cannot respond usefully to a shift. Under canonical indexing, run length zero retains prior sufficient statistics and the current observation updates growth components.
Use ForecastFeatureExtractors.changePoint() for the default five-bar window or changePoint(window) for a window-qualified schema. Both publish [mean, volatility, recent_change_probability, most_likely_run_length] only when regime uncertainty and age are intentional analog dimensions. See Forecast State Estimation for prior tuning, posterior semantics, reset behavior, and failure guidance.
A built-in projection returns ForecastSupport.Unavailable with NaN.NaN summary values until all prerequisites are valid. It can recover at a later index after invalid inputs leave the required window.
Common unavailable causes:
ReturnMoments metadata does not match the query.BarSeries.700. An overflowing optional tail is omitted while usable central fields remain.Always check isStable() when inspecting a raw summary. Point adapters are safer for normal ta4j rule composition because unavailable values become NaN.NaN.
getValue(i) reads only data at or before i; the horizon describes the future outcome, not permission to read future bars. Compare a stored forecast with its realized value only after i + horizon matures. Fixed seeds make repeated evaluation deterministic, and extending a series with future bars does not change an already-computed decision-index forecast.
| Need | Use | Avoid |
|---|---|---|
| Exact simulated price distribution | MonteCarloPriceForecastIndicator |
Transforming summary moments after simulation. |
| Cumulative log-return distribution | MonteCarloReturnProjectionIndicator |
Treating returns as prices. |
| State-conditioned empirical log returns | AnalogReturnProjectionIndicator |
Letting current features influence training standardization. |
| Abrupt regime and run-length diagnostics | OnlineChangePointForecastStateIndicator |
Treating recent-change probability as a standalone trade signal. |
| Rolling tail calibration | RollingConformalForecastProjectionIndicator |
Counting calibration rows as forecast support. |
| Price approximation from moments only | LognormalApproximationPriceForecastIndicator |
Calling it empirical support. |
| Point value in a rule | projection.median(), .mean(), or .quantile(p) |
Reimplementing unstable checks. |
| Empirical custom model output | Forecast.ofSamples(...) |
Claiming analytic support. |
| Analytic custom model output | Forecast.builder(...) |
Overloading sampleCount() with training rows. |
| Type | Package | Purpose |
|---|---|---|
EwmaReturnForecastStateIndicator |
forecast |
Default return-moment state estimator. |
RoughVolatilityForecastStateIndicator |
forecast |
EWMA moments enriched with roughness, vol-of-vol, and cumulative horizon variance. |
OnlineChangePointForecastStateIndicator |
forecast |
Bayesian run-length state with recent-change posterior mass. |
MonteCarloReturnProjectionIndicator |
forecast |
Exact empirical cumulative log-return projection. |
AnalogReturnProjectionIndicator |
forecast |
State-conditioned weighted empirical log-return projection. |
RollingConformalForecastProjectionIndicator |
forecast |
Matured-error tail calibration that preserves base support. |
MonteCarloPriceForecastIndicator |
forecast |
Exact empirical terminal-price projection. |
Forecast / ForecastSupport |
forecast.projection |
Numeric distribution summary and provenance. |
ForecastProjectionIndicator |
forecast.projection |
Horizon-aware forecast indicator with point adapters. |
ReturnForecastProjectionIndicator |
forecast.projection |
Forecast projection with return semantics. |
LognormalApproximationPriceForecastIndicator |
forecast.adapters |
Explicit analytic lognormal price approximation. |
ForecastState / ReturnMomentState / ReturnMoments |
forecast.state |
Lifecycle and validated return-state composition. |
OnlineChangePointForecastState / RunLengthPosterior |
forecast.state |
Immutable regime state and typed complete-posterior component summaries. |
ForecastFeatureSchema / ForecastFeatureExtractor |
forecast.state |
Representation-bound model feature contract. |