{"id":13591152,"url":"https://github.com/ta4j/ta4j","last_synced_at":"2026-03-16T01:58:06.719Z","repository":{"id":37270519,"uuid":"103560333","full_name":"ta4j/ta4j","owner":"ta4j","description":"A Java library for technical analysis.","archived":false,"fork":false,"pushed_at":"2025-02-26T16:47:06.000Z","size":11099,"stargazers_count":2184,"open_issues_count":50,"forks_count":746,"subscribers_count":119,"default_branch":"master","last_synced_at":"2025-04-23T20:57:54.968Z","etag":null,"topics":["bitcoin","ethereum","forex","java","java-library","litecoin","ripple","stocks","ta4j","tachnical-analysis","technical-analysis","trading","trading-algorithms","trading-strategies"],"latest_commit_sha":null,"homepage":"http://www.ta4j.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ta4j.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-14T17:14:32.000Z","updated_at":"2025-04-21T08:53:47.000Z","dependencies_parsed_at":"2024-01-03T01:20:48.419Z","dependency_job_id":"faec73ea-fc37-4e67-84d3-ce83da2e4138","html_url":"https://github.com/ta4j/ta4j","commit_stats":{"total_commits":1229,"total_committers":90,"mean_commits":"13.655555555555555","dds":0.7119609438567942,"last_synced_commit":"4755270e61e2478a66a65c1c9606e50be6c02204"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ta4j%2Fta4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ta4j%2Fta4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ta4j%2Fta4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ta4j%2Fta4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ta4j","download_url":"https://codeload.github.com/ta4j/ta4j/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250514767,"owners_count":21443208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","ethereum","forex","java","java-library","litecoin","ripple","stocks","ta4j","tachnical-analysis","technical-analysis","trading","trading-algorithms","trading-strategies"],"created_at":"2024-08-01T16:00:54.177Z","updated_at":"2026-03-16T01:58:06.706Z","avatar_url":"https://github.com/ta4j.png","language":"Java","readme":"# ta4j  [![Build and Test](https://github.com/ta4j/ta4j/actions/workflows/test.yml/badge.svg)](https://github.com/ta4j/ta4j/actions/workflows/test.yml) [![Discord](https://img.shields.io/discord/745552125769023488.svg?label=\u0026logo=discord\u0026logoColor=ffffff\u0026color=7389D8\u0026labelColor=6A7EC2)](https://discord.gg/HX9MbWZ) [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) ![Maven Central](https://img.shields.io/maven-central/v/org.ta4j/ta4j-parent?color=blue\u0026label=Version) ![JDK](https://img.shields.io/badge/JDK-21%2B-orange)\n\n***Technical Analysis for Java***\n\n![Ta4j main chart](https://raw.githubusercontent.com/ta4j/ta4j-wiki/master/img/ta4j_main_chart.png)\n\nBuild, test, and deploy trading bots in Java. With 200+ (and counting) technical indicators, intuitive APIs, and production-minded tooling, you can explore markets, validate trading ideas, visualize signals, and ship automated bots without leaving the JVM.\n\n---\n\n## Table of Contents\n\n- [Why Ta4j?](#why-ta4j)\n- [Install in seconds](#install-in-seconds)\n- [Build commands: Maven Wrapper or Maven](#build-commands-maven-wrapper-or-maven)\n- [Quick start: Your first strategy](#quick-start-your-first-strategy)\n- [Sourcing market data](#sourcing-market-data)\n- [Visualize and share strategies](#visualize-and-share-strategies)\n- [Features at a glance](#features-at-a-glance)\n- [Evaluate performance with metrics](#evaluate-performance-with-metrics)\n- [From backtest to live trading](#from-backtest-to-live-trading)\n- [Real-world examples](#real-world-examples)\n- [Performance](#performance)\n- [Community \u0026 Support](#community--support)\n- [What's next?](#whats-next)\n- [Contributing](#contributing)\n\n---\n\n## Why Ta4j?\n\n**Build, test, and deploy trading strategies in Java** without leaving your preferred language, toolchain, or mental model. Ta4j provides the building blocks needed to explore markets, validate ideas, and move from curiosity to production-grade systems.\n\nTa4j treats technical analysis for what it is: a structured way to reason about uncertainty using historical price data. As often stated, past performance is no guarantee of future results. History doesn't repeat, but it often rhymes. Technical indicators are about probabilities rather than predictions. They help us understand the art of the possible and, when used well, the art of alpha from the probable. \n\n\u003e **⚡ Performance Advantage**: Native multi-threading gives ta4j a significant comparative advantage over Python-based libraries. Backtest hundreds of strategies in parallel, process years of market data in seconds, and saturate all CPU cores. No GIL bottleneck, no multiprocessing workarounds, just straightforward parallel execution.\n\nBecause Ta4j runs on the JVM, strategies scale naturally from a single backtest on a laptop to large parameter sweeps, portfolio simulations, and research pipelines. Strong typing and explicit models make strategies easier to reason about, harder to misuse, and less likely to quietly do the wrong thing.\n\nTa4j does not promise profitable strategies. It promises reproducible experiments. If a strategy looks good, Ta4j helps you verify it. If it stops working, Ta4j helps you understand why. And if a backtest looks too good to be true, it's on you to choose skepticism over motivated thinking.\n\n\n### What can you build?\n\n- **Backtest trading strategies**: Test \"what if\" scenarios on historical data before risking real money\n- **Paper trading bots**: Run strategies live against market data without placing real orders\n- **Research tools**: Analyze market patterns, compare indicators, and explore new trading ideas\n- **Automated trading systems**: Deploy production bots that execute trades based on your strategies\n- **Market analysis dashboards**: Build visualizations and reports for your trading research\n\n### Why Java developers choose Ta4j\n\n- **Pure Java, zero friction**: Works anywhere Java 21+ runs - cloud functions, desktop tools, microservices, or trading bots. No Python bridges or external dependencies.\n- **Type-safe, Production-ready**: Ta4j favors explicit models, strong typing, and predictable performance over exploratory scripting. Deterministic outputs, JSON serialization for strategies/indicators, and minimal dependencies make it easy to deploy.\n- **Huge indicator catalog**: Aroon, ATR, Ichimoku, MACD, RSI, Renko, Heikin-Ashi, and 190+ more ready to plug together. New indicators are added regularly based on community needs and contributions.\n- **Composable strategies**: Chain rules fluently using familiar Java patterns - no DSLs or configuration files required.\n- **Backtesting built-in**: Evaluate risk/reward with realistic trading costs and performance metrics in just a few lines.\n- **MIT licensed**: Use it at work, in research, or inside your next trading product without legal concerns.\n\n## Install in seconds\n\nAdd Ta4j from Maven Central:\n\n\u003c!-- TA4J_VERSION_BLOCK:core:stable:begin --\u003e\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.ta4j\u003c/groupId\u003e\n  \u003cartifactId\u003eta4j-core\u003c/artifactId\u003e\n  \u003cversion\u003e0.22.4\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003c!-- TA4J_VERSION_BLOCK:core:stable:end --\u003e\n\nPrefer living on the edge? Use the snapshot repository and version:\n\n\u003c!-- TA4J_VERSION_BLOCK:core:snapshot:begin --\u003e\n\n```xml\n\u003crepository\u003e\n  \u003cid\u003ecentral-portal-snapshots\u003c/id\u003e\n  \u003curl\u003ehttps://central.sonatype.com/repository/maven-snapshots/\u003c/url\u003e\n\u003c/repository\u003e\n\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.ta4j\u003c/groupId\u003e\n  \u003cartifactId\u003eta4j-core\u003c/artifactId\u003e\n  \u003cversion\u003e0.22.5-SNAPSHOT\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003c!-- TA4J_VERSION_BLOCK:core:snapshot:end --\u003e\n\nSample applications are also published so you can copy/paste entire flows:\n\n\u003c!-- TA4J_VERSION_BLOCK:examples:stable:begin --\u003e\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.ta4j\u003c/groupId\u003e\n  \u003cartifactId\u003eta4j-examples\u003c/artifactId\u003e\n  \u003cversion\u003e0.22.4\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003c!-- TA4J_VERSION_BLOCK:examples:stable:end --\u003e\n\nLike living on the edge? Use the snapshot version of ta4j-examples for the latest experimental/beta features:\n\n\u003c!-- TA4J_VERSION_BLOCK:examples:snapshot:begin --\u003e\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.ta4j\u003c/groupId\u003e\n  \u003cartifactId\u003eta4j-examples\u003c/artifactId\u003e\n  \u003cversion\u003e0.22.5-SNAPSHOT\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003c!-- TA4J_VERSION_BLOCK:examples:snapshot:end --\u003e\n\n**💡 Tip**: The `ta4j-examples` module includes runnable demos, data loaders, and charting utilities. It's a great way to see Ta4j in action and learn by example.\n\n## Build commands: Maven Wrapper or Maven\n\nTa4j supports both approaches:\n\n- **Maven Wrapper (recommended):** Uses the repository-pinned Maven version and avoids requiring a global Maven installation.\n  Linux/macOS/Git Bash: `./mvnw ...`\n  Windows CMD/PowerShell: `mvnw.cmd ...`\n- **System Maven (optional):** Use `mvn ...` if you prefer your local Maven installation.\n\n## Try it now\n\n**Option 1: Run the Quickstart example** (2-3 minutes)\n\n```bash\n# Clone the repository\ngit clone https://github.com/ta4j/ta4j.git\ncd ta4j\n\n# Build the project first (Linux/macOS/Git Bash)\n./mvnw clean install -DskipTests\n# Windows CMD/PowerShell: mvnw.cmd clean install -DskipTests\n\n# Run the Quickstart example (Quickstart is configured as the default)\n./mvnw -pl ta4j-examples exec:java\n# Windows CMD/PowerShell: mvnw.cmd -pl ta4j-examples exec:java\n```\n\nPrefer system Maven? Use the same commands with `mvn` instead of `./mvnw` or `mvnw.cmd`.\n\n**Alternative:** To run a different example class:\n```bash\n# On Linux/Mac/Git Bash\n./mvnw -pl ta4j-examples exec:java -Dexec.mainClass=ta4jexamples.Quickstart\n\n# On Windows CMD (use quotes)\nmvnw.cmd -pl ta4j-examples exec:java \"-Dexec.mainClass=ta4jexamples.Quickstart\"\n```\n\nThis will load historical Bitcoin data, run a complete trading strategy, display performance metrics, and show an interactive chart - all in one go!\n\n**Option 2: Copy the code into your project** (requires `ta4j-core` and `ta4j-examples` dependencies)\n\nSee the [Quick start: Your first strategy](#quick-start-your-first-strategy) section below for a complete, runnable example you can paste into your IDE.\n\n## Quick start: Your first strategy\n\nLoad price data, plug in indicators, and describe when to enter/exit. The API reads like the trading notes you already keep.\n\n**💡 Want to see this in action?** The [`Quickstart` example](https://github.com/ta4j/ta4j/blob/master/ta4j-examples/src/main/java/ta4jexamples/Quickstart.java) includes this same pattern plus performance metrics and charting. Run it with:\n```bash\n./mvnw -pl ta4j-examples exec:java -Dexec.mainClass=ta4jexamples.Quickstart\n```\n\n**Key concepts:**\n- **Indicators**: Calculate values from price data (e.g., moving averages, RSI, MACD)\n- **Rules**: Boolean conditions that determine when to enter or exit trades\n- **Strategies**: Combine entry and exit rules into a complete trading system\n- **BarSeries**: Your price data (OHLCV bars) that everything operates on\n\n**Note:** The example below uses `BitStampCsvTradesFileBarSeriesDataSource` from `ta4j-examples` for convenience. See the [Sourcing market data](#sourcing-market-data) section below for more options.\n\n```java\nimport org.ta4j.core.*;\nimport org.ta4j.core.indicators.EMAIndicator;\nimport org.ta4j.core.indicators.helpers.ClosePriceIndicator;\nimport org.ta4j.core.rules.*;\nimport org.ta4j.core.backtest.BarSeriesManager;\nimport ta4jexamples.datasources.BitStampCsvTradesFileBarSeriesDataSource;  // Requires ta4j-examples dependency\n\n// Load historical price data (or use your own data source)\nBarSeries series = BitStampCsvTradesFileBarSeriesDataSource.loadBitstampSeries();\n\n// Create indicators: calculate moving averages from close prices\nClosePriceIndicator close = new ClosePriceIndicator(series);\nEMAIndicator fastEma = new EMAIndicator(close, 12);  // 12-period EMA\nEMAIndicator slowEma = new EMAIndicator(close, 26);  // 26-period EMA\n\n// Define entry rule: buy when fast EMA crosses above slow EMA (golden cross)\nRule entry = new CrossedUpIndicatorRule(fastEma, slowEma);\n\n// Define exit rule: sell when price gains 3% OR loses 1.5%\nRule exit = new StopGainRule(close, 3.0)      // take profit at +3%\n        .or(new StopLossRule(close, 1.5));    // or cut losses at -1.5%\n\n// Combine rules into a strategy\nStrategy strategy = new BaseStrategy(\"EMA Crossover\", entry, exit);\n\n// Run the strategy on historical data\nBarSeriesManager manager = new BarSeriesManager(series);\nTradingRecord record = manager.run(strategy);\n\n// See the results\nSystem.out.println(\"Number of trades: \" + record.getTradeCount());\nSystem.out.println(\"Number of positions: \" + record.getPositionCount());\n```\n\n## Sourcing market data\n\n**New to trading and not sure where to get historical price data?** You're not alone! Ta4j makes it easy to get started with real market data using the unified `BarSeriesDataSource` interface. All data sources work with the same domain-driven API using business concepts like ticker symbols, intervals, and date ranges.\n\n### Quick solution: Yahoo Finance (no API key required)\n\nThe easiest way to get started is using the built-in `YahooFinanceHttpBarSeriesDataSource` from `ta4j-examples`. It fetches real market data from Yahoo Finance's public API - no registration or API key needed.\n\n**Using the unified interface (recommended):**\n```java\nimport ta4jexamples.datasources.YahooFinanceHttpBarSeriesDataSource;\nimport java.time.Duration;\nimport java.time.Instant;\n\n// Enable response caching to avoid hitting API limits during development\nYahooFinanceHttpBarSeriesDataSource dataSource = new YahooFinanceHttpBarSeriesDataSource(true);\n\n// Load data using the unified interface (works with any data source)\nBarSeries series = dataSource.loadSeries(\"AAPL\", \n    Duration.ofDays(1),  // Daily bars\n    Instant.parse(\"2023-01-01T00:00:00Z\"),\n    Instant.parse(\"2023-12-31T23:59:59Z\"));\n```\n\n**Using convenience methods:**\n```java\n// Load by bar count (e.g., 2 years of daily candles)\nBarSeries series = dataSource.loadSeriesInstance(\"AAPL\", \n    YahooFinanceHttpBarSeriesDataSource.YahooFinanceInterval.DAY_1, 730);\n\n// Or use static convenience methods\nBarSeries series = YahooFinanceHttpBarSeriesDataSource.loadSeries(\"AAPL\", 365); // 1 year of daily data\nBarSeries series = YahooFinanceHttpBarSeriesDataSource.loadSeries(\"BTC-USD\", \n    YahooFinanceHttpBarSeriesDataSource.YahooFinanceInterval.HOUR_1, 500); // 500 hourly bars\n```\n\n**Supported assets:**\n- **Stocks**: `\"AAPL\"`, `\"MSFT\"`, `\"GOOGL\"`, `\"TSLA\"`, etc.\n- **ETFs**: `\"SPY\"`, `\"QQQ\"`, `\"VTI\"`, etc.\n- **Cryptocurrencies**: `\"BTC-USD\"`, `\"ETH-USD\"`, `\"SOL-USD\"`, etc.\n\n**Supported intervals:**\n- Intraday: `MINUTE_1`, `MINUTE_5`, `MINUTE_15`, `MINUTE_30`, `HOUR_1`, `HOUR_4`\n- Daily/weekly/monthly: `DAY_1`, `WEEK_1`, `MONTH_1`\n\n**💡 Tip:** Enable caching (`new YahooFinanceHttpBarSeriesDataSource(true)`) to cache API responses locally. This speeds up development and reduces API calls. Cached data is automatically reused for the same requests.\n\n**See it in action:** Run the complete example with:\n```bash\n./mvnw -pl ta4j-examples exec:java -Dexec.mainClass=ta4jexamples.backtesting.YahooFinanceBacktest\n```\n\nThis example demonstrates loading data from Yahoo Finance, building an advanced multi-indicator strategy (Bollinger Bands, RSI, ATR stops), running a backtest, and visualizing results.\n\n### Coinbase (cryptocurrency data)\n\nFor cryptocurrency data, use `CoinbaseHttpBarSeriesDataSource` which fetches data from Coinbase's public market data API. No authentication required.\n\n```java\nimport ta4jexamples.datasources.CoinbaseHttpBarSeriesDataSource;\nimport java.time.Duration;\nimport java.time.Instant;\n\n// Enable response caching\nCoinbaseHttpBarSeriesDataSource dataSource = new CoinbaseHttpBarSeriesDataSource(true);\n\n// Using the unified interface\nBarSeries series = dataSource.loadSeries(\"BTC-USD\", \n    Duration.ofDays(1),\n    Instant.parse(\"2023-01-01T00:00:00Z\"),\n    Instant.parse(\"2023-12-31T23:59:59Z\"));\n\n// Or use convenience methods\nBarSeries series = CoinbaseHttpBarSeriesDataSource.loadSeries(\"BTC-USD\", 365); // 1 year of daily data\nBarSeries series = dataSource.loadSeriesInstance(\"ETH-USD\", \n    CoinbaseHttpBarSeriesDataSource.CoinbaseInterval.ONE_HOUR, 500); // 500 hourly bars\n```\n\n**Supported trading pairs:** All Coinbase trading pairs (e.g., `\"BTC-USD\"`, `\"ETH-USD\"`, `\"SOL-USD\"`)\n\n**API limits:** Coinbase API has a maximum of 350 candles per request. The implementation automatically paginates large requests into multiple API calls and merges the results.\n\n**See it in action:** Run the complete example with:\n```bash\n./mvnw -pl ta4j-examples exec:java -Dexec.mainClass=ta4jexamples.backtesting.CoinbaseBacktest\n```\n\n### Other data sources\n\nTa4j works with any OHLCV (Open, High, Low, Close, Volume) data. The `ta4j-examples` module includes implementations for several data sources, all using the unified `BarSeriesDataSource` interface:\n\n- **[YahooFinanceHttpBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/YahooFinanceHttpBarSeriesDataSource.java)** - Fetch live data from Yahoo Finance API (stocks, ETFs, crypto) with optional response caching\n- **[CoinbaseHttpBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/CoinbaseHttpBarSeriesDataSource.java)** - Load historical crypto data from Coinbase's public API with automatic caching and pagination\n- **[CsvFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/CsvFileBarSeriesDataSource.java)** - Load OHLCV data from CSV files with intelligent filename pattern matching\n- **[JsonFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/JsonFileBarSeriesDataSource.java)** - Load Coinbase/Binance-style JSON bar data with flexible date filtering\n- **[BitStampCsvTradesFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/BitStampCsvTradesFileBarSeriesDataSource.java)** - Aggregate Bitstamp trade-level CSV data into bars on-the-fly\n\n**All data sources share the same interface:**\n```java\nBarSeriesDataSource yahoo = new YahooFinanceHttpBarSeriesDataSource(true);\nBarSeriesDataSource coinbase = new CoinbaseHttpBarSeriesDataSource(true);\nBarSeriesDataSource csv = new CsvFileBarSeriesDataSource();\n\n// Same interface, different implementations\nBarSeries aapl = yahoo.loadSeries(\"AAPL\", Duration.ofDays(1), start, end);\nBarSeries btc = coinbase.loadSeries(\"BTC-USD\", Duration.ofDays(1), start, end);\nBarSeries eth = csv.loadSeries(\"ETH-USD\", Duration.ofDays(1), start, end);\n```\n\n**Create your own data source:** Simply implement the `BarSeriesDataSource` interface. You can load data from:\n- CSV files\n- REST APIs (your broker, exchange, or data provider)\n- Databases (SQL, NoSQL)\n- WebSocket streams (for live data)\n- Any other source you prefer\n\nSee the [Data Loading Examples](#real-world-examples) section for more details.\n\n## Evaluate performance with metrics\n\nTurn ideas into numbers. Add trading costs for realism and measure what matters: returns, risk, drawdowns, and more.\n\n```java\nimport org.ta4j.core.criteria.pnl.NetReturnCriterion;\nimport org.ta4j.core.criteria.drawdown.MaximumDrawdownCriterion;\nimport org.ta4j.core.cost.LinearTransactionCostModel;\nimport org.ta4j.core.cost.LinearBorrowingCostModel;\n\n// Run backtest with realistic trading costs\n// Transaction cost: 0.1% per trade (typical for crypto exchanges)\n// Borrowing cost: 0.01% per period (for margin/short positions)\nTradingRecord record = new BarSeriesManager(series,\n        new LinearTransactionCostModel(0.001),      // 0.1% fee per trade\n        new LinearBorrowingCostModel(0.0001))       // 0.01% borrowing cost\n        .run(strategy);\n\n// Calculate performance metrics\nSystem.out.printf(\"Trades executed: %d%n\", record.getTradeCount());\nSystem.out.printf(\"Net return: %.2f%%%n\", \n    new NetReturnCriterion().calculate(series, record).multipliedBy(series.numOf(100)));\nSystem.out.printf(\"Max drawdown: %.2f%%%n\", \n    new MaximumDrawdownCriterion().calculate(series, record).multipliedBy(series.numOf(100)));\n\n// Explore more metrics: Sharpe ratio, win rate, profit factor, etc.\n// See the wiki for the full list of available criteria\n```\n\nYou can also swap in execution models that simulate slippage and order-book-style\nfills:\n\n```java\nimport org.ta4j.core.backtest.SlippageExecutionModel;\nimport org.ta4j.core.backtest.StopLimitExecutionModel;\n\n// Example 1: next-open execution with 5 bps slippage\nTradingRecord slippageRecord = new BarSeriesManager(series,\n        new SlippageExecutionModel(series.numFactory().numOf(0.0005)))\n        .run(strategy);\n\n// Example 2: stop-limit orders with partial fills (max 25% bar-volume participation)\nTradingRecord stopLimitRecord = new BarSeriesManager(series,\n        new StopLimitExecutionModel(\n                series.numFactory().numOf(0.003),  // stop trigger ratio\n                series.numFactory().numOf(0.004),  // limit offset ratio\n                series.numFactory().numOf(0.25),   // max bar participation\n                4))                                // order TTL in bars\n        .run(strategy, strategy.getStartingType(), series.numFactory().numOf(10));\n```\n\nWant a runnable side-by-side demo? `ta4j-examples` now includes\n`TradingRecordParityBacktest`, which compares next-open, current-close, and\nslippage fills on the same strategy and then shows the same setup with provided\nand factory-configured `BaseTradingRecord` flows.\n\n### Backtest hundreds or even thousands of strategies\n\nWant to find the top performers? Generate strategies with varying parameters and compare them:\n\n```java\n// Generate strategies with varying parameters\nList\u003cStrategy\u003e strategies = new ArrayList\u003c\u003e();\nfor (int fastPeriod = 5; fastPeriod \u003c= 20; fastPeriod += 5) {\n    for (int slowPeriod = 20; slowPeriod \u003c= 50; slowPeriod += 10) {\n        EMAIndicator fastEma = new EMAIndicator(close, fastPeriod);\n        EMAIndicator slowEma = new EMAIndicator(close, slowPeriod);\n        Rule entry = new CrossedUpIndicatorRule(fastEma, slowEma);\n        Rule exit = new CrossedDownIndicatorRule(fastEma, slowEma);\n        strategies.add(new BaseStrategy(\"EMA(\" + fastPeriod + \",\" + slowPeriod + \")\", entry, exit));\n    }\n}\n\n// Run all strategies with progress tracking\nBacktestExecutionResult result = new BacktestExecutor(series)\n    .executeWithRuntimeReport(strategies, \n        series.numFactory().numOf(1),  // position size: 1 unit\n        Trade.TradeType.BUY,           // long positions (use Trade.TradeType.SELL for shorts)\n        ProgressCompletion.loggingWithMemory()); // logs progress with memory stats\n\n// Weight net profit at 70% and return over max drawdown at 30%.\n// Weights are normalized internally, so 7/3 and 0.7/0.3 are equivalent.\nAnalysisCriterion netProfitCriterion = new NetProfitCriterion();\nAnalysisCriterion returnOverMaxDrawdownCriterion = new ReturnOverMaxDrawdownCriterion();\n\n// Get the top 10 strategies by composite weighted score\nList\u003cTradingStatement\u003e topStrategies = result.getTopStrategiesWeighted(10,\n    WeightedCriterion.of(netProfitCriterion, 7.0),\n    WeightedCriterion.of(returnOverMaxDrawdownCriterion, 3.0));\n\n// Review the winners\ntopStrategies.forEach(statement -\u003e {\n    System.out.printf(\"Strategy: %s, Net Profit: %s, Return over Max Drawdown: %s%n\",\n        statement.getStrategy().getName(),\n        statement.getCriterionScore(netProfitCriterion).orElse(series.numOf(0)),\n        statement.getCriterionScore(returnOverMaxDrawdownCriterion).orElse(series.numOf(0)));\n});\n```\n\nIt’s not uncommon for a first backtest to look promising. Very promising. Resist the urge to extrapolate annualized returns, quit your job, or price out yachts.\n\n\n## Visualize and share strategies\n\nSee your strategies in action. Ta4j includes charting helpers, but you're not locked in - serialize to JSON and use any visualization stack you prefer.\n\n**Built-in Java charting** (using JFreeChart):\n\nBasic strategy visualization with indicator overlays:\n\u003c!-- START_SNIPPET: ema-crossover --\u003e\n```java\n// Generate simplified chart - just price, indicators, and signals (no subchart)\nChartWorkflow chartWorkflow = new ChartWorkflow();\nJFreeChart chart = chartWorkflow.builder()\n        .withTitle(\"EMA Crossover Strategy\")\n        .withTimeAxisMode(TimeAxisMode.BAR_INDEX) // Optional: compress non-trading gaps (weekends/holidays)\n        .withSeries(series) // Price bars (candlesticks)\n        .withIndicatorOverlay(fastEma) // Overlay indicators on price chart\n        .withIndicatorOverlay(slowEma)\n        .withTradingRecordOverlay(record) // Mark entry/exit points with arrows\n        .toChart();\nchartWorkflow.saveChartImage(chart, series, \"ema-crossover-strategy\", \"output/charts\"); // Save as image\n```\n\u003c!-- END_SNIPPET: ema-crossover --\u003e\n\n![EMA Crossover Strategy Chart](ta4j-examples/docs/img/ema-crossover-readme.jpg)\n\nThe chart above shows candlestick price data with EMA lines overlaid and buy/sell signals marked with arrows. This demonstrates basic strategy visualization with indicator overlays.\nUse `TimeAxisMode.BAR_INDEX` when you want to remove visual gaps from weekends or market holidays while keeping the underlying bar timestamps intact.\n\nIf you need to inspect or customize a chart before rendering, call `toPlan()` and review `plan.context()`/`plan.metadata()` for the shared title, domain series, and time axis mode. The same metadata drives consistent title styling across chart types when you render or save charts.\n\n**Adding indicator subcharts** for indicators with different scales (like RSI, which ranges from 0-100):\n\u003c!-- START_SNIPPET: rsi-strategy --\u003e\n```java\n// Create indicators\nClosePriceIndicator close = new ClosePriceIndicator(series);\nRSIIndicator rsi = new RSIIndicator(close, 14);\n\n// RSI strategy: buy when RSI crosses below 30 (oversold), sell when RSI crosses\n// above 70 (overbought)\nRule entry = new CrossedDownIndicatorRule(rsi, 30);\nRule exit = new CrossedUpIndicatorRule(rsi, 70);\nStrategy strategy = new BaseStrategy(\"RSI Strategy\", entry, exit);\nTradingRecord record = new BarSeriesManager(series).run(strategy);\n\nChartWorkflow chartWorkflow = new ChartWorkflow();\nJFreeChart chart = chartWorkflow.builder()\n        .withTitle(\"RSI Strategy with Subchart\")\n        .withSeries(series) // Price bars (candlesticks)\n        .withTradingRecordOverlay(record) // Mark entry/exit points\n        .withSubChart(rsi) // RSI indicator in separate subchart panel\n        .toChart();\n```\n\u003c!-- END_SNIPPET: rsi-strategy --\u003e\n\n![RSI Strategy with Subchart](ta4j-examples/docs/img/rsi-strategy-readme.jpg)\n\n**Visualizing performance metrics** alongside your strategy:\n\u003c!-- START_SNIPPET: strategy-performance --\u003e\n```java\n// Create indicators: multiple moving averages\nClosePriceIndicator close = new ClosePriceIndicator(series);\nSMAIndicator sma20 = new SMAIndicator(close, 20);\nEMAIndicator ema12 = new EMAIndicator(close, 12);\n\n// Strategy: buy when EMA crosses above SMA, sell when EMA crosses below SMA\nRule entry = new CrossedUpIndicatorRule(ema12, sma20);\nRule exit = new CrossedDownIndicatorRule(ema12, sma20);\nStrategy strategy = new BaseStrategy(\"EMA/SMA Crossover\", entry, exit);\nTradingRecord record = new BarSeriesManager(series).run(strategy);\n\nChartWorkflow chartWorkflow = new ChartWorkflow();\nJFreeChart chart = chartWorkflow.builder()\n        .withTitle(\"Strategy Performance Analysis\")\n        .withSeries(series) // Price bars (candlesticks)\n        .withIndicatorOverlay(sma20) // Overlay SMA on price chart\n        .withIndicatorOverlay(ema12) // Overlay EMA on price chart\n        .withTradingRecordOverlay(record) // Mark entry/exit points\n        .withSubChart(new MaximumDrawdownCriterion(), record) // Performance metric in subchart\n        .toChart();\n```\n\u003c!-- END_SNIPPET: strategy-performance --\u003e\n\n![Strategy Performance Analysis](ta4j-examples/docs/img/strategy-performance-readme.jpg)\n\nThis chart shows price action with indicator overlays, trading signals, and a performance subchart displaying maximum drawdown over time - helping you understand risk alongside returns.\n\n**Advanced multi-indicator analysis** with multiple subcharts:\n\u003c!-- START_SNIPPET: advanced-strategy --\u003e\n```java\n// Create indicators\nClosePriceIndicator close = new ClosePriceIndicator(series);\nSMAIndicator sma50 = new SMAIndicator(close, 50);\nEMAIndicator ema12 = new EMAIndicator(close, 12);\nMACDIndicator macd = new MACDIndicator(close, 12, 26);\nRSIIndicator rsi = new RSIIndicator(close, 14);\n\n// Strategy: buy when EMA crosses above SMA and RSI \u003e 50, sell when EMA crosses\n// below SMA\nRule entry = new CrossedUpIndicatorRule(ema12, sma50).and(new OverIndicatorRule(rsi, 50));\nRule exit = new CrossedDownIndicatorRule(ema12, sma50);\nStrategy strategy = new BaseStrategy(\"Advanced Multi-Indicator Strategy\", entry, exit);\nTradingRecord record = new BarSeriesManager(series).run(strategy);\n\nChartWorkflow chartWorkflow = new ChartWorkflow();\nJFreeChart chart = chartWorkflow.builder()\n        .withTitle(\"Advanced Multi-Indicator Strategy\")\n        .withSeries(series) // Price bars (candlesticks)\n        .withIndicatorOverlay(sma50) // Overlay SMA on price chart\n        .withIndicatorOverlay(ema12) // Overlay EMA on price chart\n        .withTradingRecordOverlay(record) // Mark entry/exit points\n        .withSubChart(macd) // MACD indicator in subchart\n        .withSubChart(rsi) // RSI indicator in subchart\n        .withSubChart(new NetProfitLossCriterion(), record) // Net profit/loss performance metric\n        .toChart();\n```\n\u003c!-- END_SNIPPET: advanced-strategy --\u003e\n\n![Advanced Multi-Indicator Strategy](ta4j-examples/docs/img/advanced-strategy-readme.jpg)\n\nThis comprehensive chart demonstrates combining multiple indicators (MACD, RSI) in separate subcharts with performance metrics, giving you a complete view of strategy behavior.\n\nSee the chart at the top of this README for another example, or check the [wiki's charting guide](https://ta4j.github.io/ta4j-wiki/Charting.html) for more examples.\n\n**Export to any stack** (Python, TypeScript, etc.):\n\nSerialize indicators, rules, and strategies to JSON for persistence, sharing, or integration with other systems:\n\n\u003c!-- START_SNIPPET: serialize-indicator --\u003e\n```java\n// Serialize an indicator (RSI) to JSON\nClosePriceIndicator close = new ClosePriceIndicator(series);\nRSIIndicator rsi = new RSIIndicator(close, 14);\nString rsiJson = rsi.toJson();\nLOG.info(\"Output: {}\", rsiJson);\n// Output:\n// {\"type\":\"RSIIndicator\",\"parameters\":{\"barCount\":14},\"components\":[{\"type\":\"ClosePriceIndicator\"}]}\n```\n\u003c!-- END_SNIPPET: serialize-indicator --\u003e\n\n\u003c!-- START_SNIPPET: serialize-rule --\u003e\n```java\n// Serialize a rule (AndRule) to JSON\nRule rule1 = new OverIndicatorRule(rsi, 50);\nRule rule2 = new UnderIndicatorRule(rsi, 80);\nRule andRule = new AndRule(rule1, rule2);\nString ruleJson = ComponentSerialization.toJson(RuleSerialization.describe(andRule));\nLOG.info(\"Output: {}\", ruleJson);\n// Output:\n// {\"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\":{\"barCount\":14},\"components\":[{\"type\":\"ClosePriceIndicator\"}]}],\"parameters\":{\"threshold\":80.0}}]}\n```\n\u003c!-- END_SNIPPET: serialize-rule --\u003e\n\n\u003c!-- START_SNIPPET: serialize-strategy --\u003e\n```java\n// Serialize a strategy (EMA Crossover) to JSON\nEMAIndicator fastEma = new EMAIndicator(close, 12);\nEMAIndicator slowEma = new EMAIndicator(close, 26);\nRule entry = new CrossedUpIndicatorRule(fastEma, slowEma);\nRule exit = new CrossedDownIndicatorRule(fastEma, slowEma);\nStrategy strategy = new BaseStrategy(\"EMA Crossover\", entry, exit);\nString strategyJson = strategy.toJson();\nLOG.info(\"Output: {}\", strategyJson);\n// Output: {\"type\":\"BaseStrategy\",\"label\":\"EMA\n// 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\":[{\"type\":\"EMAIndicator\",\"parameters\":{\"barCount\":12},\"components\":[{\"type\":\"ClosePriceIndicator\"}]},{\"type\":\"EMAIndicator\",\"parameters\":{\"barCount\":26},\"components\":[{\"type\":\"ClosePriceIndicator\"}]}]}]}\n```\n\u003c!-- END_SNIPPET: serialize-strategy --\u003e\n\nRestore from JSON:\n```java\n// Restore indicators and strategies from JSON\nIndicator\u003c?\u003e restoredIndicator = Indicator.fromJson(series, rsiJson);\nStrategy restoredStrategy = Strategy.fromJson(series, strategyJson);\n```\n\nBar series serialization (Java):\n- Bar data, the `NumFactory`, and the `BarBuilderFactory` configuration are preserved across the round-trip.\n- `ConcurrentBarSeries` reinitializes its locks after deserialization and recreates the trade bar builder lazily.\n- Builder state (for example, a time period set directly on the builder) must be re-applied after deserialization unless you configured it in the factory.\n\n## Features at a glance\n\n- **190+ technical indicators (and counting)** - Aroon, ATR, Ichimoku, MACD, RSI, Renko, Heikin-Ashi, and many more. New indicators are added regularly.\n- **Candlestick pattern coverage** - Includes bullish/bearish reversal patterns such as Morning/Evening Star, Piercing Line, Dark Cloud Cover, engulfing, harami, and marubozu variants.\n- **Composable strategy API** - Build complex trading rules using fluent Java patterns\n- **Built-in backtesting engine** - Test strategies on years of data in seconds. Same code for backtesting and live trading — no rewrites.\n- **Performance metrics** - 30+ analysis criteria including Sharpe ratio, drawdown, win rate, and more\n- **Charting support** - Visualize strategies with candlestick charts, indicator overlays, and performance subcharts\n- **JSON serialization** - Save and restore strategies and indicators for persistence and sharing\n- **Production-ready** - Deterministic calculations, minimal dependencies, type-safe APIs\n- **Extensive examples** - Runnable demos covering strategies, indicators, backtesting, and live trading\n\n## From backtest to live trading\n\nThe same strategies you backtest can run live. Ta4j's deterministic calculations make it safe to deploy \u0026 test thoroughly, then execute with confidence.\n\n```java\nimport org.ta4j.core.builder.BaseBarSeriesBuilder;\n\n// Create a live series (starts empty, grows as bars arrive)\nBarSeries liveSeries = new BaseBarSeriesBuilder()\n        .withName(\"BTC-USD\")\n        .build();\n\n// Build your strategy (same code as backtesting!)\nStrategy strategy = buildStrategy(liveSeries);\n\n// Main trading loop: check for signals on each new bar\nwhile (true) {\n    // Fetch latest bar from your exchange/broker API\n    Bar latest = fetchLatestBarFromBroker();  // Your integration here\n    liveSeries.addBar(latest);\n\n    int endIndex = liveSeries.getEndIndex();\n    \n    // Check entry/exit signals (same API as backtesting)\n    if (strategy.shouldEnter(endIndex)) {\n        placeBuyOrder();  // Your order execution logic\n    } else if (strategy.shouldExit(endIndex)) {\n        placeSellOrder(); // Your order execution logic\n    }\n    \n    Thread.sleep(60000); // Wait 1 minute (or your bar interval)\n}\n```\n**Why this works:**\n- **Same code, different data**: Your strategy logic is identical for backtests and live trading\n- **Deterministic**: Same inputs always produce same outputs - critical for testing and debugging\n- **Type-safe**: Compile-time checks catch errors before they cost money\n\n### Migration note: Trade and TradingRecord surfaces\n\nTreat `Trade` and `TradingRecord` as the primary APIs. Stream single fills directly with\n`TradingRecord.operate(fill)`, or batch one logical order with `Trade.fromFills(...)` and pass that through\n`TradingRecord.operate(...)`. `BaseTrade` and `BaseTradingRecord` remain the shared implementation behind those\ncontracts.\n\n```java\nTradingRecord defaultBacktest = new BarSeriesManager(series).run(strategy);\n\nTradingRecord parityBacktest = new BarSeriesManager(series).run(\n        strategy,\n        new BaseTradingRecord(TradeType.BUY, ExecutionMatchPolicy.FIFO,\n                new ZeroCostModel(), new ZeroCostModel(), null, null));\n```\n\n## Recording live executions\n\nWhen you route orders to an exchange, stream one fill at a time with `TradingRecord.operate(fill)`, or group an\nexchange-reported batch with `Trade.fromFills(...)`. `BaseTradingRecord` still tracks partial fills, multiple open\nlots, and recorded fees so analytics can include open exposure.\n\n```java\nimport java.util.List;\nimport java.time.Instant;\n\nimport org.ta4j.core.ExecutionMatchPolicy;\nimport org.ta4j.core.ExecutionSide;\nimport org.ta4j.core.BaseTradingRecord;\nimport org.ta4j.core.Trade;\nimport org.ta4j.core.TradeFill;\nimport org.ta4j.core.TradingRecord;\nimport org.ta4j.core.Trade.TradeType;\nimport org.ta4j.core.analysis.CashFlow;\nimport org.ta4j.core.analysis.EquityCurveMode;\nimport org.ta4j.core.analysis.OpenPositionHandling;\nimport org.ta4j.core.analysis.cost.ZeroCostModel;\nimport org.ta4j.core.num.Num;\n\nTradingRecord record = new BaseTradingRecord(\n        TradeType.BUY,\n        ExecutionMatchPolicy.FIFO,\n        new ZeroCostModel(),\n        new ZeroCostModel(),\n        null,\n        null);\n\nTradeFill incomingFill = new TradeFill(\n        -1,\n        Instant.now(),\n        price,\n        amount,\n        fee,\n        ExecutionSide.BUY,\n        orderId,\n        correlationId);\nrecord.operate(incomingFill);\n\n// If the exchange already gives you multiple partial fills for one logical order,\n// you can either stream them one at a time...\nTradeFill batchFillOne = mapExchangeFill(partialOne);\nTradeFill batchFillTwo = mapExchangeFill(partialTwo);\n\n// Stream fills directly as they arrive\nrecord.operate(batchFillOne);\nrecord.operate(batchFillTwo);\n\n// ...or, if you already have the whole batch, keep them together:\nList\u003cTradeFill\u003e exchangeFills = List.of(batchFillOne, batchFillTwo);\nrecord.operate(Trade.fromFills(TradeType.BUY, exchangeFills));\n\nCashFlow equity = new CashFlow(series, record, EquityCurveMode.MARK_TO_MARKET,\n        OpenPositionHandling.MARK_TO_MARKET);\nNum latest = equity.getValue(series.getEndIndex());\n```\n\nNotes:\n- `ExecutionMatchPolicy.SPECIFIC_ID` matches exits to the lot with a matching `correlationId` or `orderId`.\n- Single fills need an explicit `ExecutionSide` so `TradingRecord.operate(fill)` can infer the right trade direction.\n- After deserializing a `BaseTradingRecord`, call `rehydrate(holdingCostModel)` to restore transient cost models.\n- See `TradeFillRecordingExample` in `ta4j-examples` for a runnable live-style walkthrough that streams fills with\n  `TradingRecord.operate(fill)`, contrasts that with grouped `Trade.fromFills(...)` recording, and shows how\n  `FIFO`, `LIFO`, `AVG_COST`, and `SPECIFIC_ID` change partial-exit matching.\n\n## Streaming trade ingestion (gap handling)\n\nWhen you need to aggregate raw trades into time bars, use `ConcurrentBarSeries` with a `TimeBarBuilderFactory`:\n\n```java\nimport java.time.Duration;\nimport java.time.Instant;\n\nimport org.ta4j.core.Bar;\nimport org.ta4j.core.ConcurrentBarSeries;\nimport org.ta4j.core.ConcurrentBarSeriesBuilder;\nimport org.ta4j.core.bars.TimeBarBuilderFactory;\n\nConcurrentBarSeries series = new ConcurrentBarSeriesBuilder()\n        .withName(\"BTC-USD\")\n        .withBarBuilderFactory(new TimeBarBuilderFactory(Duration.ofMinutes(1)))\n        .build();\n\nInstant t0 = Instant.parse(\"2024-01-01T10:05:00Z\");\nseries.ingestTrade(t0, 1, 100);\nseries.ingestTrade(t0.plusSeconds(150), 2, 105); // skips the 10:06 bar\n\nLOG.info(\"Bars: {}\", series.getBarCount()); // 2\nLOG.info(\"Second bar begin: {}\", series.getBar(1).getBeginTime()); // 2024-01-01T10:07:00Z\n```\n\nTime gaps are omitted; no empty bars are inserted. If your pipeline expects continuous prices, reconcile and backfill OHLCV data upstream before ingestion.\n\n## Elliott Wave quickstart\n\nThe Elliott Wave suite exposes two minimal entry points:\n\n- `ElliottWaveFacade` for indicator-style, per-bar access (recommended for rules and chart overlays)\n- `ElliottWaveAnalyzer` for one-shot analysis runs with pluggable detectors and confidence profiles\n\n```java\nBarSeries series = ...;\nint index = series.getEndIndex();\n\nElliottWaveFacade facade = ElliottWaveFacade.fractal(series, 5, ElliottDegree.INTERMEDIATE);\n\nElliottPhase phase = facade.phase().getValue(index);\nElliottScenarioSet scenarios = facade.scenarios().getValue(index);\nNum invalidation = facade.invalidationLevel().getValue(index);\n```\n\nSee the [Elliott Wave Indicators wiki guide](https://ta4j.github.io/ta4j-wiki/Elliott-Wave-Indicators.html) for the full quickstart and analyzer-based workflow.\n\n## Real-world examples\n\nThe `ta4j-examples` module includes runnable examples demonstrating common patterns and strategies:\n\n### Strategy Examples\n- **[RSI2Strategy](ta4j-examples/src/main/java/ta4jexamples/strategies/RSI2Strategy.java)** - Mean reversion strategy using RSI with entry/exit rules\n- **[ADXStrategy](ta4j-examples/src/main/java/ta4jexamples/strategies/ADXStrategy.java)** - Trend-following strategy using ADX and DI indicators\n- **[CCICorrectionStrategy](ta4j-examples/src/main/java/ta4jexamples/strategies/CCICorrectionStrategy.java)** - Commodity Channel Index-based correction strategy\n- **[MovingMomentumStrategy](ta4j-examples/src/main/java/ta4jexamples/strategies/MovingMomentumStrategy.java)** - Momentum-based strategy with moving averages\n- **[GlobalExtremaStrategy](ta4j-examples/src/main/java/ta4jexamples/strategies/GlobalExtremaStrategy.java)** - Strategy using global price extrema for entries/exits\n- **[NetMomentumStrategy](ta4j-examples/src/main/java/ta4jexamples/strategies/NetMomentumStrategy.java)** - Net momentum calculation with multiple indicators\n\n### Data Loading Examples\n- **[YahooFinanceHttpBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/YahooFinanceHttpBarSeriesDataSource.java)** - Fetch historical OHLCV data from Yahoo Finance API (stocks, ETFs, crypto). Includes response caching to reduce API calls. See the [Sourcing market data](#sourcing-market-data) section above for a quick start guide.\n- **[YahooFinanceBacktest](ta4j-examples/src/main/java/ta4jexamples/backtesting/YahooFinanceBacktest.java)** - Complete example demonstrating Yahoo Finance data loading, advanced multi-indicator strategy (Bollinger Bands, RSI, ATR stops), backtesting, and visualization\n- **[CoinbaseHttpBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/CoinbaseHttpBarSeriesDataSource.java)** - Load historical crypto data from Coinbase's public API with automatic caching and pagination\n- **[CoinbaseBacktest](ta4j-examples/src/main/java/ta4jexamples/backtesting/CoinbaseBacktest.java)** - Complete example demonstrating Coinbase data loading, advanced multi-indicator strategy (MACD, Keltner Channels, VWAP, MFI), risk management, and transaction cost analysis\n- **[BitStampCsvTradesFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/BitStampCsvTradesFileBarSeriesDataSource.java)** - Load historical trade data from Bitstamp CSV files and aggregate into OHLCV bars\n- **[CsvFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/CsvFileBarSeriesDataSource.java)** - Load OHLCV bar data from CSV files with intelligent filename pattern matching\n- **[JsonFileBarSeriesDataSource](ta4j-examples/src/main/java/ta4jexamples/datasources/JsonFileBarSeriesDataSource.java)** - Parse JSON data from Coinbase/Binance APIs with flexible date filtering\n\n### Analysis \u0026 Backtesting Examples\n- **[StrategyAnalysis](ta4j-examples/src/main/java/ta4jexamples/analysis/StrategyAnalysis.java)** - Comprehensive strategy performance analysis\n- **[ElliottWaveIndicatorSuiteDemo](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/ElliottWaveIndicatorSuiteDemo.java)** - Canonical Elliott Wave scenario analysis with confidence scoring, structured reporting, and annotated charts. Defaults to an ossified classpath dataset when run without arguments; optional command-line arguments can load Yahoo Finance or Coinbase data.\n- **[ElliottWavePresetDemo](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/ElliottWavePresetDemo.java)** - Consolidated preset launcher with fixed ossified presets (`btc`, `eth`, `sp500`) and flexible live mode where you can provide any ticker.\n- **[ElliottWaveAdaptiveSwingAnalysis](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/demo/ElliottWaveAdaptiveSwingAnalysis.java)** - Demonstrates adaptive/composite swing detection for scenario generation.\n- **[ElliottWavePatternProfileDemo](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/demo/ElliottWavePatternProfileDemo.java)** - Compares default and pattern-aware confidence profiles.\n- **[ElliottWaveMultiDegreeAnalysisDemo](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/demo/ElliottWaveMultiDegreeAnalysisDemo.java)** - Shows cross-degree validation and scenario recommendation.\n- **[ElliottWaveTrendBacktest](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/backtest/ElliottWaveTrendBacktest.java)** - Evaluates trend-bias directionality over backtest and walk-forward windows.\n- **[HighRewardElliottWaveBacktest](ta4j-examples/src/main/java/ta4jexamples/analysis/elliottwave/backtest/HighRewardElliottWaveBacktest.java)** - Backtests the high-reward Elliott Wave strategy presets.\n- **[WyckoffCycleIndicatorSuiteDemo](ta4j-examples/src/main/java/ta4jexamples/wyckoff/WyckoffCycleIndicatorSuiteDemo.java)** - Demonstrates the Wyckoff cycle entry points (`WyckoffCycleFacade`, `WyckoffCycleAnalysis`) and prints phase transitions on an ossified bar series dataset\n- **[MultiStrategyBacktest](ta4j-examples/src/main/java/ta4jexamples/backtesting/MultiStrategyBacktest.java)** - Compare multiple strategies side-by-side\n- **[TradeFillRecordingExample](ta4j-examples/src/main/java/ta4jexamples/backtesting/TradeFillRecordingExample.java)** - Walk through a live-style partial-fill workflow with `TradingRecord.operate(fill)`, inspect `getOpenPositions()` versus `getCurrentPosition()`, and compare `FIFO`, `LIFO`, `AVG_COST`, and `SPECIFIC_ID` partial-exit matching.\n- **[TradingRecordParityBacktest](ta4j-examples/src/main/java/ta4jexamples/backtesting/TradingRecordParityBacktest.java)** - Compare next-open, current-close, and slippage execution models side by side, then verify the same fills across default, provided, and factory-configured `BaseTradingRecord` runs.\n- **[BacktestPerformanceTuningHarness](ta4j-examples/src/main/java/ta4jexamples/backtesting/BacktestPerformanceTuningHarness.java)** - Tune backtest performance (strategy count, bar count, cache window hints, heap sweeps)\n\n### Charting Examples\n- **[IndicatorsToChart](ta4j-examples/src/main/java/ta4jexamples/indicators/IndicatorsToChart.java)** - Visualize indicators overlaid on price charts\n- **[CandlestickChart](ta4j-examples/src/main/java/ta4jexamples/indicators/CandlestickChart.java)** - Basic candlestick chart with trading signals\n- **[CashFlowToChart](ta4j-examples/src/main/java/ta4jexamples/analysis/CashFlowToChart.java)** - Visualize cash flow and equity curves\n\n**💡 Tip**: Run any example with `./mvnw -pl ta4j-examples exec:java -Dexec.mainClass=ta4jexamples.Quickstart` (replace `Quickstart` with the class name; on Windows use `mvnw.cmd`).\n\n## Performance\n\n\u003c!-- TODO: Add performance benchmarks and metrics --\u003e\n\u003c!-- Consider including:\n- Backtesting performance (strategies/second, bars/second)\n- Memory usage patterns\n- Comparison with other technical analysis libraries\n- Num type performance characteristics (DecimalNum vs DoubleNum)\n- Real-world usage statistics if available\n--\u003e\n\nTa4j is designed for performance and scalability:\n\n- **Efficient calculations** - Optimized indicator implementations with minimal overhead\n- **Flexible number types** - Choose between `DecimalNum` (precision) and `DoubleNum` (speed) based on your needs\n- **Memory-efficient** - Support for moving windows and sub-series to minimize memory footprint\n- **Parallel-friendly** - Strategies can be backtested independently for easy parallelization\n\nFor detailed performance characteristics and benchmarks, see the [wiki's performance guide](https://ta4j.github.io/ta4j-wiki/) (TODO: add link when available).\n\n## Community \u0026 Support\n\nGet help, share ideas, and connect with other Ta4j users:\n\n- **💬 [Discord Community](https://discord.gg/HX9MbWZ)** - Active community for quick questions, strategy discussions, and real-time help\n- **📖 [Documentation Wiki](https://ta4j.github.io/ta4j-wiki/)** - Comprehensive guides covering indicators, strategies, backtesting, and more\n- **📚 [Javadoc API Reference](https://ta4j.github.io/ta4j/)** - Complete API documentation with examples\n- **🐛 [GitHub Issues](https://github.com/ta4j/ta4j/issues)** - Report bugs, request features, or ask questions\n- **💡 [Usage Examples](https://github.com/ta4j/ta4j/tree/master/ta4j-examples/src/main/java/ta4jexamples)** - Browse runnable code examples in the repository\n\n## What's next?\n\n**New to technical analysis?**\n- Start with the [wiki's Getting Started guide](https://ta4j.github.io/ta4j-wiki/) to learn core concepts\n- Explore the [`ta4j-examples`](ta4j-examples) module - each example is runnable and well-commented\n- Try modifying the quick start example above: change indicator parameters, add new rules, or test different exit conditions\n\n**Ready to go deeper?**\n- Browse [strategy recipes](https://ta4j.github.io/ta4j-wiki/) for Renko bricks, Ichimoku clouds, breakout strategies, and more\n- Learn about [portfolio metrics](https://ta4j.github.io/ta4j-wiki/) for multi-asset strategies\n- Check out [advanced backtesting patterns](https://ta4j.github.io/ta4j-wiki/) like walk-forward analysis\n\n**Need help?**\n- See the [Community \u0026 Support](#community--support) section above for all available resources\n\n## Contributing\n\n- Scan the [roadmap](https://ta4j.github.io/ta4j-wiki/Roadmap-and-Tasks.html) and [how-to-contribute guide](https://ta4j.github.io/ta4j-wiki/How-to-contribute).\n- [Fork the repo](http://help.github.com/forking/), open pull requests, and join code discussions on Discord.\n- See the [contribution policy](.github/CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Release \u0026 snapshot publishing\n\nTa4j uses automated workflows for publishing both snapshot and stable releases.\n\n### Snapshots\n\nEvery push to `master` triggers a snapshot deployment via the `snapshot.yml` GitHub workflow:\n\nSnapshots are available at:\n\n```text\nhttps://central.sonatype.com/repository/maven-snapshots/\n```\n\n### Stable releases\n\nReleases are also automated via GitHub workflows. For detailed information about the release process, see [RELEASE_PROCESS.md](RELEASE_PROCESS.md).\n\n\n## Warranty\n\n\u003e **🛡️ Ta4j and its developers guarantee your experience to meet or exceed reasonable expectations for correctness and profitability for a minimum period of one (1) year, beginning the moment you run your first ta4j-based backtest\\***.\n\nJust kidding.\n\nTa4j is open-source software released under the MIT License. There is no warranty, express, implied, imaginary, or otherwise. Ta4j is provided as-is. Use it, fork it, break it, improve it, or walk away entirely.\n\nTa4j is built and maintained by developers contributing on their own time, at their own expense, and for reasons as varied as the markets themselves. For some, it’s a hobby. For others, a labor of love. Some run Ta4j inside proprietary trading stacks and choose to give back. Others contribute to open-source to offset certain download habits that, in practice, look a lot like torrenting north of a thousand terabytes of movies, TV shows, software installers, cracked plug-ins, ROM sets, **The.Sims.3.Complete.Collection-RELOADED**, and e-books, while maintaining a lifetime upload ratio of 0. Who can say?\n\nWhat *is* certain is this: whoever they are, and whatever motivates them, they don’t owe you anything. If Ta4j helps you learn, experiment, or even make money, great. If it doesn’t, that’s the risk you accepted.\n\n\\*Applies only to the Premium Subscription Package, which includes 24/7 technical support, guaranteed alpha, and on-demand feature requests.  \n(Also just kidding. There is no Premium Subscription Package.)\n\n\n\n\n## Powered by\n\n[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSource)\n\n\u003ca href = https://github.com/ta4j/ta4j/graphs/contributors\u003e\n  \u003cimg src = https://contrib.rocks/image?repo=ta4j/ta4j\u003e\n\u003c/a\u003e\n","funding_links":[],"categories":["Projects","Java","项目","Technical analysis libraries"],"sub_categories":["Financial","财务","FrameWorks"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fta4j%2Fta4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fta4j%2Fta4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fta4j%2Fta4j/lists"}