Contributions from the trading community help drive NautilusTrader forward. This guide covers how to pick something up, set up your environment, and get a PR merged. If you get stuck at any point, ask on Discord.
Important
Never report a security vulnerability as a public issue. Follow SECURITY.md instead.
Open a GitHub issue to discuss your proposed changes or enhancements. Early feedback is the quickest way to avoid work that can't be merged.
Check the open-source scope first so your idea fits what the project maintains, and read the Code of Conduct.
You also need to sign the Contributor License Agreement before we can merge your work. CLA Assistant prompts you automatically on your first PR.
Note
New integrations are a major undertaking for the project and require discussion and approval before any PR is opened. See ROADMAP: Community-contributed integrations for the process, and ADAPTERS.md for adapter tiers, community listings, and support boundaries.
The Rust workspace lives under crates/, and the PyO3 Python package lives under python/. See
MIGRATION_V2.md when porting code from the legacy v1 package on develop_v1.
If you aren't sure where a change belongs, ask in the issue.
Fork the repository and branch from develop, merging upstream changes regularly to keep your fork
current. Then follow the Environment setup guide for
Rust, Python, and uv. With those in place, install the pinned development tools. This includes
prek, which runs pre-commit checks, formatters, and linters before
each commit:
cargo install cargo-binstall --locked # one-off prerequisite
make install-tools
prek installmake install-tools reads pinned versions from Cargo.toml, tools.toml, and
python/pyproject.toml. See
Install development tools
for the full list, what each tool does, and which tools install separately.
Include tests that cover your change. Running the relevant target locally first saves a round trip:
make cargo-testruns the Rust tests.make pytestruns the Python tests, building the extension and stubs first.
Rust tests use #[rstest] rather than #[test], including non-parameterized ones, and pre-commit
enforces this (#[tokio::test] is fine for async tests). See
Testing for the wider conventions.
Follow the established coding practices in the
Developer Guide. For documentation changes,
follow the style guide in docs/developer_guide/docs.md (use sentence case for headings H2 and
below).
These are the checks that most often send a PR back:
- Run
make formatandmake pre-commitso CI passes on the first attempt. - If you changed PyO3 bindings or the Rust docs behind them, run
make py-stubsand commit the generated output. These stubs are generated rather than hand-edited, and CI fails on drift. See Generated Python artifacts. - Give new Rust files the standard copyright header. See File header requirements.
- Do not update
RELEASES.md. Maintainers keep it current to avoid frequent merge conflicts. - Do not use Conventional Commits syntax for commit messages or PR titles. Follow Commit messages instead. PR titles matter because a squash merge turns the PR title into the commit subject.
Open the PR against develop with a summary comment and a reference to any relevant GitHub issue.
Keep it small and focused, which makes review much faster.
We typically respond to PRs within a couple of days, and will let you know if anything needs changing before merging.