Strategy Development Guide
Relevant source files
The following files were used as context for generating this wiki page:
The Strategy module serves as the core logic engine for the backtrader framework, enabling users to define trading rules, manage positions, and handle order execution. By subclassing the base bt.Strategy class, developers can implement technical indicators, state machines for pattern recognition, and sophisticated risk management systems that respond to market data feeds in a bar-by-bar (synchronous) fashion.
Sources: backtrader/strategy.py:127-130, Tutorials/quickstart/test_strategies.py:108-111
Core Architecture and Lifecycle
Strategies in backtrader follow a strict event-driven lifecycle. The system orchestrates initialization, data synchronization across multiple timeframes, and recurring execution logic.
Lifecycle Events
The following table summarizes the primary hooks available for strategy development:
| Method | Timing | Primary Purpose |
|---|---|---|
__init__ | Instantiation | Initialization of indicators and local state. |
start | Pre-backtest | Logic to run exactly once before data processing starts. |
prenext | Data Warm-up | Called when indicators lack enough data to produce values. |
nextstart | Initial Value | Called once when indicators first have enough data. |
next | Main Loop | Primary entry point for trading logic on every new bar. |
stop | Post-backtest | Logging final results and performance metrics. |
Sources: backtrader/strategy.py:355-390, Tutorials/quickstart/test_strategies.py:65-72, Tutorials/quickstart/test_strategies.py:108-115
Synchronization Flow
The framework ensures that next is only called when all technical indicators defined in __init__ have sufficient data according to their minimum periods.
Order Management and Notifications
Strategies interact with the broker using high-level methods like buy(), sell(), and close(). The execution lifecycle is handled via asynchronous-style notifications.
Order Submission Methods
Strategies provide multiple ways to adjust position sizing and target specific portfolio values:
- Standard Orders:
buy()andsell()for direct quantity-based entries. - Target Rebalancing:
order_target_size(): Rebalances to a specific number of units.order_target_value(): Rebalances to a specific currency amount.order_target_percent(): Rebalances to a percentage of total portfolio equity.
- Bracket Orders:
buy_bracket()andsell_bracket()for submitting entry, stop-loss, and take-profit orders simultaneously.
Sources: backtrader/strategy.py:756-760, backtrader/strategy.py:1049-1060, backtrader/strategy.py:1130-1140
Notification System
The framework provides feedback on trade and order status changes through dedicated methods:
Position Sizing and Risk Management
Sophisticated strategies implement dynamic position sizing and automated exit logic to manage risk exposure.
Position Sizers
Strategies use a sizer component to automate unit calculation. By default, a FixedSize sizer is used, but this can be replaced via setsizer().
Sources: backtrader/strategy.py:1270-1280
Advanced Exit Strategies
Implementation of risk management often involves monitoring current positions and dynamic thresholds:
- Trailing Stops: Updating a
stop_pricebased on ATR or high-water marks. - Volatility Scaling: Adjusting entries based on the
AverageVolatilityindicator. - Pattern-based Exits: For example, exiting a "Cup and Handle" trade once a
profit_targetproject from cup depth is reached.
Sources: strategies/gaussian_triple_confirmation.py:330-360, strategies/cup_and_handle.py:270-285, strategies/moving_average_crossover.py:260-275
Implementation Table: Risk Management Options
| Feature | Implementation Logic | File Context |
|---|---|---|
| Stop Loss | Fixed percentage below buyprice set in notify_order. | strategies/moving_average_crossover.py:210 |
| Trailing Stop | Comparison of datalow[0] vs. a dynamic trail_price in next. | strategies/rsi_overbought_oversold_reversal.py:415-430 |
| Position Sizing | Calculated as risk_amount / risk_per_share where risk is equity percentage. | strategies/gaussian_triple_confirmation.py:290-305 |
| Throttling | Logic in can_trade_now() to prevent overtrading within time windows. | strategies/gaussian_triple_confirmation.py:250 |
Sources: strategies/gaussian_triple_confirmation.py:250-305, strategies/moving_average_crossover.py:210, strategies/rsi_overbought_oversold_reversal.py:415-430
Pattern and Signal-Based Logic
The framework supports specialized strategy subclasses for simplified signal handling and complex pattern recognition.
Signal Strategies
bt.SignalStrategy automates entry/exit logic by mapping indicator values to specific signal types (LONG, SHORT, LONGEXIT, SHORTEXIT). Values > 0 indicate a long signal, while < 0 indicate short.
Sources: backtrader/strategy.py:1330-1350
State-Machine Pattern Recognition
Complex patterns like the Cup and Handle require tracking multiple stages (Cup Stage -> Handle Stage -> Breakout Stage) across hundreds of bars.
# Conceptual flow from CupAndHandleStrategy
def next(self):
if self.cup_stage:
# Detect U-shape and depth
if valid_cup: self.transition_to_handle()
elif self.handle_stage:
# Detect pullback and volume contraction
if valid_handle: self.transition_to_breakout()
elif self.breakout_stage:
# Buy on high-volume price breakout
Sources: strategies/cup_and_handle.py:465-530
Conclusion
Strategy development in this framework is characterized by a synchronous data processing model where indicators and risk management tools are integrated into a single, cohesive lifecycle. By leveraging notification hooks for order status and trade completion, developers can build robust, self-correcting systems that manage the entire trade lifecycle from pattern recognition to automated risk-based exits.
Sources: backtrader/strategy.py:127-140, Tutorials/quickstart/test_strategies.py:137-145