Developer Guide
This page is intended for developers of Freqtrade, people who want to contribute to the Freqtrade codebase or documentation, or people who want to understand the source code of the application they're running.
All contributions, bug reports, bug fixes, documentation improvements, enhancements and ideas are welcome. We track issues on GitHub and also have a dev channel on discord where you can ask questions.
Getting Started
Prerequisites
- Python 3.11 or higher
- Git
- Basic understanding of Python and trading concepts
- Familiarity with pytest for testing
Development Setup
Option 1: Setup Script
# Clone the repository
git clone https://github.com/freqtrade/freqtrade.git
cd freqtrade
# Run setup script and answer "y" for dev dependencies
./setup.sh
# Install pre-commit hooks
pre-commit install
Option 2: Manual Setup
# Clone and enter directory
git clone https://github.com/freqtrade/freqtrade.git
cd freqtrade
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install development dependencies
pip install -r requirements-dev.txt
pip install -e .[all]
# Install pre-commit hooks
pre-commit install
Option 3: DevContainer (Recommended)
The fastest way to get started is using VSCode with the Remote Container extension.
Requirements:
This provides a complete development environment without installing dependencies locally.
Development Tools
Code Quality Tools
The development environment includes several tools:
- pytest - Testing framework
- ruff - Fast Python linter and formatter
- mypy - Static type checker
- pre-commit - Git hooks for code quality
- coveralls - Code coverage reporting
Pre-commit Hooks
Pre-commit hooks run automatically before each commit to ensure code quality:
# Install hooks (run once)
pre-commit install
# Run hooks manually
pre-commit run --all-files
# Skip hooks (not recommended)
git commit --no-verify
Testing
Running Tests
# Run all tests
pytest
# Run specific test file
pytest tests/test_configuration.py
# Run with coverage
pytest --cov=freqtrade
# Run tests in parallel
pytest -n auto
Writing Tests
New features should include comprehensive tests. Test files should be placed in the tests/
directory with names matching test_*.py
.
Basic Test Structure
import pytest
from freqtrade.configuration import Configuration
def test_configuration_creation():
"""Test that configuration can be created."""
config = Configuration.from_files(['config.json'])
assert config is not None
assert 'exchange' in config
Testing with Fixtures
def test_strategy_loading(default_conf, mocker):
"""Test strategy loading with mocked dependencies."""
# Use provided fixtures for common test data
strategy = StrategyResolver.load_strategy(default_conf)
assert strategy is not None
Testing Log Messages
from tests.conftest import log_has, log_has_re
def test_method_with_logging(caplog):
"""Test method that produces log messages."""
method_to_test()
# Check exact log message
assert log_has("This event happened", caplog)
# Check with regex for dynamic content
assert log_has_re(r"This dynamic event happened and produced \d+", caplog)
Test Categories
- Unit Tests - Test individual functions/methods
- Integration Tests - Test component interactions
- End-to-End Tests - Test complete workflows
- Performance Tests - Test performance characteristics
Debugging
VSCode Debug Configuration
Create .vscode/launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"name": "freqtrade trade",
"type": "debugpy",
"request": "launch",
"module": "freqtrade",
"console": "integratedTerminal",
"args": [
"trade",
"--strategy", "SampleStrategy",
"--config", "config.json"
]
},
{
"name": "freqtrade backtesting",
"type": "debugpy",
"request": "launch",
"module": "freqtrade",
"console": "integratedTerminal",
"args": [
"backtesting",
"--strategy", "SampleStrategy",
"--timerange", "20230101-20230201"
]
}
]
}
PyCharm Debug Configuration
- Go to Run/Debug Configurations
- Add new Python configuration
- Set Module name:
freqtrade
- Set Parameters:
trade --strategy SampleStrategy
- Set Working directory to repository root
Code Style and Standards
Python Style Guide
Freqtrade follows PEP 8 with some modifications:
- Line length: 100 characters
- Use type hints for all functions
- Use docstrings for all public methods
- Follow naming conventions
Code Formatting
# Format code with ruff
ruff format .
# Check and fix linting issues
ruff check . --fix
# Type checking
mypy freqtrade
Documentation Standards
- All public functions must have docstrings
- Use Google-style docstrings
- Include type hints
- Add examples for complex functions
def calculate_profit(entry_price: float, exit_price: float, amount: float) -> float:
"""Calculate profit from a trade.
Args:
entry_price: Price at which the trade was entered
exit_price: Price at which the trade was exited
amount: Amount of the asset traded
Returns:
Profit amount in quote currency
Example:
>>> calculate_profit(100.0, 110.0, 1.0)
10.0
"""
return (exit_price - entry_price) * amount
Contributing Guidelines
Before Contributing
- Check existing issues - Look for related issues or discussions
- Create an issue - Discuss your idea before implementing
- Fork the repository - Create your own fork to work on
- Create a branch - Use descriptive branch names
Pull Request Process
-
Create feature branch:
git checkout -b feature/my-awesome-feature
-
Make changes with proper tests and documentation
-
Run quality checks:
pre-commit run --all-files
pytest -
Commit changes:
git commit -m "feat: add awesome new feature"
-
Push and create PR:
git push origin feature/my-awesome-feature
Commit Message Format
Use conventional commits format:
feat:
- New featuresfix:
- Bug fixesdocs:
- Documentation changesstyle:
- Code style changesrefactor:
- Code refactoringtest:
- Test additions/changeschore:
- Maintenance tasks
Architecture Overview
Core Components
freqtrade/
├── main.py # Entry point
├── configuration/ # Configuration handling
├── data/ # Data management
├── exchange/ # Exchange interfaces
├── optimize/ # Backtesting and hyperopt
├── plugins/ # Pluggable components
├── resolvers/ # Dynamic loading
├── rpc/ # Remote procedure calls
├── strategy/ # Strategy framework
└── worker.py # Main worker process
Key Classes
- FreqtradeBot - Main trading bot logic
- IStrategy - Strategy interface
- Exchange - Exchange abstraction layer
- DataProvider - Data access layer
- Backtesting - Backtesting engine
Plugin System
Freqtrade uses a plugin system for extensibility:
- Strategies - Trading logic
- Pairlists - Pair selection
- Protections - Risk management
- HyperOpt Loss Functions - Optimization objectives
Creating Plugins
Custom Pairlist
from freqtrade.plugins.pairlist.IPairList import IPairList
class MyCustomPairList(IPairList):
def __init__(self, exchange, pairlistmanager, config, pairlistconfig, pairlist_pos):
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
@property
def needstickers(self) -> bool:
return False
def short_desc(self) -> str:
return f"MyCustomPairList - top {self._number_pairs} pairs"
def gen_pairlist(self, tickers):
# Your custom logic here
return self._whitelist[:self._number_pairs]
Custom Strategy
from freqtrade.strategy import IStrategy
from pandas import DataFrame
class MyCustomStrategy(IStrategy):
INTERFACE_VERSION = 3
minimal_roi = {"0": 0.1}
stoploss = -0.05
timeframe = '5m'
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Add your indicators
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Define entry conditions
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Define exit conditions
return dataframe
Error Handling
Exception Hierarchy
FreqtradeException
├── OperationalException
│ └── ConfigurationError
├── DependencyException
│ ├── PricingError
│ └── ExchangeError
│ ├── TemporaryError
│ ├── DDosProtection
│ └── InvalidOrderException
│ ├── RetryableOrderError
│ └── InsufficientFundsError
└── StrategyError
Custom Exceptions
from freqtrade.exceptions import OperationalException
def my_function():
if error_condition:
raise OperationalException("Descriptive error message")
Documentation
Building Documentation
# Install documentation dependencies
pip install -r docs/requirements-docs.txt
# Serve documentation locally
mkdocs serve
# Build documentation
mkdocs build
Documentation Structure
- Use MkDocs Material theme
- Write in Markdown format
- Include code examples
- Add admonitions for important notes
Special Documentation Elements
!!! note "Important Note"
This is an important note box.
!!! warning "Warning"
This is a warning box.
!!! tip "Pro Tip"
This is a tip box.
Performance Considerations
Optimization Guidelines
- Use vectorized operations - Prefer pandas operations over loops
- Minimize API calls - Cache data when possible
- Profile code - Use profiling tools to identify bottlenecks
- Memory management - Be aware of memory usage in long-running processes
Profiling
import cProfile
import pstats
# Profile a function
profiler = cProfile.Profile()
profiler.enable()
your_function()
profiler.disable()
# Analyze results
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(10)
Release Process
Version Management
Freqtrade uses semantic versioning (MAJOR.MINOR.PATCH):
- MAJOR - Breaking changes
- MINOR - New features (backward compatible)
- PATCH - Bug fixes
Release Branches
- develop - Development branch
- stable - Stable release branch
- feature/ - Feature branches
- hotfix/ - Hotfix branches
Getting Help
Community Resources
- Discord - Join the developer channel
- GitHub Discussions - Ask questions
- GitHub Issues - Report bugs or request features
Code Review Process
- All changes require review
- Automated tests must pass
- Code coverage should not decrease
- Documentation must be updated
- Breaking changes need migration guide
Best Practices
Development Workflow
- Start with tests - Write tests before implementation
- Small commits - Make focused, atomic commits
- Regular rebasing - Keep branches up to date
- Code review - Review your own code before submitting
- Documentation - Update docs with code changes
Code Quality
- Type hints - Use type hints everywhere
- Error handling - Handle errors gracefully
- Logging - Add appropriate logging
- Performance - Consider performance implications
- Security - Follow security best practices
Resources
- Contributing Guidelines - Detailed contribution guide
- GitHub Repository - Source code and issues
- Discord Community - Developer discussions
- Documentation - User documentation