Parameter System Quick Start Guide

5-Minute Introduction

The new Backtrader parameter system makes your code more robust, faster, and easier to maintain. Here’s how to get started in 5 minutes.

Installation and Import

No installation needed! The new parameter system is built into Backtrader. Simply import what you need:

from backtrader.parameters import (
    ParameterizedBase,    # Base class for parameterized objects
    ParameterDescriptor,  # Parameter definition
    Int, Float, Bool,     # Validators
    OneOf                 # Choice validator

)

```bash

## Your First Parameterized Class

### Old Way (Still Works)

```python
class MyIndicator(bt.Indicator):
    params = (
        ('period', 20),
        ('factor', 2.0),
    )

```bash

### New Way (Enhanced)

```python
class MyIndicator(ParameterizedBase):
    period = ParameterDescriptor(
        default=20,
        type_=int,
        validator=Int(min_val=1, max_val=100),
        doc="Calculation period"
    )

    factor = ParameterDescriptor(
        default=2.0,
        type_=float,
        validator=Float(min_val=0.1, max_val=10.0),
        doc="Multiplication factor"
    )

```bash

## Key Benefits You Get Immediately

### 1. Type Safety

```python

# This now prevents bugs:

indicator = MyIndicator(period="twenty")  # ❌ Auto-converts or errors

indicator = MyIndicator(period=20)        # ✅ Works correctly

```bash

### 2. Validation

```python

# This prevents invalid configurations:

indicator = MyIndicator(period=-5)    # ❌ Validation error

indicator = MyIndicator(period=500)   # ❌ Out of range

indicator = MyIndicator(period=20)    # ✅ Valid

```bash

### 3. Better Error Messages

```python

# Old system: Generic error

# New system: "Parameter 'period' expects int between 1 and 100, got -5"

```bash

## Common Parameter Patterns

### 1. Integer with Range

```python
period = ParameterDescriptor(
    default=20,
    type_=int,
    validator=Int(min_val=1, max_val=252),
    doc="Trading period in days"
)

```bash

### 2. Float with Range

```python
alpha = ParameterDescriptor(
    default=0.5,
    type_=float,
    validator=Float(min_val=0.0, max_val=1.0),
    doc="Smoothing factor"
)

```bash

### 3. Choice Parameter

```python
mode = ParameterDescriptor(
    default='sma',
    validator=OneOf('sma', 'ema', 'wma'),
    doc="Moving average type"
)

```bash

### 4. Boolean Parameter

```python
enabled = ParameterDescriptor(
    default=True,
    type_=bool,
    doc="Enable this feature"
)

```bash

### 5. Optional Parameter

```python
custom_value = ParameterDescriptor(
    default=None,
    type_=float,
    validator=lambda x: x is None or x > 0,
    doc="Optional custom value"
)

```bash

## Using Parameters (Same as Before!)

```python
class MyStrategy(ParameterizedBase):
    period = ParameterDescriptor(default=20, type_=int)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

# All these work exactly the same:
        print(self.p.period)              # ✅ Legacy way
        print(self.params.period)         # ✅ Legacy way
        print(self.get_param('period'))   # ✅ New way (recommended)

```bash

## Complete Example: Simple Strategy

```python
from backtrader.parameters import ParameterizedBase, ParameterDescriptor, Int, Float

class SimpleMAStrategy(ParameterizedBase):
    """Simple moving average crossover strategy with enhanced parameters."""

# Moving average periods
    fast_period = ParameterDescriptor(
        default=10,
        type_=int,
        validator=Int(min_val=1, max_val=50),
        doc="Fast moving average period"
    )

    slow_period = ParameterDescriptor(
        default=20,
        type_=int,
        validator=Int(min_val=1, max_val=100),
        doc="Slow moving average period"
    )

# Risk management
    position_size = ParameterDescriptor(
        default=0.1,
        type_=float,
        validator=Float(min_val=0.01, max_val=1.0),
        doc="Position size as fraction of portfolio"
    )

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

