Strategy class is the abstract base class all trading strategies must extend. Override init() to set up indicators and next() to implement per-bar trading logic.
Defining a strategy
SubclassStrategy and implement the two abstract methods:
Abstract methods
Strategy.init()
- Declare all indicators with
self.I(). - Precompute any data that can be vectorized up front.
If your strategy extends a composable base strategy from
backtesting.lib, you must call super().init() at the top of your override.Strategy.next()
next():
self.dataarrays are sliced to the current bar (the last element is always the most recent value).- Indicator arrays are similarly sliced.
- Call
self.buy(),self.sell(),self.position.close(), ortrade.close()to act.
If your strategy extends a composable base strategy from
backtesting.lib, you must call super().next() at the top of your override.Strategy.I() — declare an indicator
init()) and then revealed bar-by-bar during next(), just like data.
A function that returns an array (or tuple of arrays) of the same length as
data. Common sources include TA-Lib functions, pandas rolling methods, or any custom vectorized function.*args
Positional arguments passed through to
func.**kwargs
Keyword arguments passed through to
func.Name(s) shown in the plot legend. When
None, the name is derived from the function name and its arguments. For indicators that return multiple arrays (e.g. MACD), pass a list of strings matching the number of arrays returned.Whether to include this indicator in the
plot() output.Controls indicator placement on the chart:
True— overlay on the main price/candlestick chart (suitable for moving averages).False— draw in a separate sub-panel below the price chart.None(default) — auto-detect: overlays if the majority of values fall within 30%–140% of the Close price.
Hex RGB color (e.g.
'#3498db') or an X11 color name (e.g. 'royalblue'). When None, the next available color is assigned automatically.When
True, plot the indicator as scatter points (circles) instead of a connected line.np.ndarray — the full indicator array. During next(), this is automatically sliced to the current bar length.
Strategy.buy() and Strategy.sell()
Both methods place a new order and return an Order object. They share the same parameters.
Unless
trade_on_close=True, market orders fill at the next bar’s open. Limit, stop-limit, and stop-market orders fill when their price conditions are first met.Order size. Two interpretations:
- Fraction
(0, 1)— fraction of current available equity (cash + unrealized P&L − used margin). E.g.0.5uses half of available funds. - Whole number
≥ 1— absolute number of units to trade.
_FULL_EQUITY) is approximately 1 - epsilon, meaning “use all available equity.”Limit price. When set, creates a limit order that fills only if the price reaches
limit. When None, creates a market order.Stop price. When set, creates a stop order. Combining
stop and limit creates a stop-limit order.Stop-loss price. When the resulting trade’s price reaches
sl, a contingent stop-market order is placed to close the trade. You can adjust this later via trade.sl.For long orders: sl must be below the entry price.
For short orders: sl must be above the entry price.Take-profit price. When the resulting trade’s price reaches
tp, a contingent limit order is placed to close the trade. You can adjust this later via trade.tp.For long orders: tp must be above the entry price.
For short orders: tp must be below the entry price.Arbitrary value (string, integer, dict, etc.) attached to the order and its resulting trade. Use for tracking, grouping, or conditional logic in analysis.
Order object.
Properties
Strategy.data
next() and full-length in init().
_Data provides:
- OHLCV arrays:
data.Open,data.High,data.Low,data.Close,data.Volume— NumPy arrays where[-1]is the most recent value. .saccessor:data.Close.sreturns the column as apd.Serieswith the datetime index..dfaccessor:data.dfreturns the full current slice as apd.DataFrame..pip: The smallest meaningful price increment (one pip), useful for setting SL/TP offsets..index: The datetime index of the data.- Custom columns: Any extra columns passed in the original DataFrame are accessible by attribute (e.g.
data.Sentiment).
Strategy.equity
Strategy.position
False when flat (no open trades).
| Property | Type | Description |
|---|---|---|
position.size | float | Total position size in units. Negative for net short. |
position.pl | float | Unrealized profit/loss in cash units. |
position.pl_pct | float | Unrealized profit/loss as a percentage. |
position.is_long | bool | True when net long. |
position.is_short | bool | True when net short. |
position.close(portion=1.0) closes the given fraction of all active trades.
Strategy.orders
Order exposes:
order.size— signed size (negative for shorts)order.limit,order.stop— price conditionsorder.sl,order.tp— contingent SL/TP pricesorder.tag— tracking tagorder.is_long,order.is_short,order.is_contingent— booleansorder.cancel()— cancel this order
Strategy.trades
Trade exposes:
| Property | Type | Description |
|---|---|---|
trade.size | int | Units held; negative for shorts. |
trade.entry_price | float | Price at which the trade was opened. |
trade.entry_bar | int | Bar index of entry. |
trade.entry_time | pd.Timestamp | Datetime of entry. |
trade.exit_price | float | None | Exit price (None if still open). |
trade.exit_bar | int | None | Bar index of exit. |
trade.exit_time | pd.Timestamp | None | Datetime of exit. |
trade.pl | float | Unrealized P&L in cash units. |
trade.pl_pct | float | Unrealized P&L as a percentage. |
trade.value | float | Total position value (units × price). |
trade.sl | float | None | Writable — get/set the stop-loss price. |
trade.tp | float | None | Writable — get/set the take-profit price. |
trade.tag | any | Tracking tag inherited from the originating order. |
trade.is_long | bool | True for long trades. |
trade.is_short | bool | True for short trades. |
trade.close(portion=1.0) places an order to close the given fraction of the trade.
Strategy.closed_trades
trades, with exit_price, exit_bar, and exit_time populated.
Complete example
This example demonstrates indicators, bracket orders (SL/TP), trade management, and use oftag: