Skip to main content

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

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

  1. Go to Run/Debug Configurations
  2. Add new Python configuration
  3. Set Module name: freqtrade
  4. Set Parameters: trade --strategy SampleStrategy
  5. 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

  1. Check existing issues - Look for related issues or discussions
  2. Create an issue - Discuss your idea before implementing
  3. Fork the repository - Create your own fork to work on
  4. Create a branch - Use descriptive branch names

Pull Request Process

  1. Create feature branch:

    git checkout -b feature/my-awesome-feature
  2. Make changes with proper tests and documentation

  3. Run quality checks:

    pre-commit run --all-files
    pytest
  4. Commit changes:

    git commit -m "feat: add awesome new feature"
  5. Push and create PR:

    git push origin feature/my-awesome-feature

Commit Message Format

Use conventional commits format:

  • feat: - New features
  • fix: - Bug fixes
  • docs: - Documentation changes
  • style: - Code style changes
  • refactor: - Code refactoring
  • test: - Test additions/changes
  • chore: - 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

  1. Use vectorized operations - Prefer pandas operations over loops
  2. Minimize API calls - Cache data when possible
  3. Profile code - Use profiling tools to identify bottlenecks
  4. 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

Code Review Process

  1. All changes require review
  2. Automated tests must pass
  3. Code coverage should not decrease
  4. Documentation must be updated
  5. Breaking changes need migration guide

Best Practices

Development Workflow

  1. Start with tests - Write tests before implementation
  2. Small commits - Make focused, atomic commits
  3. Regular rebasing - Keep branches up to date
  4. Code review - Review your own code before submitting
  5. Documentation - Update docs with code changes

Code Quality

  1. Type hints - Use type hints everywhere
  2. Error handling - Handle errors gracefully
  3. Logging - Add appropriate logging
  4. Performance - Consider performance implications
  5. Security - Follow security best practices

Resources