backtrader.strategy module

Strategy module - Base class for user-defined trading strategies.

This module provides the Strategy class which serves as the foundation for all user-defined trading strategies in Backtrader. It handles order management, position tracking, indicator integration, and the event-driven execution model.

Key Features:
  • Order creation and management (buy, sell, close, cancel)

  • Position tracking per data feed

  • Integration with indicators and analyzers

  • Event notifications (order, trade, data, timer)

  • Support for multiple data feeds and timeframes

  • Signal-based trading via SignalStrategy

Example

Basic strategy implementation:

import backtrader as bt

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

    def __init__(self):
        self.sma = bt.indicators.SMA(period=self.p.period)

    def next(self):
        if self.data.close[0] > self.sma[0]:
            self.buy()
        elif self.data.close[0] < self.sma[0]:
            self.sell()
Classes:

Strategy: Main base class for trading strategies. SignalStrategy: Strategy subclass that responds to signal indicators.

class backtrader.strategy.Strategy[source]

Bases: StrategyBase

Base class for user-defined trading strategies.

This class provides the core functionality for implementing trading strategies including order management, position tracking, and event handling. Users should subclass this to create custom strategies.

env

Reference to the Cerebro environment.

cerebro

Alias for env.

broker

Reference to the broker for order execution.

datas

List of data feeds available to the strategy.

data

Shortcut to the first data feed (datas[0]).

position

Current position for the main data feed.

stats

Collection of observer instances.

analyzers

Collection of analyzer instances.

Methods to Override:

__init__: Initialize indicators and strategy state. start: Called when the strategy starts running. prenext: Called before minimum period is reached. nextstart: Called once when minimum period is first reached. next: Main strategy logic, called on each bar. stop: Called when the strategy stops running. notify_order: Receive order status notifications. notify_trade: Receive trade notifications. notify_data: Receive data feed notifications. notify_timer: Receive timer notifications.

Example

class MyStrategy(bt.Strategy):

params = ((‘period’, 20),)

def __init__(self):

self.sma = bt.indicators.SMA(period=self.p.period)

def next(self):
if not self.position:
if self.data.close[0] > self.sma[0]:

self.buy()

else:
if self.data.close[0] < self.sma[0]:

self.close()

static __new__(cls, *args, **kwargs)[source]

Override __new__ to handle method renaming that was done in MetaStrategy

__init__(*args, **kwargs)
csv = True
log(txt, dt=None, level='info')[source]

Log a message with optional datetime.

This method provides basic logging functionality. For comprehensive logging including orders, trades, positions, indicators, and signals, use the TradeLogger observer.

Parameters:
  • txt – The message text to log.

  • dt – Optional datetime. If None, uses current bar datetime.

  • level – Log level (‘info’, ‘warning’, ‘error’, ‘debug’).

Example

>>> self.log(f'Close price: {self.data.close[0]:.2f}')
>>> self.log('Warning message', level='warning')
qbuffer(savemem=0, replaying=False)[source]

Enable the memory saving schemes. Possible values for savemem:

0: No savings. Each line object keeps in memory all values

1: All lines objects save memory, using the strict minimum needed

Negative values are meant to be used when plotting is required:

-1: Indicators at Strategy Level and Observers do not enable memory

savings (but anything declared below it does)

-2: Same as -1 plus activation of memory saving for any indicators

which has declared plotinfo.plot as False (will not be plotted)

prenext_open()[source]

Called before next() during prenext phase.

This is a hook for strategies to take action at the open of each bar before minimum period is reached.

nextstart_open()[source]

Called at the open of the first bar where minimum period is satisfied.

This is called only once, transitioning from prenext to next phase.

next_open()[source]

Called at the open of each bar during normal execution.

This is a hook for strategies to take action at the open of each bar.

start()[source]

Called right before the backtesting is about to be started.

This is a hook for strategies to perform initialization before the backtesting loop begins.

