Contributing to Optopsy¶
Thank you for your interest in contributing to Optopsy! This guide will help you get started.
Development Setup¶
1. Clone the Repository¶
2. Install Dependencies¶
3. Install Pre-commit Hooks¶
4. Verify Installation¶
Development Workflow¶
Running Tests¶
# Run all tests
uv run pytest tests/ -v
# Run specific test file
uv run pytest tests/test_strategies.py -v
# Run tests matching a pattern
uv run pytest tests/ -k "butterfly" -v
Code Formatting and Linting¶
Optopsy uses Ruff for formatting and linting:
# Check formatting
uv run ruff format --check optopsy/ tests/
# Auto-format code
uv run ruff format optopsy/ tests/
# Lint code
uv run ruff check optopsy/ tests/
# Lint and auto-fix
uv run ruff check --fix optopsy/ tests/
# Type check
uv run ty check optopsy/
Important: All code must pass ruff format, ruff check, and ty check before submitting a PR.
Adding a New Strategy¶
Follow these steps to add a new options strategy:
1. Define Strategy in strategies.py¶
Add a public function and helper if needed:
def new_strategy(data: pd.DataFrame, **kwargs: Any) -> pd.DataFrame:
"""
Generate new strategy statistics.
A clear description of what this strategy does, including:
- Leg composition
- Market outlook
- Profit/loss characteristics
Args:
data: DataFrame containing option chain data
**kwargs: Optional strategy parameters
Returns:
DataFrame with strategy performance statistics
"""
return _helper(data, leg_def=[...], **kwargs)
2. Add Validation Rules (if needed)¶
If your strategy has strike constraints, add them to rules.py:
def _rule_new_strategy_strikes(df: pd.DataFrame) -> pd.DataFrame:
"""
Validate strike ordering for new strategy.
Rule: [Describe your rule here]
"""
# Implementation
return df[mask]
3. Update Column Definitions (if needed)¶
If your strategy needs new column structures, add them to definitions.py:
4. Export in __init__.py¶
Add your strategy to the exports:
from .strategies import (
# ... existing strategies
new_strategy,
)
__all__ = [
# ... existing strategies
"new_strategy",
]
5. Add Tests¶
Create tests in tests/test_strategies.py:
def test_new_strategy(sample_data):
"""Test new strategy returns expected output."""
results = op.new_strategy(sample_data)
assert isinstance(results, pd.DataFrame)
assert len(results) > 0
assert 'mean' in results.columns
# Additional assertions
6. Update Documentation¶
Add documentation to the appropriate strategy category file in docs/strategies/.
Pull Request Guidelines¶
Before Submitting¶
- [ ] All tests pass (
uv run pytest tests/ -v) - [ ] Code is formatted with Ruff (
uv run ruff format optopsy/ tests/) - [ ] Linting passes (
uv run ruff check optopsy/ tests/) - [ ] Type checking passes (
uv run ty check optopsy/) - [ ] New features have tests
- [ ] New strategies have documentation
- [ ] Docstrings follow existing style (Google format)
- [ ] Type hints are included
PR Description¶
Include in your PR description: - What changes you made - Why you made them - How to test the changes - Any breaking changes
Example PR Template¶
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How to test these changes
## Checklist
- [ ] Tests pass
- [ ] Code formatted with Ruff
- [ ] Documentation updated
- [ ] Type hints included
Code Style Guidelines¶
Docstrings¶
Use Google-style docstrings:
def function_name(param1: str, param2: int) -> bool:
"""
Brief description of function.
Longer description if needed, explaining behavior,
edge cases, or important details.
Args:
param1: Description of param1
param2: Description of param2
Returns:
Description of return value
Raises:
ValueError: When param1 is invalid
"""
pass
Type Hints¶
Always include type hints:
from typing import Any, Dict, List
import pandas as pd
def process_data(
data: pd.DataFrame,
params: Dict[str, Any]
) -> List[pd.DataFrame]:
...
Function Naming¶
- Public functions:
snake_case(e.g.,long_calls) - Private functions:
_snake_case(e.g.,_process_strategy) - Constants:
UPPER_CASE(rarely used)
Testing Guidelines¶
Test Structure¶
def test_feature_name(sample_data):
"""Test that feature behaves correctly."""
# Arrange
expected_result = ...
# Act
actual_result = function_under_test(sample_data)
# Assert
assert actual_result == expected_result
Fixtures¶
Use pytest fixtures for common test data:
@pytest.fixture
def sample_data():
"""Generate sample options data for testing."""
return pd.DataFrame({...})
Coverage¶
Aim for high test coverage on public APIs. Not every internal function needs tests, but all public strategy functions should be tested.
Documentation¶
Building Docs Locally¶
# Install MkDocs and required plugins
pip install mkdocs mkdocs-material "mkdocstrings[python]"
# Serve docs locally
mkdocs serve
# Visit http://127.0.0.1:8000
Documentation Structure¶
docs/index.md- Home pagedocs/getting-started.md- Installation and quick startdocs/strategies/- Strategy-specific documentationdocs/parameters.md- Parameter referencedocs/examples.md- Usage examplesdocs/api-reference.md- Auto-generated API docs
Reporting Issues¶
Bug Reports¶
Include: - Python version - Optopsy version - Minimal reproducible example - Expected vs actual behavior - Error messages/tracebacks
Feature Requests¶
Describe: - The problem you're trying to solve - How you envision the solution - Any alternatives you've considered - Whether you're willing to contribute the feature
Community¶
- GitHub Issues: Bug reports and feature requests
- Discussions: Questions and general discussion
- Pull Requests: Code contributions
License¶
By contributing to Optopsy, you agree that your contributions will be licensed under the AGPL-3.0 License.
Questions?¶
If you have questions about contributing, feel free to: - Open a GitHub Discussion - Create an issue with the "question" label - Check existing issues and documentation
Thank you for contributing to Optopsy!