136 lines
9.2 KiB
Markdown
136 lines
9.2 KiB
Markdown
# 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/<you>/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 <version>`.
|
||
- 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_<TAG>_SCHEDULE_ENABLED=true`
|
||
and `TA4J_TAGGED_TEST_<TAG>_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 <version>` 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. |