getwriterheaders()[source]

Get the CSV headers for writer output.

Returns:

Headers including indicator/observer names and line aliases

Return type:

list

getwritervalues()[source]

Get current values for writer output.

Returns:

Current values from indicators and observers

Return type:

list

getwriterinfo()[source]

Get comprehensive writer information including params and analysis.

Returns:

Nested structure containing params, indicators,

observers, and analyzer results

Return type:

AutoOrderedDict

stop()[source]

Called right before the backtesting is about to be stopped.

This is a hook for strategies to perform cleanup or final logging.

set_tradehistory(onoff=True)[source]

Enable or disable trade history tracking.

Parameters:

onoff – If True, keep full trade history; if False, only track current trade

clear()[source]

Clear pending orders and trades.

Moves pending orders to _orders list and clears pending trades.

add_timer(when, offset=datetime.timedelta(0), repeat=datetime.timedelta(0), weekdays=[], weekcarry=False, monthdays=[], monthcarry=True, allow=None, tzdata=None, cheat=False, *args, **kwargs)[source]

Schedule a timer to invoke notify_timer or a callback.

Note: Can be called during __init__ or start

Schedules a timer to invoke either a specified callback or the notify_timer of one or more strategies.

Parameters:
  • when – Can be: - datetime.time instance (see tzdata below) - bt.timer.SESSION_START to reference session start - bt.timer.SESSION_END to reference session end

  • offset (datetime.timedelta) – Offset the when value. Used with SESSION_START/SESSION_END to trigger after session start/end.

  • repeat (datetime.timedelta) – If set, timer repeats at this interval within the same session. Resets to original when after session end.

  • weekdays (list) – Sorted iterable with integers (Monday=1, Sunday=7) indicating which days the timer can be invoked. Empty = all days.

  • weekcarry (bool) – If True and weekday not seen (e.g., holiday), execute on next day (even if in new week).

  • monthdays (list) – Sorted iterable with integers (1-31) indicating which days of month to execute. Empty = all days.

  • monthcarry (bool) – If True and day not seen (weekend, holiday), execute on next available day.

  • allow (callable) – Callback receiving datetime.date, returns True if date is allowed for timer execution.

  • tzdata – Timezone data - None, pytz instance, or data feed instance. If None and when is SESSION_START/END, uses first data feed.

  • cheat (bool) – If True, timer called before broker evaluates orders, allowing orders based on opening price.

  • *args – Additional args passed to notify_timer

  • **kwargs – Additional kwargs passed to notify_timer

Returns:

The created timer instance

notify_timer(timer, when, *args, **kwargs)[source]

Receive timer notifications.

Receives a timer notification where timer is the timer instance returned by add_timer, and when is the calling time. args and kwargs are any additional arguments passed to add_timer.

The actual when time can be later than expected, as the system may not have been able to call the timer before. This value is the timer’s scheduled time, not the actual system time.

Parameters:
  • timer – The timer instance created by add_timer

  • when – The scheduled time when the timer was triggered

  • *args – Additional positional arguments passed to add_timer

  • **kwargs – Additional keyword arguments passed to add_timer

notify_cashvalue(cash, value)[source]

Notify the current cash and value of the strategy’s broker.

Parameters:
  • cash – Current cash amount

  • value – Current portfolio value

notify_fund(cash, value, fundvalue, shares)[source]

Notify the current cash, value, fund value, and fund shares.

Parameters:
  • cash – Current cash amount

  • value – Current portfolio value

  • fundvalue – Current fund value

  • shares – Current fund shares

notify_order(order)[source]

Receive notification when an order status changes.

Parameters:

order – The order with changed status

notify_trade(trade)[source]

Receive notification when a trade status changes.

Parameters:

trade – The trade with changed status

notify_store(msg, *args, **kwargs)[source]

Receive notification from a store provider.

