Thank you for your interest in contributing to QuantStack! This document provides guidelines and information for contributors.
- Getting Started
- Development Setup
- Making Changes
- Code Style
- Testing
- Documentation
- Submitting Changes
- Release Process
- Python 3.10 or higher
- Git
- A GitHub account
Contributions are welcome! Here are some ways to help:
- Bug fixes: Fix issues reported in GitHub Issues
- Features: Implement new features (please discuss in an issue first)
- Documentation: Improve or add documentation
- Tests: Add or improve tests
- Performance: Optimize existing code
- Research: Add new trading strategies, indicators, or research modules
-
Fork the repository
Click the "Fork" button on GitHub to create your own copy.
-
Clone your fork
git clone https://github.com/kbichave/QuantStack.git cd QuantStack -
Set up the development environment
This project uses uv for dependency management.
# Install uv if not already installed curl -LsSf https://astral.sh/uv/install.sh | sh # Install dependencies (creates .venv automatically) uv sync --all-extras # Install pre-commit hooks uv run pre-commit install
-
Create a branch
git checkout -b feature/your-feature-name
Use descriptive branch names:
feature/add-bollinger-bands- New featuresfix/backtest-memory-leak- Bug fixesdocs/improve-api-reference- Documentationrefactor/simplify-feature-factory- Code refactoringperf/optimize-zscore-calculation- Performance improvements
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Formatting, no code changerefactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or updating testschore: Maintenance tasks
Examples:
feat(features): add Keltner Channel indicator
fix(backtest): correct Sharpe ratio calculation for daily data
docs(readme): add installation instructions for M1 Macs
We use Ruff for linting and formatting:
# Format code
ruff format packages/quantcore tests
# Check for issues
ruff check packages/quantcore tests
# Auto-fix issues
ruff check --fix packages/quantcore testsAll public functions must have type hints:
def calculate_rsi(
prices: pd.Series,
period: int = 14,
) -> pd.Series:
"""Calculate RSI indicator."""
...Use NumPy-style docstrings for all public functions and classes:
def calculate_zscore(
series: pd.Series,
period: int,
min_periods: int | None = None,
) -> pd.Series:
"""
Calculate rolling z-score.
Parameters
----------
series : pd.Series
Input time series.
period : int
Lookback period for mean and standard deviation.
min_periods : int, optional
Minimum observations required. Default is period // 2.
Returns
-------
pd.Series
Z-score series.
Examples
--------
>>> prices = pd.Series([100, 102, 98, 103, 97])
>>> zscore = calculate_zscore(prices, period=3)
Notes
-----
Z-scores are commonly used for mean reversion strategies.
"""
...# Run all tests
uv run pytest tests/ -v
# Run specific test file
uv run pytest tests/unit/test_features.py -v
# Run with coverage
uv run pytest tests/ --cov=packages/quantcore --cov-report=html
# Run only fast tests (exclude slow)
uv run pytest tests/ -m "not slow"- Place unit tests in
tests/unit/ - Place integration tests in
tests/integration/ - Use fixtures from
tests/conftest.py - Test edge cases and error conditions
- Aim for > 80% coverage on new code
Example test:
import pytest
import pandas as pd
from quantcore.features.base import FeatureBase
class TestFeatureBase:
"""Tests for FeatureBase class."""
def test_zscore_calculation(self, sample_ohlcv_df):
"""Test z-score calculation."""
zscore = FeatureBase.zscore(sample_ohlcv_df["close"], period=20)
assert len(zscore) == len(sample_ohlcv_df)
assert zscore.iloc[19:].notna().all() # After warmup
assert abs(zscore.mean()) < 0.5 # Approximately centered
def test_zscore_handles_zero_std(self):
"""Test z-score with constant values (zero std)."""
constant = pd.Series([100.0] * 30)
zscore = FeatureBase.zscore(constant, period=10)
assert zscore.isna().all() # Should be NaN, not inf# Build docs locally
mkdocs serve
# View at http://127.0.0.1:8000- Update docstrings when changing function signatures
- Add examples for new features
- Update the changelog for user-facing changes
- Include type information in documentation
-
Update your branch
git fetch upstream git rebase upstream/main
-
Run all checks
# Lint and format uv run ruff check packages/quantcore tests uv run ruff format --check packages/quantcore tests # Type check uv run mypy packages/quantcore # Tests uv run pytest tests/ -v
-
Push your changes
git push origin feature/your-feature-name
-
Create a Pull Request
- Use a clear title following commit conventions
- Fill out the PR template
- Link related issues
- Request reviews from maintainers
- All CI checks must pass
- At least one maintainer approval
- No merge conflicts
- Documentation updated if needed
- Tests added for new functionality
Releases are managed by maintainers. The process:
- Update version in
pyproject.toml - Update
CHANGELOG.md - Create a git tag:
git tag v0.1.0 - Push tag:
git push origin v0.1.0 - GitHub Actions will build and publish to PyPI
- Open a GitHub Discussion for questions
- Open an Issue for bugs or feature requests
- Check existing issues before creating new ones
Thank you for contributing!