pybroker.strategy module

Contains implementation for backtesting trading strategies.

class BacktestMixin[source]

Bases: object

Mixin implementing backtesting functionality.

backtest_executions(config: StrategyConfig, executions: set[Execution], before_exec_fn: Callable[[Mapping[str, ExecContext]], None] | None, after_exec_fn: Callable[[Mapping[str, ExecContext]], None] | None, sessions: Mapping[str, MutableMapping], models: Mapping[ModelSymbol, TrainedModel], indicator_data: Mapping[IndicatorSymbol, Series], test_data: DataFrame, portfolio: Portfolio, pos_size_handler: Callable[[PosSizeContext], None] | None, exit_dates: Mapping[str, datetime64], train_only: bool = False, slippage_model: SlippageModel | None = None, enable_fractional_shares: bool = False, round_fill_price: bool = True, warmup: int | None = None) dict[str, DataFrame][source]

Backtests a set of Executions that implement trading logic.

Parameters:
Returns:

Dictionary of pandas.DataFrames containing bar data, indicator data, and model predictions for each symbol when pybroker.config.StrategyConfig.return_signals is True.

class Execution(id: int, symbols: frozenset[str], fn: Callable[[ExecContext], None] | None, model_names: frozenset[str], indicator_names: frozenset[str])[source]

Bases: NamedTuple

Represents an execution of a Strategy. Holds a reference to a Callable that implements trading logic.

id

Unique ID.

Type:

int

symbols

Ticker symbols used for execution of fn.

Type:

frozenset[str]

fn

Implements trading logic.

Type:

Callable[[pybroker.context.ExecContext], None] | None

model_names

Names of pybroker.model.ModelSources used for execution of fn.

Type:

frozenset[str]

indicator_names

Names of pybroker.indicator.Indicators used for execution of fn.

Type:

frozenset[str]

class Strategy(data_source: DataSource | DataFrame, start_date: str | datetime, end_date: str | datetime, config: StrategyConfig | None = None)[source]

Bases: BacktestMixin, EvaluateMixin, IndicatorsMixin, ModelsMixin, WalkforwardMixin

Class representing a trading strategy to backtest.

Parameters:
add_execution(fn: Callable[[ExecContext], None] | None, symbols: str | Iterable[str], models: ModelSource | Iterable[ModelSource] | None = None, indicators: Indicator | Iterable[Indicator] | None = None)[source]

Adds an execution to backtest.

Parameters:
backtest(start_date: str | datetime | None = None, end_date: str | datetime | None = None, timeframe: str = '', between_time: tuple[str, str] | None = None, days: str | Day | Iterable[str | Day] | None = None, lookahead: int = 1, train_size: int = 0, shuffle: bool = False, calc_bootstrap: bool = False, disable_parallel: bool = False, warmup: int | None = None, portfolio: Portfolio | None = None) TestResult[source]

Backtests the trading strategy by running executions that were added with add_execution().

Parameters:
  • start_date – Starting date of the backtest (inclusive). Must be within start_date and end_date range that was passed to __init__().

  • end_date – Ending date of the backtest (inclusive). Must be within start_date and end_date range that was passed to __init__().

  • timeframe

    Formatted string that specifies the timeframe resolution of the backtesting data. The timeframe string supports the following units:

    • "s"/"sec": seconds

    • "m"/"min": minutes

    • "h"/"hour": hours

    • "d"/"day": days

    • "w"/"week": weeks

    An example timeframe string is 1h 30m.

  • between_timetuple[str, str] of times of day e.g. (‘9:30’, ‘16:00’) used to filter the backtesting data (inclusive).

  • days – Days (e.g. "mon", "tues" etc.) used to filter the backtesting data.

  • lookahead – Number of bars in the future of the target prediction. For example, predicting returns for the next bar would have a lookahead of 1. This quantity is needed to prevent training data from leaking into the test boundary.

  • train_size – Amount of pybroker.data.DataSource data to use for training, where the max train_size is 1. For example, a train_size of 0.9 would result in 90% of data being used for training and the remaining 10% of data being used for testing.

  • shuffle – Whether to randomly shuffle the data used for training. Defaults to False. Disabled when model caching is enabled via pybroker.cache.enable_model_cache().

  • calc_bootstrap – Whether to compute randomized bootstrap evaluation metrics. Defaults to False.

  • disable_parallel – If True, pybroker.indicator.Indicator data is computed serially. If False, pybroker.indicator.Indicator data is computed in parallel using multiple processes. Defaults to False.

  • warmup – Number of bars that need to pass before running the executions.

  • portfolio – Custom pybroker.portfolio.Portfolio to use for backtests.

Returns:

TestResult containing portfolio balances, order history, and evaluation metrics.

clear_executions()[source]

Clears executions that were added with add_execution().

set_after_exec(fn: Callable[[Mapping[str, ExecContext]], None] | None)[source]