Parameters:
  • msg – Message from the store

  • *args – Additional positional arguments

  • **kwargs – Additional keyword arguments

notify_data(data, status, *args, **kwargs)[source]

Receive notification from a data feed.

Parameters:
  • data – The data feed sending the notification

  • status – Status code

  • *args – Additional positional arguments

  • **kwargs – Additional keyword arguments

notify_tick(tick)[source]

Called when a new tick event arrives.

Override this method to implement tick-level trading logic.

Parameters:

tick – TickEvent instance with price, volume, direction, etc.

notify_orderbook(orderbook)[source]

Called when a new order book snapshot arrives.

Override this method to implement orderbook-based trading logic.

Parameters:

orderbook – OrderBookSnapshot instance with bids, asks, spread, etc.

notify_funding(funding)[source]

Called when a new funding rate event arrives.

Override this method to implement funding rate arbitrage or position management.

Parameters:

funding – FundingEvent instance with rate, mark_price, etc.

notify_bar(bar)[source]

Called when a bar event arrives from the channel system.

This is different from the standard next() method which processes bars from LineSeries data feeds. This callback handles BarEvents from the channel/queue system.

Parameters:

bar – BarEvent instance with open, high, low, close, volume.

get_last_tick(symbol=None)[source]

Get the last tick for a symbol.

Parameters:

symbol – Symbol name. If None, returns first available.

Returns:

TickEvent or None.

get_last_orderbook(symbol=None)[source]

Get the last order book for a symbol.

Parameters:

symbol – Symbol name. If None, returns first available.

Returns:

OrderBookSnapshot or None.

get_last_funding(symbol=None)[source]

Get the last funding rate for a symbol.

Parameters:

symbol – Symbol name. If None, returns first available.

Returns:

FundingEvent or None.

getdatanames()[source]

Get a list of all data names in the system.

Returns:

Names of all data feeds

Return type:

list

getdatabyname(name)[source]

Get a data feed by its name.

Parameters:

name – Name of the data feed

Returns:

The data feed with the given name

cancel(order)[source]

Cancel an order in the broker.

Parameters:

order – The order to cancel

buy(data=None, size=None, price=None, plimit=None, exectype=None, valid=None, tradeid=0, oco=None, trailamount=None, trailpercent=None, parent=None, transmit=True, **kwargs)[source]

Create a buy (long) order and send it to the broker.

Parameters:
  • data – The data feed for the order. If None, uses the first data feed (self.data).

  • size – Size to use (positive) for the order. If None, the sizer instance retrieved via getsizer will determine the size.

  • price – Price to use. None is valid for Market and Close orders. For Limit, Stop and StopLimit orders this determines the trigger point.

  • plimit – Only applicable to StopLimit orders. This is the price at which to set the implicit Limit order, once the Stop has been triggered.

  • trailamount – For StopTrail/StopTrailLimit orders, an absolute amount which determines the distance to the price to keep the trailing stop.

  • trailpercent – For StopTrail/StopTrailLimit orders, a percentage amount which determines the distance to the price to keep the trailing stop.

  • exectype – Execution type. Possible values: - Order.Market or None: Market order - Order.Limit: Limit order - Order.Stop: Stop order - Order.StopLimit: Stop-limit order - Order.Close: Close order - Order.StopTrail: Stop-trail order - Order.StopTrailLimit: Stop-trail-limit order

  • valid – Order validity. Possible values: - None: Good till cancel - datetime.datetime/date: Good till date - Order.DAY: Day order

  • tradeid – Internal value to track overlapping trades.

  • oco – Another order instance for OCO (Order Cancel Others) group.

  • parent – Controls the relationship of a group of orders (e.g., bracket orders).

  • transmit – If True, transmit the order to the broker. Used for controlling bracket orders.

  • **kwargs – Additional broker-specific parameters.

Returns:

The submitted order, or None if size is 0.

Example

Create a market buy order: >>> order = self.buy()

