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.

ta4j can serialize indicators, rules, and strategies to JSON. This lets you persist strategies to a database, share them as configuration files, or send them to Python or TypeScript consumers.

Serializing an indicator

Call toJson() on any indicator instance:
import org.ta4j.core.indicators.RSIIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;

ClosePriceIndicator close = new ClosePriceIndicator(series);
RSIIndicator rsi = new RSIIndicator(close, 14);

String rsiJson = rsi.toJson();
// Output:
// {"type":"RSIIndicator","parameters":{"barCount":14},
//  "components":[{"type":"ClosePriceIndicator"}]}
The JSON captures the indicator type, its numeric parameters, and the full chain of component indicators it depends on.

Serializing a rule

Rules use ComponentSerialization.toJson together with RuleSerialization.describe:
import org.ta4j.core.serialization.ComponentSerialization;
import org.ta4j.core.serialization.RuleSerialization;
import org.ta4j.core.rules.OverIndicatorRule;
import org.ta4j.core.rules.UnderIndicatorRule;
import org.ta4j.core.rules.AndRule;

Rule rule1   = new OverIndicatorRule(rsi, 50);
Rule rule2   = new UnderIndicatorRule(rsi, 80);
Rule andRule = new AndRule(rule1, rule2);

String ruleJson = ComponentSerialization.toJson(RuleSerialization.describe(andRule));
// Output:
// {"type":"AndRule","label":"AndRule","components":[
//   {"type":"OverIndicatorRule","label":"OverIndicatorRule",
//    "components":[{"type":"RSIIndicator","parameters":{"barCount":14},
//                   "components":[{"type":"ClosePriceIndicator"}]}],
//    "parameters":{"threshold":50.0}},
//   {"type":"UnderIndicatorRule","label":"UnderIndicatorRule",
//    "components":[{"type":"RSIIndicator",...}],
//    "parameters":{"threshold":80.0}}]}

Serializing a strategy

Call toJson() on any Strategy instance:
import org.ta4j.core.indicators.EMAIndicator;
import org.ta4j.core.rules.CrossedUpIndicatorRule;
import org.ta4j.core.rules.CrossedDownIndicatorRule;
import org.ta4j.core.BaseStrategy;

EMAIndicator fastEma = new EMAIndicator(close, 12);
EMAIndicator slowEma = new EMAIndicator(close, 26);

Rule entry = new CrossedUpIndicatorRule(fastEma, slowEma);
Rule exit  = new CrossedDownIndicatorRule(fastEma, slowEma);

Strategy strategy = new BaseStrategy("EMA Crossover", entry, exit);
String strategyJson = strategy.toJson();
// Output:
// {"type":"BaseStrategy","label":"EMA Crossover","parameters":{"unstableBars":0},
//  "rules":[
//    {"type":"CrossedUpIndicatorRule","label":"entry","components":[
//      {"type":"EMAIndicator","parameters":{"barCount":12},
//       "components":[{"type":"ClosePriceIndicator"}]},
//      {"type":"EMAIndicator","parameters":{"barCount":26},
//       "components":[{"type":"ClosePriceIndicator"}]}]},
//    {"type":"CrossedDownIndicatorRule","label":"exit","components":[...]}]}

Restoring from JSON

Pass the BarSeries and the JSON string to the static fromJson methods:
import org.ta4j.core.Indicator;
import org.ta4j.core.Strategy;

// Restore an indicator
Indicator<?> restoredRsi = Indicator.fromJson(series, rsiJson);

// Restore a strategy
Strategy restoredStrategy = Strategy.fromJson(series, strategyJson);

// Use the restored strategy just like the original
TradingRecord record = new BarSeriesManager(series).run(restoredStrategy);
The BarSeries argument anchors the restored objects to price data. Indicators recalculate lazily as they do when created normally.

BarSeries serialization notes

When serializing a BarSeries itself:
  • Bar data, the NumFactory, and the BarBuilderFactory configuration are preserved across the round-trip.
  • ConcurrentBarSeries reinitialises its internal locks after deserialization and recreates the trade bar builder lazily.
  • Builder state set directly on the builder (for example, a custom time period) must be re-applied after deserialization unless it was configured through the factory.

Use cases

Save a strategy to a database or file at the end of a research session. Restore it later without keeping the original Java source in scope.
// Save
String json = strategy.toJson();
Files.writeString(Path.of("strategies/ema-crossover.json"), json);

// Restore later
String saved = Files.readString(Path.of("strategies/ema-crossover.json"));
Strategy strategy = Strategy.fromJson(series, saved);
Export a strategy as JSON and share it with a colleague or publish it to a repository. The recipient only needs a BarSeries to instantiate it.
The JSON output is plain text and follows a self-describing structure. A Python or TypeScript consumer can parse it to understand what indicators and rules a strategy uses, even without running the Java backtest engine.This is useful for building trading dashboards that display strategy configuration, or for pipelines that generate strategy variants and pass them back to the Java executor.

Live trading

Restore serialized strategies on service restart.

Parallel backtesting

Generate and persist large numbers of strategy variants.