Callable[[Mapping[str, ExecContext]] that runs after all execution functions.

Parameters:

fnCallable that takes a Mapping of all ticker symbols to ExecContexts.

set_before_exec(fn: Callable[[Mapping[str, ExecContext]], None] | None)[source]

Callable[[Mapping[str, ExecContext]] that runs before all execution functions.

Parameters:

fnCallable that takes a Mapping of all ticker symbols to ExecContexts.

set_pos_size_handler(fn: Callable[[PosSizeContext], None] | None)[source]

Sets a Callable that determines position sizes to use for buy and sell signals.

Parameters:

fnCallable invoked before placing orders for buy and sell signals, and is passed a pybroker.context.PosSizeContext.

set_slippage_model(slippage_model: SlippageModel | None)[source]

Sets pybroker.slippage.SlippageModel.

walkforward(windows: int, lookahead: int = 1, start_date: str | datetime | None = None, end_date: str | datetime | None = None, timeframe: str = '', between_time: tuple[str, str] | None = None, days: str | Day | Iterable[str | Day] | None = None, train_size: float = 0.5, shuffle: bool = False, calc_bootstrap: bool = False, disable_parallel: bool = False, warmup: int | None = None, portfolio: Portfolio | None = None) TestResult[source]

Backtests the trading strategy using Walkforward Analysis. Backtesting data supplied by the pybroker.data.DataSource is divided into windows number of equal sized time windows, with each window split into train and test data as specified by train_size. The backtest “walks forward” in time through each window, running executions that were added with add_execution().

Parameters:
  • windows – Number of walkforward time windows.

  • start_date – Starting date of the Walkforward Analysis (inclusive). Must be within start_date and end_date range that was passed to __init__().

  • end_date – Ending date of the Walkforward Analysis (inclusive). Must be within start_date and end_date range that was passed to __init__().

  • timeframe

    Formatted string that specifies the timeframe resolution of the backtesting data. The timeframe string supports the following units:

    • "s"/"sec": seconds

    • "m"/"min": minutes

    • "h"/"hour": hours

    • "d"/"day": days

    • "w"/"week": weeks

    An example timeframe string is 1h 30m.

  • between_timetuple[str, str] of times of day e.g. (‘9:30’, ‘16:00’) used to filter the backtesting data (inclusive).

  • days – Days (e.g. "mon", "tues" etc.) used to filter the backtesting data.

  • lookahead – Number of bars in the future of the target prediction. For example, predicting returns for the next bar would have a lookahead of 1. This quantity is needed to prevent training data from leaking into the test boundary.

  • train_size – Amount of pybroker.data.DataSource data to use for training, where the max train_size is 1. For example, a train_size of 0.9 would result in 90% of data being used for training and the remaining 10% of data being used for testing.

  • shuffle – Whether to randomly shuffle the data used for training. Defaults to False. Disabled when model caching is enabled via pybroker.cache.enable_model_cache().

  • calc_bootstrap – Whether to compute randomized bootstrap evaluation metrics. Defaults to False.

  • disable_parallel – If True, pybroker.indicator.Indicator data is computed serially. If False, pybroker.indicator.Indicator data is computed in parallel using multiple processes. Defaults to False.

  • warmup – Number of bars that need to pass before running the executions.

  • portfolio – Custom pybroker.portfolio.Portfolio to use for backtests.

Returns:

TestResult containing portfolio balances, order history, and evaluation metrics.

class TestResult(start_date: datetime, end_date: datetime, portfolio: DataFrame, positions: DataFrame, orders: DataFrame, trades: DataFrame, metrics: EvalMetrics, metrics_df: DataFrame, bootstrap: BootstrapResult | None, signals: dict[str, DataFrame] | None, stops: DataFrame | None)[source]

Bases: object

Contains the results of backtesting a Strategy.

start_date

Starting date of backtest.

Type:

datetime.datetime

end_date

Ending date of backtest.

Type:

datetime.datetime

portfolio

pandas.DataFrame of pybroker.portfolio.Portfolio balances for every bar.

Type:

pandas.core.frame.DataFrame

positions

pandas.DataFrame of pybroker.portfolio.Position balances for every bar.

Type:

pandas.core.frame.DataFrame

orders

pandas.DataFrame of all orders that were placed.

Type:

pandas.core.frame.DataFrame

trades

pandas.DataFrame of all trades that were made.

Type:

pandas.core.frame.DataFrame

metrics

Evaluation metrics.

Type:

pybroker.eval.EvalMetrics

metrics_df

pandas.DataFrame of evaluation metrics.

Type:

pandas.core.frame.DataFrame

bootstrap

Randomized bootstrap evaluation metrics.

Type:

pybroker.eval.BootstrapResult | None

signals

Dictionary of pandas.DataFrames containing bar data, indicator data, and model predictions for each symbol when pybroker.config.StrategyConfig.return_signals is True.

Type:

dict[str, pandas.core.frame.DataFrame] | None

stops

pandas.DataFrame containing stop data per-bar when pybroker.config.StrategyConfig.return_stops is True.

Type:

pandas.core.frame.DataFrame | None

class WalkforwardMixin[source]

Bases: object

Mixin implementing logic for Walkforward Analysis.

walkforward_split(df: DataFrame, windows: int, lookahead: int, train_size: float = 0.9, shuffle: bool = False) Iterator[WalkforwardWindow][source]

Splits a pandas.DataFrame containing data for multiple ticker symbols into an Iterator of train/test time windows for Walkforward Analysis.

Parameters:
  • dfpandas.DataFrame of data to split into train/test windows for Walkforward Analysis.

  • windows – Number of walkforward time windows.

  • lookahead – Number of bars in the future of the target prediction. For example, predicting returns for the next bar would have a lookahead of 1. This quantity is needed to prevent training data from leaking into the test boundary.

  • train_size – Amount of data in df to use for training, where the max train_size is 1. For example, a train_size of 0.9 would result in 90% of data in df being used for training and the remaining 10% of data being used for testing.

  • shuffle – Whether to randomly shuffle the data used for training. Defaults to False.

Returns:

Iterator of WalkforwardWindows containing train and test data.

class WalkforwardWindow(train_data: ndarray[Any, dtype[int64]], test_data: ndarray[Any, dtype[int64]])[source]

Bases: NamedTuple

Contains train_data and test_data of a time window used for Walkforward Analysis.

train_data

Train data.

Type:

numpy.ndarray[Any, numpy.dtype[numpy.int64]]

test_data

Test data.

Type:

numpy.ndarray[Any, numpy.dtype[numpy.int64]]