Create a limit buy order: >>> order = self.buy(price=100.0, exectype=Order.Limit)

sell(data=None, size=None, price=None, plimit=None, exectype=None, valid=None, tradeid=0, oco=None, trailamount=None, trailpercent=None, parent=None, transmit=True, **kwargs)[source]

Create a sell (short) order and send it to the broker.

See the documentation for buy for an explanation of the parameters.

Returns:

The submitted order, or None if no order was created

close(data=None, size=None, **kwargs)[source]

Close a long or short position.

Creates an order that counters the existing position to close it.

Parameters:
  • data – The data feed for which to close the position. If None, uses the default data feed.

  • size – The size to close. If None, closes the entire position.

  • **kwargs – Additional keyword arguments passed to the order.

Note

If size is not provided, it is automatically calculated from the existing position to fully close it.

Returns:

The submitted order, or None if no position exists

buy_bracket(data=None, size=None, price=None, plimit=None, exectype=2, valid=None, tradeid=0, trailamount=None, trailpercent=None, oargs={}, stopprice=None, stopexec=3, stopargs={}, limitprice=None, limitexec=2, limitargs={}, **kwargs)[source]

Create a bracket order group (buy order with stop-loss and take-profit).

Creates a bracket order group consisting of:
  • A main buy order with the specified execution type (default: Limit)

  • A low side bracket sell stop-loss order

  • A high side bracket sell take-profit order

Parameters:
  • (default (- limitargs) – None): The data feed for the order. If None, uses the first data feed (self.data).

  • (defaultNone): Size for the order. If None, the sizer determines the size. The same size is applied to all three orders.

  • (defaultNone): Price for the main buy order. None is valid for Market and Close orders.

  • (defaultNone): Price limit for StopLimit orders.

  • (defaultNone): Absolute trailing amount for StopTrail/StopTrailLimit orders.

  • (defaultNone): Percentage trailing amount for StopTrail/StopTrailLimit orders.

  • (defaultbt.Order.Limit): Execution type for the main order. See buy() documentation for possible values.

  • (defaultNone): Order validity period. See buy() documentation for possible values.

  • (default0): Trade ID for tracking overlapping trades.

  • (default{}): Specific keyword arguments (dict) for the main side order. Applied before **kwargs.

  • **kwargs (-) – Additional keyword arguments applied to all three orders. See buy() documentation for possible values.

  • (defaultNone): Specific price for the stop-loss order.

  • (defaultbt.Order.Stop): Execution type for the stop-loss order.

  • (default{}): Specific keyword arguments (dict) for the stop-loss order.

  • (defaultNone): Specific price for the take-profit order.

  • (defaultbt.Order.Limit): Execution type for the take-profit order.

  • (default{}): Specific keyword arguments (dict) for the take-profit order.

Returns:

A list containing the three orders [main_order, stop_order, limit_order]. Suppressed orders are represented as None.

Note

High/Low side orders can be suppressed by setting limitexec=None or stopexec=None.

sell_bracket(data=None, size=None, price=None, plimit=None, exectype=2, valid=None, tradeid=0, trailamount=None, trailpercent=None, oargs={}, stopprice=None, stopexec=3, stopargs={}, limitprice=None, limitexec=2, limitargs={}, **kwargs)[source]

Create a sell bracket order group (sell order with stop-loss and take-profit).

Creates a bracket order group consisting of:
  • A main sell order with the specified execution type (default: Limit)

  • A high side bracket buy stop-loss order

  • A low side bracket buy take-profit order

Parameters:

documentation. (See buy_bracket() for parameter)

Returns:

A list containing the three orders [main_order, stop_order, limit_order]. Suppressed orders are represented as None.

Note

High/Low side orders can be suppressed by setting limitexec=None or stopexec=None.

order_target_size(data=None, target=0, **kwargs)[source]

Place an order to achieve a target position size.

Rebalances the current position to reach the specified target size.

