# Contributing to ta4j ta4j has been around for years and serves a large, diverse user base. Contributions are very welcome, but long‑term maintainability takes precedence over quick wins. Please keep the sections below in mind before filing an issue or opening a PR. ## Principles 1. **Public APIs are contracts.** Moving classes between packages, renaming methods, or otherwise breaking binary/source compatibility forces every downstream user into a refactor. We only accept breaking changes when the value dramatically outweighs the disruption, and even then they must ship with deprecation shims and migration notes. 2. **Opinionated implementations belong outside the core.** ta4j aims to be widely applicable. Highly subjective “feature bundles” (e.g., metric dashboards, bespoke reporting formats, hard-coded broker behaviors) are better published as separate modules or example projects. Keep contributions focused on reusable primitives. 3. **Additive code beats churn.** New indicators, rules, serialization helpers, and documentation are great. Mechanical refactors (“just moved files around”) or stylistic changes with no behavioral impact rarely get merged. 4. **Tests tell the story.** Every change—bug fix or feature—needs focused tests demonstrating the behavior and guarding against regressions. - **Run this before opening or updating a PR:** `mvn -B verify` This matches the main CI path and keeps SpotBugs and JaCoCo advisory in the full contributor flow. - **Use focused local quality loops when iterating:** `mvn -pl ta4j-core -am spotbugs:check` and `mvn -pl ta4j-core -am test jacoco:report jacoco:check` These are intentionally strict for the module you are changing, so you can tighten one tool at a time before rerunning the full `mvn -B verify`. - **Fix formatting and license headers when needed:** `mvn -B license:format formatter:format` First-time contributors almost always hit this; run the formatter command locally before your final `mvn -B verify`. ## Contribution checklist 1. **Use Java 25+ and Maven 3.9+.** The build enforces these versions during Maven validation. 2. **Start with an issue** for anything non-trivial. Use it to confirm fit with the [Roadmap](https://ta4j.github.io/ta4j-wiki/Roadmap-and-Tasks.html) and to align on scope. [Search existing issues](https://github.com/ta4j/ta4j/issues?q=is%3Aissue) before opening a new one. 3. **Fork & branch** from `master`. ```bash git clone https://github.com//ta4j.git cd ta4j git checkout -b feature/your-topic ``` 4. **Implement + test.** Run the full build before pushing: ```bash mvn -B clean license:format formatter:format test install ``` CI will fail if your changes are not formatted or lack the project license header. First-time contributors almost always hit this; run the command locally first. Update `CHANGELOG.md` when you add, fix, or change behavior. 5. **Open the PR** against `ta4j/master`. Draft PRs are encouraged for early feedback. Prefer [well-formed commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). **Optional: Enable workflow linting hook** - If you're modifying GitHub Actions workflows, enable the pre-push hook to catch syntax errors early: ```bash git config core.hooksPath .githooks ``` Then install `actionlint` (e.g., `brew install actionlint`). The hook will automatically lint any modified files under `.github/workflows/` before pushing. ## Contribution priorities 1. Items on the [Roadmap](https://ta4j.github.io/ta4j-wiki/Roadmap-and-Tasks.html). 2. Additive indicators/criteria/rules that do not change existing behavior. 3. Test coverage or documentation improvements. 4. Bug fixes (smaller, localized fixes are easier to land; large refactors should be discussed first). 5. API changes: only with clear justification, deprecation shims, and migration docs. ## Coding expectations - Favor clarity over cleverness; write the code you’d want to debug a year from now. - Keep PRs scoped. If you find unrelated issues, file them or send separate PRs. - Every new public class/method needs Javadoc with `@since `. - Use primitives for indicator parameters (e.g., `int timeFrame`). Convert to `Num` inside using `series.numFactory()`. - Do not cache `Num` instances globally—always obtain them from the relevant factory. ## Indicator contributions Open an issue to discuss the new indicator first. Every indicator must ship with matching tests: - `src/main/java/org/ta4j/core/indicators/.../NewIndicator.java` - `src/test/java/org/ta4j/core/indicators/.../NewIndicatorTest.java` ## Tagged test workflows Regular PR and push CI skips test tags configured by `ta4j.excludedTestTags`. Run tagged suites manually from GitHub Actions, or locally with: - `xvfb-run mvn -B test -Dgroups=integration -Dta4j.excludedTestTags=analysis-demo,elliott-macro-cycle-replay` - `xvfb-run mvn -B test -Dgroups=benchmark -Dta4j.excludedTestTags= -Dta4j.runBenchmarks=true` - `xvfb-run mvn -B test -Dgroups=analysis-demo -Dta4j.excludedTestTags=elliott-macro-cycle-replay -Dta4j.analysisDemoInstrument=coinbase:BTC-USD -Dta4j.analysisDemoOutputDir=target/analysis-demos/elliott-wave` - `xvfb-run mvn -B test -Dgroups=elliott-macro-cycle-replay -Dta4j.excludedTestTags= -Dtest=ElliottWaveMacroCycleDetectorTest` These examples match the Linux GitHub Actions runners. On macOS, use XQuartz or run the Maven command without `xvfb-run` when your local display can satisfy UI-dependent tests. On Windows, use WSL2, a CI runner, or an equivalent X server. The dedicated workflows are: - `Run Integration Tagged Tests` (`.github/workflows/test-tag-integration.yml`) - `Run Benchmark Tagged Tests` (`.github/workflows/test-tag-benchmark.yml`) - `Run Analysis Demo Tagged Tests` (`.github/workflows/test-tag-analysis-demo.yml`) - `Run Elliott Macro Cycle Replay Tagged Tests` (`.github/workflows/test-tag-elliott-macro-cycle-replay.yml`) Scheduled runs are opt-in per tag. Set `TA4J_TAGGED_TEST__SCHEDULE_ENABLED=true` and `TA4J_TAGGED_TEST__SCHEDULE_SLOT=daily`, `weekly`, or `monthly`. Unset variables leave scheduled runs disabled, while manual workflow dispatches run regardless of the schedule variables. The `elliott-macro-cycle-replay` workflow is manual-only and requires a self-hosted runner labeled `ta4j-macro-cycle-replay`. The `analysis-demo` tag is for examples that produce analysis reports and must be the only JUnit tag on each tagged test or class. Its workflow defaults to `coinbase:BTC-USD`, accepts provider-qualified manual inputs such as `coinbase:ETH-USD` or `coinbase:ETH/USD`, and uploads generated JSON, charts, and cached provider responses from `target/analysis-demos/**`. Version 1 supports Coinbase instruments only. For scheduled analysis-demo runs, `weekly` is the intended slot; use `TA4J_TAGGED_TEST_ANALYSIS_DEMO_SCHEDULE_ENABLED=true` with `TA4J_TAGGED_TEST_ANALYSIS_DEMO_SCHEDULE_SLOT=weekly`, and set `TA4J_ANALYSIS_DEMO_INSTRUMENT` to override the scheduled instrument. ## API lifecycle and @since policy - Add `@since ` to every newly introduced class and API member, using the introducing release version without `-SNAPSHOT` (for example `0.22.4`, not `0.22.4-SNAPSHOT`). - This gives us a reliable introduction point for deprecation tracking and lifecycle automation. - New API is considered volatile for the next 5 minor releases after it is introduced. - Example: API added in `0.22.4` may still change incompatibly, or be removed, through `0.27.4` (inclusive). - Treat this window as experimental/beta and avoid production-critical dependency unless you explicitly accept migration risk. ## Branching model Enhancements, new features and fixes should be pushed to a [fork](https://help.github.com/articles/fork-a-repo/) of the master branch. Once completed they will be merged with the master branch during a [pull request](https://help.github.com/articles/about-pull-requests/). GitHub actions are configured to run the tests, validate the licence header and source code format. After the PR has been merged a new SNAPSHOT will be deployed. This development process is similar to [github flow](https://docs.github.com/en/get-started/quickstart/github-flow). * **Only the content of the master branch is going to become a release.** * **There is no release branch nor a mandatory develop branch** ### Release Process For maintainers, the release process is fully automated using GitHub Actions workflows. The process includes: - **Automated release scheduling**: AI-powered scheduler analyzes changes and determines version bumps (patch/minor/major) - **Two-phase release workflow**: `prepare-release.yml` prepares release commits and PRs, `publish-release.yml` handles tagging and deployment - **Release health monitoring**: Automated checks for tag reachability, version drift, and stale release PRs - **GitHub Release automation**: Automatic creation of GitHub Releases with artifacts and release notes For detailed information about the release process, see [RELEASE_PROCESS.md](../RELEASE_PROCESS.md) in the main repository. ## Quick tips - Use `series.getBeginIndex()` instead of `0` when iterating a `BarSeries`. - Remember the difference between `DecimalNum.min(...)` and `DecimalNum.minus(...)`. - When in doubt, ask. It’s easier (and faster) to course-correct early than to rework a large PR later.