# Reusable strategies and analysis helpers



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](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-signalstrategy) · [TrailingStrategy](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-trailingstrategy) · [resample_apply](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-resample-apply) · [MultiBacktest](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-multibacktest) · [barssince](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-barssince) · [quantile](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-quantile) · [compute_stats](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-compute-stats) · [random_ohlc_data](https://docs.openbacktesting.com/reference/helpers/#openbacktesting-lib-random-ohlc-data)

## SignalStrategy: trade a signal series

```python
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.

<a id="openbacktesting-lib-signalstrategy"></a>



## SignalStrategy

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

### Attributes

| Attribute | Meaning |
| --- | --- |
| <a id="openbacktesting-lib-signalstrategy-instrument"></a>`instrument` | Asset rules for this run. |
| <a id="openbacktesting-lib-signalstrategy-account"></a>`account` | Frozen snapshot of current balance, equity, actual fees, and margin. |
| <a id="openbacktesting-lib-signalstrategy-closed-trade-stats"></a>`closed_trade_stats` | Read frozen statistics for closed portions, including allocated fees and excluding unrealized profit or loss. |

<a id="openbacktesting-lib-signalstrategy-next"></a>



### SignalStrategy.next

```python
SignalStrategy.next()
```

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

<a id="openbacktesting-lib-signalstrategy-set-signal"></a>



### SignalStrategy.set_signal

```python
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](https://docs.openbacktesting.com/reference/strategy/index.md) for order sizing, targets, and lifecycle hooks:

<a id="openbacktesting-lib-signalstrategy-order-target-value"></a>[order_target_value](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-value) · <a id="openbacktesting-lib-signalstrategy-order-target-quantity"></a>[order_target_quantity](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-quantity) · <a id="openbacktesting-lib-signalstrategy-order-target-percent"></a>[order_target_percent](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-percent) · <a id="openbacktesting-lib-signalstrategy-on-finish"></a>[on_finish](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-finish) · <a id="openbacktesting-lib-signalstrategy-close-position"></a>[close_position](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-close-position) · <a id="openbacktesting-lib-signalstrategy-on-start"></a>[on_start](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-start) · <a id="openbacktesting-lib-signalstrategy-on-fill"></a>[on_fill](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-fill) · <a id="openbacktesting-lib-signalstrategy-submit-oco"></a>[submit_oco](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-submit-oco) · <a id="openbacktesting-lib-signalstrategy-on-order"></a>[on_order](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-order)

## TrailingStrategy: update ATR-based protection

```python
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.

<a id="openbacktesting-lib-trailingstrategy"></a>



## TrailingStrategy

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

### Attributes

| Attribute | Meaning |
| --- | --- |
| <a id="openbacktesting-lib-trailingstrategy-instrument"></a>`instrument` | Asset rules for this run. |
| <a id="openbacktesting-lib-trailingstrategy-account"></a>`account` | Frozen snapshot of current balance, equity, actual fees, and margin. |
| <a id="openbacktesting-lib-trailingstrategy-closed-trade-stats"></a>`closed_trade_stats` | Read frozen statistics for closed portions, including allocated fees and excluding unrealized profit or loss. |

<a id="openbacktesting-lib-trailingstrategy-init"></a>



### TrailingStrategy.init

```python
TrailingStrategy.init()
```

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

<a id="openbacktesting-lib-trailingstrategy-next"></a>



### TrailingStrategy.next

```python
TrailingStrategy.next()
```

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

<a id="openbacktesting-lib-trailingstrategy-set-atr-periods"></a>



### TrailingStrategy.set_atr_periods

```python
TrailingStrategy.set_atr_periods(periods=100)
```

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

<a id="openbacktesting-lib-trailingstrategy-set-trailing-pct"></a>



### TrailingStrategy.set_trailing_pct

```python
TrailingStrategy.set_trailing_pct(pct=0.05)
```

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

<a id="openbacktesting-lib-trailingstrategy-set-trailing-sl"></a>



### TrailingStrategy.set_trailing_sl

```python
TrailingStrategy.set_trailing_sl(n_atr=6)
```

Set the ATR multiple for subsequent trailing stops.

### Inherited methods

Use the [Strategy methods](https://docs.openbacktesting.com/reference/strategy/index.md) for order sizing, targets, and lifecycle hooks:

<a id="openbacktesting-lib-trailingstrategy-order-target-value"></a>[order_target_value](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-value) · <a id="openbacktesting-lib-trailingstrategy-order-target-quantity"></a>[order_target_quantity](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-quantity) · <a id="openbacktesting-lib-trailingstrategy-order-target-percent"></a>[order_target_percent](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-order-target-percent) · <a id="openbacktesting-lib-trailingstrategy-on-finish"></a>[on_finish](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-finish) · <a id="openbacktesting-lib-trailingstrategy-close-position"></a>[close_position](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-close-position) · <a id="openbacktesting-lib-trailingstrategy-on-start"></a>[on_start](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-start) · <a id="openbacktesting-lib-trailingstrategy-on-fill"></a>[on_fill](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-on-fill) · <a id="openbacktesting-lib-trailingstrategy-submit-oco"></a>[submit_oco](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-submit-oco) · <a id="openbacktesting-lib-trailingstrategy-on-order"></a>[on_order](https://docs.openbacktesting.com/reference/strategy/index.md#openbacktesting-strategy-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.

```python
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,
    )
```

<a id="openbacktesting-lib-resample-apply"></a>



## resample_apply

```python
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.

<a id="openbacktesting-lib-multibacktest"></a>



## MultiBacktest

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

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

<a id="openbacktesting-lib-multibacktest-optimize"></a>



### MultiBacktest.optimize

```python
MultiBacktest.optimize(**kwargs)
```

Optimize parameters separately for each dataset and aggregate parameter scores.

<a id="openbacktesting-lib-multibacktest-run"></a>



### MultiBacktest.run

```python
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. |

<a id="openbacktesting-lib-barssince"></a>



## barssince

```python
lib.barssince(condition, default=inf)
```

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

<a id="openbacktesting-lib-quantile"></a>



## quantile

```python
lib.quantile(series, quantile=None)
```

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

<a id="openbacktesting-lib-compute-stats"></a>



## compute_stats

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

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

<a id="openbacktesting-lib-random-ohlc-data"></a>



## random_ohlc_data

```python
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.

<a id="openbacktesting-lib-ohlcv-agg"></a>



## OHLCV_AGG

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

<a id="openbacktesting-lib-trades-agg"></a>



## 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](https://docs.openbacktesting.com/reference/strategy/index.md) · [Backtest](https://docs.openbacktesting.com/reference/core/index.md) · [User manual](https://docs.openbacktesting.com/index.md)