Parameters:
  • data – The data feed for the order. If None, uses the default data feed.

  • target – Target position size. - If target > pos.size: buy (target - pos.size) - If target < pos.size: sell (pos.size - target) - If target == 0: close the entire position

  • **kwargs – Additional keyword arguments passed to buy/sell.

Returns:

The generated order, or None if target == current position size.

order_target_value(data=None, target=0.0, price=None, **kwargs)[source]

Place an order to achieve a target position value.

Rebalances the position to reach the specified target value.

Parameters:
  • data – The data feed for the order. If None, uses the default data feed.

  • target – Target position value in currency units. - If target is 0: close position - If target > value: buy to increase value - If target < value: sell to decrease value

  • price – Price for size calculation. If None, uses data.close[0].

  • **kwargs – Additional keyword arguments passed to buy/sell.

Returns:

The generated order, or None if no order was issued.

order_target_percent(data=None, target=0.0, **kwargs)[source]

Place an order to achieve a target percentage of portfolio value.

Rebalances the position so its value equals the target percentage of the total portfolio value.

Parameters:
  • data – The data feed for the order. If None, uses the default data feed.

  • target – Target percentage as a decimal (e.g., 0.05 for 5%).

  • **kwargs – Additional keyword arguments passed to order_target_value.

Returns:

The generated order, or None if no order was issued.

Example

With target=0.05 and portfolio value of 100: - Target value = 0.05 * 100 = 5 - Orders are placed through order_target_value

Note

Position direction (long/short) is considered: - If target > value: buy if pos.size >= 0, sell if pos.size < 0 - If target < value: sell if pos.size >= 0, buy if pos.size < 0

getposition(data=None, broker=None)[source]

Get the current position for a data feed.

Parameters:
  • data – The data feed to get position for. If None, uses the first data feed.

  • broker – The broker to query. If None, uses the default broker.

Returns:

The current Position object.

Note

A property position is also available as a shortcut.

property position

Get the current position for a data feed.

Parameters:
  • data – The data feed to get position for. If None, uses the first data feed.

  • broker – The broker to query. If None, uses the default broker.

Returns:

The current Position object.

Note

A property position is also available as a shortcut.

getpositionbyname(name=None, broker=None)[source]

Get the current position for a data feed by name.

Parameters:
  • name – Name of the data feed. If None, uses the first data feed.

  • broker – The broker to query. If None, uses the default broker.

Returns:

The current Position object.

Note

A property positionbyname is also available as a shortcut.

property positionbyname

Get the current position for a data feed by name.

Parameters:
  • name – Name of the data feed. If None, uses the first data feed.

  • broker – The broker to query. If None, uses the default broker.

Returns:

The current Position object.

Note

A property positionbyname is also available as a shortcut.

getpositions(broker=None)[source]

Get all positions from the broker.

Parameters:

broker – The broker to query. If None, uses the default broker.

Returns:

Dictionary mapping data feeds to Position objects.

Note

A property positions is also available as a shortcut.

property positions

Get all positions from the broker.

Parameters:

broker – The broker to query. If None, uses the default broker.

Returns:

Dictionary mapping data feeds to Position objects.

Note

A property positions is also available as a shortcut.

getpositionsbyname(broker=None)[source]

Get all positions from the broker indexed by data name.

Parameters:

broker – The broker to query. If None, uses the default broker.

Returns:

OrderedDict mapping data names to Position objects.

Note

A property positionsbyname is also available as a shortcut.

property positionsbyname

Get all positions from the broker indexed by data name.

Parameters:

broker – The broker to query. If None, uses the default broker.

Returns:

OrderedDict mapping data names to Position objects.

Note

A property positionsbyname is also available as a shortcut.

setsizer(sizer)[source]

Set the sizer for automatic stake calculation.

Parameters:

sizer – The sizer instance to use

Returns:

The sizer instance

getsizer()[source]

