Documentation, examples and further information of the ta4j project
This project is maintained by ta4j Organization
Welcome! This guide walks you from “What is ta4j?” to running a validated backtest and knowing what to explore next. It assumes you are new to both the project and systematic technical-analysis trading.
If technical analysis is brand new to you, skim Wikipedia or Investopedia for the vocabulary we use throughout this guide.
ta4j is published on Maven Central as org.ta4j:ta4j-core.
Prefer to inspect the code? Clone ta4j and import the root Maven project—ta4j-core and ta4j-examples live side-by-side.
mvn -pl ta4j-examples test (or ./mvnw if you pulled the repo).ta4jexamples.Quickstart from your IDE.Now you know your toolchain, ta4j dependency, and plotting libraries are wired correctly.
| Concept | Description | Where to learn more |
|---|---|---|
BarSeries |
Ordered collection of bars (OHLCV data) used for all calculations. | Bar Series & Bars |
Num |
Precision-safe numeric abstraction (Decimal, Double, custom). | Num |
Indicator<T extends Num> |
Lazily evaluated time series derived from bars or other indicators. | Technical Indicators |
Rule / Strategy |
Boolean conditions that generate entry/exit signals; strategies pair entry + exit rules. | Trading Strategies |
BarSeriesManager & BacktestExecutor |
Drivers that run strategies against data and return a TradingRecord. |
Backtesting |
Why this matters: each component is composable. Bars feed indicators; indicators feed rules; rules feed strategies; strategies feed backtests. Once you understand one layer, the next is just another combination.
We will:
BarSeries series = new BaseBarSeriesBuilder()
.withName("bitstamp_btc")
.build();
try (InputStream csv = Files.newInputStream(Path.of("data/bitstamp_btc.csv"))) {
new BitstampCsvTradesDataSource().load(csv, series); // see ta4j-examples/datasources
}
Other options:
TimeBarBuilder, TickBarBuilder, VolumeBarBuilder, or the new AmountBarBuilder when aggregating streaming trades.series.addBar(...) directly—barBuilder() lets you specify beginTime or endTime depending on how the exchange reports timestamps.ClosePriceIndicator close = new ClosePriceIndicator(series);
SMAIndicator fastSma = new SMAIndicator(close, 5);
SMAIndicator slowSma = new SMAIndicator(close, 30);
MACDVIndicator macdv = new MACDVIndicator(series, 12, 26, 9); // uses volume weighting
Indicators are cached automatically. If you mutate the most recent bar (typical in live trading), ta4j recalculates the final value on demand.
If you specifically want the volatility-normalized MACD-V formulation ((EMAfast - EMAslow) / ATR * scale, often called Spiroglou-style), use VolatilityNormalizedMACDIndicator instead of MACDVIndicator.
Rule entryRule = new CrossedUpIndicatorRule(fastSma, slowSma)
.and(new OverIndicatorRule(macdv.getMacd(), series.numFactory().numOf(0)));
Rule exitRule = new CrossedDownIndicatorRule(fastSma, slowSma)
.or(new StopLossRule(close, series.numFactory().numOf(2.5)))
.or(new StopGainRule(close, series.numFactory().numOf(4.0)));
Strategy strategy = new BaseStrategy("SMA + MACDV swing", entryRule, exitRule);
strategy.setUnstableBars(30); // ignore early warm-up signals
Prefer reusable presets? Explore NamedStrategy implementations under org.ta4j.core.strategy.named. They can be serialized/deserialized, parameterized, and discovered at runtime via NamedStrategy.initializeRegistry(...).
BarSeriesManager manager = new BarSeriesManager(series);
TradingRecord record = manager.run(strategy);
System.out.printf("Trades: %d%n", record.getPositionCount());
For large strategy grids or long histories, switch to the new BacktestExecutor:
BacktestExecutor executor = new BacktestExecutor(series);
BacktestExecutionResult batch = executor.executeWithRuntimeReport(
strategies,
series.numFactory().numOf(1),
Trade.TradeType.BUY,
ProgressCompletion.logging("getting-started"));
List<TradingStatement> topRuns = batch.getTopStrategies(10, new NetReturnCriterion());
executeWithRuntimeReport collects trading statements plus runtime analytics, while getTopStrategies helps you home in on the best parameter sets without hand-rolling a sorter. The snippet wires everything up manually; if you prefer a full working example, inspect ta4jexamples.backtesting.TopStrategiesExampleBacktest.
AnalysisCriterion netReturn = new NetReturnCriterion();
AnalysisCriterion romad = new ReturnOverMaxDrawdownCriterion();
AnalysisCriterion commissions = new CommissionsImpactPercentageCriterion();
System.out.printf("Net return: %s%n", netReturn.calculate(series, record));
System.out.printf("Return / Max Drawdown: %s%n", romad.calculate(series, record));
System.out.printf("Commission drag: %s%n", commissions.calculate(series, record));
Need deeper insight?
SharpeRatioCriterion.MonteCarloMaximumDrawdownCriterion.InPositionPercentageCriterion.MaxConsecutiveLossCriterion and MaxConsecutiveProfitCriterion.TotalFeesCriterion; open-position cost basis and unrealized PnL: OpenPositionCostBasisCriterion, OpenPositionUnrealizedProfitCriterion (with LiveTradingRecord).new BaseTradingStatement(strategy, record) exposes trades, exposure, and commission totals.| Goal | Where to go |
|---|---|
| Load better data | Bar Series & Bars covers CSV datasources, bar builders, and moving series. |
| Explore indicator coverage | Technical Indicators + Moving Averages list every indicator family, including Renko helpers and Net Momentum. |
| Compare many parameter sets | See Trading Strategies for best practices plus VoteRule tips for ensembles. |
| Persist and share strategies | Use StrategySerialization / Strategy.fromJson(...) (documented in Trading Strategies). |
| Prepare for live trading | Read Live Trading for architecture patterns, bar updates, and trade execution models. |
| Track partial fills, cost basis, or unrealized PnL | Use LiveTradingRecord and the walkthrough there for code examples and criteria. |
ta4j-examples.System.out.println(“Return over Max Drawdown: “ + romad.calculate(series, tradingRecord));
// Net return of our strategy vs net return of a buy-and-hold strategy AnalysisCriterion vsBuyAndHold = new VersusEnterAndHoldCriterion(new NetReturnCriterion()); System.out.println(“Our net return vs buy-and-hold net return: “ + vsBuyAndHold.calculate(series, tradingRecord));
Trading strategies can be easily compared according to [a set of analysis criteria](/ta4j-wiki/Backtesting.html).
##### Visualizing your results
Ta4j provides powerful charting capabilities through the `ChartWorkflow` class and its fluent `ChartBuilder` API. You can create charts with price data, indicators, trading signals, and performance metrics.
**Basic chart with trading signals**:
```java
// Create a chart with trading record overlay
ChartWorkflow chartWorkflow = new ChartWorkflow();
chartWorkflow.builder()
.withSeries(series)
.withTradingRecordOverlay(tradingRecord)
.display();
Advanced chart with indicators and performance metrics:
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator sma = new SMAIndicator(closePrice, 50);
chartWorkflow.builder()
.withSeries(series)
.withTradingRecordOverlay(tradingRecord)
.withIndicatorOverlay(sma)
.withLineColor(Color.ORANGE)
// Visualize net profit over time using AnalysisCriterionIndicator
.withAnalysisCriterionOverlay(new NetProfitCriterion(), tradingRecord)
.withLineColor(Color.GREEN)
.display();
Key features:
AnalysisCriterionIndicator to track performance metrics (profit, return, drawdown) over timeSee the Charting Guide for comprehensive documentation on creating sophisticated trading charts, including sub-charts, custom styling, and advanced examples.
Ta4j can also be used for live trading with more complicated strategies. Check out the rest of the documentation and the examples.