Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ta4j/ta4j/llms.txt

Use this file to discover all available pages before exploring further.

Analysis criteria measure a single aspect of strategy performance — returns, drawdown, win rate, or cost — and return a Num value. They share a common interface that makes it straightforward to swap metrics or combine them for strategy ranking.

The AnalysisCriterion interface

public interface AnalysisCriterion {
    // Evaluate over all positions in a trading record
    Num calculate(BarSeries series, TradingRecord tradingRecord);

    // Evaluate for a single position
    Num calculate(BarSeries series, Position position);

    // Compare two criterion values — each criterion defines what "better" means
    boolean betterThan(Num criterionValue1, Num criterionValue2);
}

AnalysisWindow for scoped analysis

Calculate any criterion over a sub-range of bars or a date range without re-running the backtest:
import org.ta4j.core.analysis.AnalysisWindow;
import java.time.Duration;
import java.time.Instant;

AnalysisCriterion criterion = new NetReturnCriterion();

// Past 30 days
Num last30 = criterion.calculate(series, record,
        AnalysisWindow.lookbackDuration(Duration.ofDays(30)));

// Explicit date range
Num q1 = criterion.calculate(series, record,
        AnalysisWindow.timeRange(
                Instant.parse("2024-01-01T00:00:00Z"),
                Instant.parse("2024-04-01T00:00:00Z")));

// Last N bars
Num last100bars = criterion.calculate(series, record,
        AnalysisWindow.lookbackBars(100));

Benchmark comparison

Simulates a buy-and-hold baseline: enter at the close of the first bar, exit at the close of the last bar. Wrap any criterion to get its buy-and-hold equivalent.
// Net return of a simple buy-and-hold over the same period
EnterAndHoldCriterion buyAndHold = new EnterAndHoldCriterion(
        TradeType.BUY, new NetReturnCriterion());

Num holdReturn = buyAndHold.calculate(series, record);
Use the factory method for the most common case:
EnterAndHoldCriterion baseline = EnterAndHoldCriterion.EnterAndHoldReturnCriterion();
Computes a criterion for the active strategy and divides it by the same criterion calculated for a buy-and-hold baseline — giving a relative performance ratio.
VersusEnterAndHoldCriterion vs = new VersusEnterAndHoldCriterion(
        TradeType.BUY, new NetReturnCriterion());

Num ratio = vs.calculate(series, record);
// ratio > 1.0 means the strategy outperformed buy-and-hold

Criteria by category

Criteria in the org.ta4j.core.criteria.pnl package measure profit, loss, and return at various levels of aggregation.
Total net return (after costs) over all positions. Returns a multiplicative factor by default (e.g., 1.15 for +15%).
new NetReturnCriterion()
new NetReturnCriterion(ReturnRepresentation.PERCENTAGE)
Total net profit in currency units.
new NetProfitCriterion()
Net profit minus net loss across all closed positions (signed currency amount).
new NetProfitLossCriterion()
Total gross return before transaction costs.
new GrossReturnCriterion()
Sum of all profitable position gains before costs.
new GrossProfitCriterion()
Sum of all losing position losses before costs (returned as a non-negative value).
new GrossLossCriterion()
Gross profit minus gross loss across all closed positions.
new GrossProfitLossCriterion()
Gross profit/loss expressed as a percentage of invested capital.
new GrossProfitLossPercentageCriterion()
Ratio of gross profit to gross loss (profit factor).
new GrossProfitLossRatioCriterion()
Net profit/loss as a percentage of invested capital.
new NetProfitLossPercentageCriterion()
Ratio of net profit to net loss.
new NetProfitLossRatioCriterion()
Average net profit per winning position, or average net loss per losing position.
new NetAverageProfitCriterion()
new NetAverageLossCriterion()
Average gross profit or gross loss per position.
new GrossAverageProfitCriterion()
new GrossAverageLossCriterion()
Longest consecutive winning or losing streak (position count).
new MaxConsecutiveProfitCriterion()
new MaxConsecutiveLossCriterion()
Largest single-position net profit or net loss across the trading record.
new MaxPositionNetProfitCriterion()
new MaxPositionNetLossCriterion()
Average return per bar over the full series duration — useful for comparing strategies with different holding periods.
new AverageReturnPerBarCriterion()
Criteria in org.ta4j.core.criteria.drawdown measure peak-to-trough losses in the equity curve.
Maximum peak-to-trough decline of the equity curve, expressed as a decimal in [0, 1] (e.g., 0.20 = 20% drawdown). Lower values are better.
new MaximumDrawdownCriterion()

