Contributing to tradedesk¶
We welcome contributions to tradedesk. This guide covers the standards and
workflow you need to contribute successfully.
What this repository holds¶
This repository holds the tradedesk framework: the Python package (tradedesk/)
with its tests, docs and examples, and the Rust crates (crates/tradedesk-data and
crates/tradedesk-backtest) with theirs, plus the CI and release workflows. It
holds no trading strategies, no research artefacts (hypotheses, registrations,
registries, results, verdicts) and no venue- or deployment-specific configuration
(accounts, credentials, live sizing, portfolio or strategy configs). Those belong
elsewhere, and a pull request that carries them is declined.
"Trading strategies" means the venture's strategies: the ideas, parameters and
configurations that trade its capital, which live in the private strategy
repository. Four things that look like strategies are framework and belong here:
the generic strategy base and runtime glue in tradedesk/strategy/ (the
MLDirectionStrategy runs any predict_proba model through the portfolio's
risk controls and carries no model, instrument or parameters of its own); the
documentation examples in docs/examples/, which exist to show the API; the
backtester's test strategy (crates/tradedesk-backtest/tests/toy/), which exists
only to drive its tests; and its builtin cost table
(crates/tradedesk-backtest/config/costs.toml), which is reference data: the
venues' published fees, each with its source, that any run can replace with its
own file. The test of any of them is that it names no instrument, parameter set or
result that is the venture's.
Review enforces this boundary for now; tooling to check it is still to come. The pre-commit guard below catches the most common path-based cases.
Getting Started¶
- Fork the repository and create a feature branch from
main. - Clone locally and install the dev dependencies:
- We use
uvfor dependency management. If you haveuvinstalled you can use it directly:
- Install the pre-commit hooks. These run
ruff-formatand a guard that blocks private strategy research from being committed to this public repo (paths underresearch/,killstack/, or anything containingprivate):
The guard script lives at scripts/hooks/block-private-research.sh and is
also runnable on demand against the staged tree. If a commit is rejected
with Blocked: private research content detected — commit to ig_trader
instead, the listed files belong in the private ig_trader repo, not here.
Code Standards¶
Python Version¶
Python 3.11+ is required.
Style and Linting¶
We use ruff for linting and formatting:
Rules enforced: E, F, I (import sorting), TID (tidy imports).
Line length is 100 characters.
Type Checking¶
We use mypy in strict mode:
All contributions must pass with zero type errors.
Import Conventions¶
Cross-domain imports must use top-level re-exports. For example, code in
tradedesk.execution should import from tradedesk.marketdata, never from
tradedesk.marketdata.events. Classes and functions intended for use outside
their domain must be explicitly exported in __init__.py.
Testing¶
We use pytest:
The Rust crates have their own gates, run from the repository root with the
toolchain pinned in rust-toolchain.toml; CI runs them when a Rust path changes:
cargo build --workspace --all-targets --locked
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
cargo fmt --check
cargo deny check
- All new and existing tests must pass following any code change.
- Include tests for new functionality or bug fixes.
- Code coverage must not decrease.
Credentials and Release Automation¶
Local development, CI, and backtests do not require repository secrets.
Live IG execution uses environment variables read by
tradedesk.execution.ig.settings.Settings:
IG_API_KEY(required)IG_USERNAME(required)IG_PASSWORD(required)IG_ENVIRONMENT(optional, defaults toDEMO; must beDEMOorLIVE)
Do not commit real IG values in examples, shell history snippets, or tests. The
library negotiates the short-lived IG session headers (CST and
X-SECURITY-TOKEN) during authentication, so contributors should not try to
store or configure those manually.
Maintainers triggering .github/workflows/prepare-release.yml must configure
these repository secrets:
RELEASE_APP_IDRELEASE_APP_PRIVATE_KEY
The shared reusable release workflow uses those values to mint a GitHub App
token for checkout, version bumping, pushing the release commit, and creating
the GitHub release. .github/workflows/publish.yml uses PyPI trusted
publishing via GitHub OIDC (id-token: write), so no PyPI API token secret is
expected in this repository.
Pull Requests¶
- Keep changes small, well-scoped, and documented in PR descriptions.
- Open PRs against
main. - Rebase your branch onto
mainbefore submitting — we do not use merge commits. - Provide a brief rationale and expected impact in the PR description.
- Do not include secrets or internal data.
Commit Messages¶
Follow Conventional Commits:
feat(strategy): add trailing stop support
fix(portfolio): correct position sizing on partial fills
docs: update backtesting guide
Reporting Issues¶
If you find a bug or have a feature request, open an issue describing the goal and expected behaviour. Include steps to reproduce for bugs.
If unsure, open an issue describing the goal and request guidance before implementing.
License¶
Licensed under the Apache License, Version 2.0. See: https://www.apache.org/licenses/LICENSE-2.0
Copyright 2026 Radius Red Ltd. | Contact