# Validate parameter relationships
        if self.get_param('fast_period') >= self.get_param('slow_period'):
            raise ValueError("Fast period must be less than slow period")

        print(f"Strategy created: MA({self.p.fast_period}, {self.p.slow_period})")

# Usage - both ways work:

strategy1 = SimpleMAStrategy()                           # Use defaults

strategy2 = SimpleMAStrategy(fast_period=5, slow_period=15)  # Custom values

```bash

## Instant Upgrades: Using Factory Functions

For even faster development, use factory functions:

```python
from backtrader.parameters import FloatParam, BoolParam, StringParam

class QuickIndicator(ParameterizedBase):

# These one-liners give you full validation:
    alpha = FloatParam(default=0.5, min_val=0.0, max_val=1.0, doc="Alpha factor")
    enabled = BoolParam(default=True, doc="Enable indicator")
    name = StringParam(default="indicator", min_length=1, doc="Indicator name")

```bash

## Migration Strategy: Start Small

You don't need to migrate everything at once:

### 1. Keep Existing Code (Works Forever)

```python

# This continues to work unchanged

class LegacyStrategy(bt.Strategy):
    params = (('period', 20),)

```bash

### 2. Use New System for New Classes

```python

# New classes get enhanced features

class ModernIndicator(ParameterizedBase):
    period = ParameterDescriptor(default=20, type_=int)

```bash

### 3. They Work Together Seamlessly

```python
class MixedStrategy(bt.Strategy):
    def __init__(self):
        self.legacy_indicator = LegacyIndicator()
        self.modern_indicator = ModernIndicator()

# Both work the same way!

```bash

## Advanced Features (When You Need Them)

### Parameter Groups

```python
class AdvancedStrategy(ParameterizedBase):
    fast_period = ParameterDescriptor(default=10, type_=int)
    slow_period = ParameterDescriptor(default=20, type_=int)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

# Group related parameters
        self._param_manager.create_group('MA_PERIODS', ['fast_period', 'slow_period'])

# Update as a group
        self._param_manager.set_group('MA_PERIODS', {'fast_period': 5, 'slow_period': 15})

```bash

### Change Callbacks

```python
class ReactiveIndicator(ParameterizedBase):
    period = ParameterDescriptor(default=20, type_=int)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

# React to parameter changes
        def on_period_change(name, old_val, new_val):
            print(f"Period changed from {old_val} to {new_val}")
            self.recalculate()

        self._param_manager.add_change_callback(on_period_change, 'period')

```bash

## Performance: It's Faster!

The new system is significantly faster:

- Parameter access: 4x faster
- Parameter setting: 2x faster
- Memory usage: More efficient

## Troubleshooting Common Issues

### Type Errors

```python

# Problem: String where int expected

indicator = MyIndicator(period="20")

# Solution: Pass correct type

indicator = MyIndicator(period=20)

```bash

### Validation Errors

```python

# Problem: Value out of range

indicator = MyIndicator(period=-5)  # Error: must be >= 1

# Solution: Use valid value

indicator = MyIndicator(period=20)

```bash

### Parameter Not Found

```python

# Problem: Wrong parameter name

print(indicator.p.periods)  # Error: should be 'period'

# Solution: Use correct name

print(indicator.p.period)

```bash

## Next Steps

1. **Try It**: Copy one of the examples above and run it
2. **Migrate Gradually**: Start with new classes or simple existing ones
3. **Add Validation**: Use built-in validators to make your code more robust
4. **Explore Advanced Features**: Groups, callbacks, and more when you need them
5. **Read the Full Docs**: Check out the API reference and migration guide

## Need Help?

- **API Reference**: Complete documentation of all features
- **Migration Guide**: Detailed guidance for converting existing code
- **Examples**: Comprehensive examples showing all capabilities
- **Performance Guide**: Optimization tips and benchmarks

The new parameter system is designed to make your life easier while maintaining 100% backward compatibility. Start simple, and add features as you need them!