Get the current sizer for automatic stake calculation.

Returns:

The current sizer instance

Note

Also available as the sizer property.

property sizer

Get the current sizer for automatic stake calculation.

Returns:

The current sizer instance

Note

Also available as the sizer property.

getsizing(data=None, isbuy=True)[source]

Get the order size from the sizer.

Uses the configured sizer to calculate the appropriate stake size for the next order.

Parameters:
  • data – The data feed for the order. If None, uses the default data.

  • isbuy – True for buy orders, False for sell orders.

Returns:

The calculated stake size.

frompackages = ()
packages = ()
class backtrader.strategy.SignalStrategy[source]

Bases: Strategy

A strategy subclass that automatically operates using signals.

This strategy subclass responds to signal indicators to automatically enter and exit positions based on signal values.

Signal values:
  • > 0 indicates a long (buy) signal

  • < 0 indicates a short (sell) signal

There are five types of signals, broken into two groups:

Main Group:

  • LONGSHORT: Both long and short indications from this signal are taken. The strategy will go long or short based on the sign.

  • LONG: - Positive (long) indications: Go long - Negative (short) indications: Close long position

    • If LONGEXIT exists, it is used to exit longs

    • If SHORT signal exists and no LONGEXIT, it will close longs before opening a short

  • SHORT: - Negative (short) indications: Go short - Positive (long) indications: Close short position

    • If SHORTEXIT exists, it is used to exit shorts

    • If LONG signal exists and no SHORTEXIT, it will close shorts before opening a long

Exit Group:

These signals override others to provide explicit exit criteria:

  • LONGEXIT: Negative indications are taken to exit long positions

  • SHORTEXIT: Positive indications are taken to exit short positions

Order Issuing

Orders are placed with Market execution type and Good-Until-Canceled validity.

Params:

  • signals (default: []): A list/tuple of lists/tuples for signal instantiation and type allocation. This parameter is typically managed through cerebro.add_signal.

  • _accumulate (default: False): Allow entering the market even if already in a position (accumulate positions).

  • _concurrent (default: False): Allow issuing orders even when orders are already pending execution.

  • _data (default: None): If multiple datas are present in the system which is the target for orders. This can be

    • None: The first data in the system will be used

    • An int: indicating the data that was inserted at that position

    • An str: name given to the data when creating it (parameter name) or when adding it cerebro with cerebro.adddata(..., name=)

    • A data instance

static __new__(cls, *args, **kwargs)[source]

Override __new__ to handle next method remapping that was done in MetaSigStrategy

__init__(*args, **kwargs)
signal_add(sigtype, signal)[source]

Add a signal indicator to the strategy.

Parameters:
  • sigtype – Type of signal (e.g., SIGNAL_LONG, SIGNAL_SHORT)

  • signal – The signal indicator instance

frompackages = ()
packages = ()
class backtrader.strategy.BtApiStrategy[source]

Bases: Strategy

A Strategy subclass with built-in logging capabilities.

This strategy class extends the base Strategy class with automatic logger initialization using the SpdLogManager. It provides a default log() method for logging messages and custom notification handling.

logger

The configured logger instance from SpdLogManager.

Params:
log_file_name: Optional custom log file name. If not provided,

defaults to “{ClassName}.log”.

Example

class MyStrategy(bt.BtApiStrategy):

params = ((‘log_file_name’, ‘my_strategy.log’),)

def next(self):

self.log(f’Close price: {self.data.close[0]:.2f}’)

frompackages = ()
packages = ()
__init__(*args, **kwargs)
init_logger(log_file_name=None)[source]

Initialize and return a logger instance.

Creates a logger using SpdLogManager with the specified or default log file name.

Parameters:

log_file_name – Optional custom log file name. If None, uses “{ClassName}.log” as the default.

Returns:

A configured logger instance.

log(txt)[source]

Log a message at INFO level.

Parameters:

txt – The message text to log.