Skip to content

Reusable strategies and analysis helpers

View Markdown

Import helpers from openbacktesting.lib. Use the base strategies to reuse signal execution or trailing-stop behavior, and the functions for resampling or analyzing results.

SignalStrategy · TrailingStrategy · resample_apply · MultiBacktest · barssince · quantile · compute_stats · random_ohlc_data

SignalStrategy: trade a signal series

from openbacktesting import Backtest
from openbacktesting.lib import SignalStrategy
from openbacktesting.test import GOOG

class Signals(SignalStrategy):
    def init(self):
        super().init()
        entry = (self.close.s > self.close.s.shift(1)).astype(float)
        self.set_signal(entry_size=entry, exit_portion=entry * 0 + 1)

    def next(self):
        super().next()

result = Backtest(GOOG, Signals).run()
print(result["# Trades"])

entry_size is a same-length signed series: positive buys, negative sells, zero does nothing. Sizes are asset units. exit_portion is a signed series specifying portions to close for the relevant side; zero does nothing. Signals are read on the current bar and orders follow ordinary matching timing. Call super().init() and super().next() when overriding composable bases so their behavior still runs.

SignalStrategy

Composable strategy base class driven by precomputed entry and exit signals.

Attributes

Attribute Meaning
instrument Asset rules for this run.
account Frozen snapshot of current balance, equity, actual fees, and margin.
closed_trade_stats Read frozen statistics for closed portions, including allocated fees and excluding unrealized profit or loss.

SignalStrategy.next

SignalStrategy.next()

Per-bar strategy callback, starting at input bar 0 and called once for each normally reached bar.

SignalStrategy.set_signal

SignalStrategy.set_signal(entry_size, exit_portion=None)

Register actual asset quantities and exit-fraction sequences; positive opens long, negative opens short, zero does not enter.

Inherited methods

Use the Strategy methods for order sizing, targets, and lifecycle hooks:

order_target_value · order_target_quantity · order_target_percent · on_finish · close_position · on_start · on_fill · submit_oco · on_order

TrailingStrategy: update ATR-based protection

from openbacktesting import Backtest
from openbacktesting.lib import TrailingStrategy
from openbacktesting.test import GOOG

class TrailingEntry(TrailingStrategy):
    def init(self):
        super().init()
        self.set_trailing_sl(n_atr=3)

    def next(self):
        super().next()
        if self.bar_index == 120:
            self.buy(qty=1)

result = Backtest(GOOG, TrailingEntry).run()
print(result["Return [%]"])

set_atr_periods(periods=100) sets the ATR lookback. set_trailing_sl(n_atr=6) sets a multiple of ATR, updated by the base next(). set_trailing_pct(pct=0.05) instead trails by 5% of the current confirmed close, independently of ATR readiness. Stops ratchet in the favorable direction and updates take effect no earlier than the next bar. The base strategy manages protection but does not create entry signals for you.

TrailingStrategy

Composable strategy base class that updates trade stop losses using ATR.

Attributes

Attribute Meaning
instrument Asset rules for this run.
account Frozen snapshot of current balance, equity, actual fees, and margin.
closed_trade_stats Read frozen statistics for closed portions, including allocated fees and excluding unrealized profit or loss.

TrailingStrategy.init

TrailingStrategy.init()

Strategy initialization entry point for precomputation and indicator registration; complete historical data is accessible.

TrailingStrategy.next

TrailingStrategy.next()

Per-bar strategy callback, starting at input bar 0 and called once for each normally reached bar.

TrailingStrategy.set_atr_periods

TrailingStrategy.set_atr_periods(periods=100)

Set the causal ATR window, default 100; do not backfill or set ATR stops during warmup.

TrailingStrategy.set_trailing_pct

TrailingStrategy.set_trailing_pct(pct=0.05)

Calculate percentage distance from the currently confirmed price, default 5%, without full-sample estimation.

TrailingStrategy.set_trailing_sl

TrailingStrategy.set_trailing_sl(n_atr=6)

Set the ATR multiple for subsequent trailing stops.

Inherited methods

Use the Strategy methods for order sizing, targets, and lifecycle hooks:

order_target_value · order_target_quantity · order_target_percent · on_finish · close_position · on_start · on_fill · submit_oco · on_order

Use a higher timeframe

In init(), resample_apply(rule, func, series, *args, agg=None, **kwargs) resamples indexed market data, runs a calculation, and aligns the completed values to the original bars. For example, use a daily rolling mean from hourly data. The result inside a strategy is a registered handle; check its validity in next(). rule is a pandas resampling rule; agg chooses aggregation or defaults to the appropriate OHLCV rule. Your function must return an aligned result for the resampled series.

from openbacktesting.lib import resample_apply

def init(self):
    self.weekly_mean = resample_apply(
        "W-FRI", lambda values: values.rolling(3).mean(), self.data.Close,
    )

resample_apply

lib.resample_apply(rule, func, series, *args, agg=None, **kwargs)

Resample and apply the function, then align to the original calendar; automatically register the result handle within strategy initialization.

Compare several assets

MultiBacktest([data_a, data_b], MyStrategy, **backtest_kwargs) runs the same strategy independently for each dataset. .run(**strategy_params) returns a DataFrame of results; .optimize(**search_options) returns per-dataset parameter scores. This is a collection of separate accounts, not a multi-asset portfolio sharing capital.

MultiBacktest

lib.MultiBacktest(df_list, strategy_cls, **kwargs)

Run one strategy on multiple datasets and aggregate statistics for each dataset.

MultiBacktest.optimize

MultiBacktest.optimize(**kwargs)

Optimize parameters separately for each dataset and aggregate parameter scores.

MultiBacktest.run

MultiBacktest.run(**kwargs)

Backtest each dataset and return statistics in dataset columns.

Analyze or generate data

Helper Usage
barssince(condition, default=inf) Number of bars since the most recent truthy value; returns default if none.
quantile(series, quantile=None) Omit quantile for the last value's rank; pass a fraction such as 0.9 for that quantile value.
compute_stats(stats=result, data=data, trades=subset) Recompute statistics for a selected trade table, optionally with risk_free_rate. Does not rerun orders.
random_ohlc_data(data, frac=1.0, random_state=0) Generator of synthetic OHLC samples; next(generator) returns a DataFrame.
OHLCV_AGG, TRADES_AGG Dictionaries for pandas resampling/aggregation.

barssince

lib.barssince(condition, default=inf)

Query the distance from the current position to the latest true condition; this is a scalar helper.

quantile

lib.quantile(series, quantile=None)

Query the relative rank of the last value or a specified quantile value, depending on quantile.

compute_stats

lib.compute_stats(*, stats, data, trades=None, risk_free_rate=...)

Recompute performance statistics from existing results, data, and an optional trade subset.

random_ohlc_data

lib.random_ohlc_data(example_data, *, frac=1.0, random_state=None)

Iteratively generate random samples preserving basic market-data structure; these are not real-market forecasts.

OHLCV_AGG

lib.OHLCV_AGG = OrderedDict({'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last', 'Volume': 'sum'})

TRADES_AGG

lib.TRADES_AGG = OrderedDict({'Size': 'sum', 'EntryBar': 'first', 'ExitBar': 'last', 'EntryPrice': 'mean', 'ExitPrice': 'mean', 'PnL': 'sum', 'ReturnPct': 'mean', 'EntryTime': 'first', 'ExitTime': 'last', 'Duration': 'sum'})

Strategy · Backtest · User manual