// With explicit equity curve mode
new MaximumDrawdownCriterion(EquityCurveMode.MARK_TO_MARKET,
                              OpenPositionHandling.IGNORE)
Maximum drawdown in absolute currency units rather than as a percentage.
new MaximumAbsoluteDrawdownCriterion()
Duration of the maximum drawdown period, expressed in bars.
new MaximumDrawdownBarLengthCriterion()
Net return divided by maximum drawdown. Higher is better — rewards strategies that earn more per unit of drawdown risk.
// Use the canonical location (not the deprecated alias)
new org.ta4j.core.criteria.drawdown.ReturnOverMaxDrawdownCriterion()
org.ta4j.core.criteria.ReturnOverMaxDrawdownCriterion is deprecated since 0.19 and will be removed in 0.24.0. Use org.ta4j.core.criteria.drawdown.ReturnOverMaxDrawdownCriterion directly.
Monte Carlo simulation of the maximum drawdown by randomly permuting the order of closed positions. Useful for estimating worst-case drawdown risk.
new MonteCarloMaximumDrawdownCriterion(1000)   // 1000 simulation runs
Count and classify positions in the trading record.
Total number of closed positions.
new NumberOfPositionsCriterion()
Number of positions that closed with a net profit.
new NumberOfWinningPositionsCriterion()
Number of positions that closed with a net loss.
new NumberOfLosingPositionsCriterion()
Number of positions that closed at exactly zero net profit/loss.
new NumberOfBreakEvenPositionsCriterion()
Ratio of a filtered position count to the total — for example, the win rate.
// Win rate: winning positions / total positions
new PositionsRatioCriterion(AnalysisCriterion.PositionFilter.PROFIT)
Maximum number of consecutive positions of the specified type (profit or loss).
new NumberOfConsecutivePositionsCriterion(AnalysisCriterion.PositionFilter.PROFIT)
Fraction of total bars during which a position was open. Higher values indicate the strategy is more frequently invested.
new InPositionPercentageCriterion()
Total number of bars covered by the trading record.
new NumberOfBarsCriterion()
Average duration of closed positions, in bars.
new PositionDurationCriterion()
Mathematical expectancy: (winRate × avgWin) - (lossRate × avgLoss). Positive values indicate a profitable edge on average.
new ExpectancyCriterion()
Total transaction costs assuming a linear (percentage-based) cost model.
new LinearTransactionCostCriterion(series.numFactory().numOf(0.001)) // 0.1% per trade
Cost basis of any currently open position (entry price × quantity, including costs).
new OpenPositionCostBasisCriterion()
Unrealized profit or loss of the current open position at the last bar’s close price.
new OpenPositionUnrealizedProfitCriterion()

Calculating multiple criteria at once

import org.ta4j.core.*;
import org.ta4j.core.criteria.pnl.*;
import org.ta4j.core.criteria.drawdown.*;
import org.ta4j.core.criteria.*;
import org.ta4j.core.backtest.BarSeriesManager;

BarSeries series = /* your data source */;
Strategy strategy = /* your strategy */;

TradingRecord record = new BarSeriesManager(series).run(strategy);

// PnL
Num netReturn   = new NetReturnCriterion().calculate(series, record);
Num netProfit   = new NetProfitCriterion().calculate(series, record);
Num grossPnL    = new GrossProfitLossCriterion().calculate(series, record);

// Drawdown
Num maxDD       = new org.ta4j.core.criteria.drawdown
                      .MaximumDrawdownCriterion().calculate(series, record);
Num roMaD       = new org.ta4j.core.criteria.drawdown
                      .ReturnOverMaxDrawdownCriterion().calculate(series, record);

// Trade stats
Num totalTrades = new NumberOfPositionsCriterion().calculate(series, record);
Num winRate     = new PositionsRatioCriterion(
                      AnalysisCriterion.PositionFilter.PROFIT).calculate(series, record);
Num expectancy  = new ExpectancyCriterion().calculate(series, record);

System.out.printf("Net return:    %.2f%%%n", netReturn.doubleValue() * 100 - 100);
System.out.printf("Max drawdown:  %.2f%%%n", maxDD.doubleValue() * 100);
System.out.printf("RoMaD:         %.2f%n",  roMaD.doubleValue());
System.out.printf("Win rate:      %.1f%%%n", winRate.doubleValue() * 100);
System.out.printf("Expectancy:    %.4f%n",   expectancy.doubleValue());
Use AnalysisWindow to calculate rolling metrics for monitoring live strategy health without re-running the full backtest:
Num rolling30dReturn = new NetReturnCriterion().calculate(
        series, record, AnalysisWindow.lookbackDuration(Duration.ofDays(30)));