pybroker.strategy module
Contains implementation for backtesting trading strategies.
- class BacktestMixin[source]
Bases:
objectMixin 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
setofExecutions that implement trading logic.- Parameters:
config –
pybroker.config.StrategyConfig.executions –
Executions to run.sessions –
Mappingof symbols toMappingof custom data that persists for every bar during theExecution.models –
Mappingofpybroker.common.ModelSymbolpairs topybroker.common.TrainedModels.indicator_data –
Mappingofpybroker.common.IndicatorSymbolpairs topandas.Seriesofpybroker.indicator.Indicatorvalues.test_data –
pandas.DataFrameof test data.portfolio –
pybroker.portfolio.Portfolio.pos_size_handler –
Callablethat sets position sizes when placing orders for buy and sell signals.exit_dates –
Mappingof symbols to exit dates.train_only – Whether the backtest is run with trading rules or only trains models.
enable_fractional_shares – Whether to enable trading fractional shares.
round_fill_price – Whether to round fill prices to the nearest cent.
warmup – Number of bars that need to pass before running the executions.
- Returns:
Dictionary of
pandas.DataFrames containing bar data, indicator data, and model predictions for each symbol whenpybroker.config.StrategyConfig.return_signalsisTrue.
- class Execution(id: int, symbols: frozenset[str], fn: Callable[[ExecContext], None] | None, model_names: frozenset[str], indicator_names: frozenset[str], args: tuple[Any, ...] = (), kwargs: tuple[tuple[str, Any], ...] = ())[source]
Bases:
NamedTupleRepresents an execution of a
Strategy. Holds a reference to aCallablethat implements trading logic.- fn
Implements trading logic.
- Type:
Callable[[pybroker.context.ExecContext], None] | None
- model_names
Names of
pybroker.model.ModelSources used for execution offn.
- indicator_names
Names of
pybroker.indicator.Indicators used for execution offn.
- class Strategy(data_source: DataSource | DataFrame, start_date: str | datetime, end_date: str | datetime, config: StrategyConfig | None = None)[source]
Bases:
BacktestMixin,EvaluateMixin,IndicatorsMixin,ModelsMixin,WalkforwardMixinClass representing a trading strategy to backtest.
- Parameters:
data_source –
pybroker.data.DataSourceorpandas.DataFrameof backtesting data.start_date – Starting date of the data to fetch from
data_source(inclusive).end_date – Ending date of the data to fetch from
data_source(inclusive).config –
Optionalpybroker.config.StrategyConfig.
- add_execution(fn: ~typing.Callable[[~typing_extensions.Concatenate[~pybroker.context.ExecContext, ~P]], None] | None, symbols: str | ~typing.Iterable[str], models: ~pybroker.model.ModelSource | ~typing.Iterable[~pybroker.model.ModelSource] | None = None, indicators: ~pybroker.indicator.Indicator | ~typing.Iterable[~pybroker.indicator.Indicator] | None = None, *args: ~typing.~P, **kwargs: ~typing.~P)[source]
Adds an execution to backtest.
- Parameters:
fn –
Callableinvoked on every bar of data during the backtest and passed anpybroker.context.ExecContextfor each ticker symbol insymbols.symbols – Ticker symbols used to run
fn, wherefnis called separately for each symbol.models –
Iterableofpybroker.model.ModelSources to train/load for backtesting.indicators –
Iterableofpybroker.indicator.Indicators to compute for backtesting.args – Positional arguments passed to
fn.kwargs – Keyword arguments passed to
fn.
- 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: float = 0, shuffle: bool = False, calc_bootstrap: bool = False, disable_parallel: bool = False, warmup: int | None = None, portfolio: Portfolio | None = None, adjust: Any | None = None, seed: int | None = 42) 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_dateandend_daterange that was passed to__init__().end_date – Ending date of the backtest (inclusive). Must be within
start_dateandend_daterange 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_time –
tuple[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
lookaheadof1. This quantity is needed to prevent training data from leaking into the test boundary.train_size – Amount of
pybroker.data.DataSourcedata to use for training, where the maxtrain_sizeis1. For example, atrain_sizeof0.9would 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 viapybroker.cache.enable_model_cache().calc_bootstrap – Whether to compute randomized bootstrap evaluation metrics. Defaults to
False.disable_parallel – If
True,pybroker.indicator.Indicatordata is computed serially. IfFalse,pybroker.indicator.Indicatordata is computed in parallel using multiple processes. Defaults toFalse.warmup – Number of bars that need to pass before running the executions.
portfolio – Custom
pybroker.portfolio.Portfolioto use for backtests.adjust – The type of adjustment to make to the
pybroker.data.DataSource.seed – Random seed used for reproducibility. Defaults to
42.
- Returns:
TestResultcontaining 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:
fn –
Callablethat takes aMappingof all ticker symbols toExecContexts.
- set_before_exec(fn: Callable[[Mapping[str, ExecContext]], None] | None)[source]
Callable[[Mapping[str, ExecContext]]that runs before all execution functions.- Parameters:
fn –
Callablethat takes aMappingof all ticker symbols toExecContexts.
- set_pos_size_handler(fn: Callable[[PosSizeContext], None] | None)[source]
Sets a
Callablethat determines position sizes to use for buy and sell signals.- Parameters:
fn –
Callableinvoked before placing orders for buy and sell signals, and is passed apybroker.context.PosSizeContext.
- set_slippage_model(slippage_model: SlippageModel | None)[source]
- 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, adjust: Any | None = None, seed: int | None = 42) TestResult[source]
Backtests the trading strategy using Walkforward Analysis. Backtesting data supplied by the
pybroker.data.DataSourceis divided intowindowsnumber of equal sized time windows, with each window split into train and test data as specified bytrain_size. The backtest “walks forward” in time through each window, running executions that were added withadd_execution().- Parameters:
windows – Number of walkforward time windows.
start_date – Starting date of the Walkforward Analysis (inclusive). Must be within
start_dateandend_daterange that was passed to__init__().end_date – Ending date of the Walkforward Analysis (inclusive). Must be within
start_dateandend_daterange 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_time –
tuple[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
lookaheadof1. This quantity is needed to prevent training data from leaking into the test boundary.train_size – Amount of
pybroker.data.DataSourcedata to use for training, where the maxtrain_sizeis1. For example, atrain_sizeof0.9would 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 viapybroker.cache.enable_model_cache().calc_bootstrap – Whether to compute randomized bootstrap evaluation metrics. Defaults to
False.disable_parallel – If
True,pybroker.indicator.Indicatordata is computed serially. IfFalse,pybroker.indicator.Indicatordata is computed in parallel using multiple processes. Defaults toFalse.warmup – Number of bars that need to pass before running the executions.
portfolio – Custom
pybroker.portfolio.Portfolioto use for backtests.adjust – The type of adjustment to make to the
pybroker.data.DataSource.seed – Random seed used for reproducibility. Defaults to
42.
- Returns:
TestResultcontaining 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:
objectContains the results of backtesting a
Strategy.- start_date
Starting date of backtest.
- Type:
- end_date
Ending date of backtest.
- Type:
- portfolio
pandas.DataFrameofpybroker.portfolio.Portfoliobalances for every bar.- Type:
pandas.core.frame.DataFrame
- positions
pandas.DataFrameofpybroker.portfolio.Positionbalances for every bar.- Type:
pandas.core.frame.DataFrame
- orders
pandas.DataFrameof all orders that were placed.- Type:
pandas.core.frame.DataFrame
- trades
pandas.DataFrameof all trades that were made.- Type:
pandas.core.frame.DataFrame
- metrics
Evaluation metrics.
- metrics_df
pandas.DataFrameof evaluation metrics.- Type:
pandas.core.frame.DataFrame
- bootstrap
Randomized bootstrap evaluation metrics.
- Type:
- signals
Dictionary of
pandas.DataFrames containing bar data, indicator data, and model predictions for each symbol whenpybroker.config.StrategyConfig.return_signalsisTrue.
- stops
pandas.DataFramecontaining stop data per-bar whenpybroker.config.StrategyConfig.return_stopsisTrue.- Type:
pandas.core.frame.DataFrame | None
- class WalkforwardMixin[source]
Bases:
objectMixin 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.DataFramecontaining data for multiple ticker symbols into anIteratorof train/test time windows for Walkforward Analysis.- Parameters:
df –
pandas.DataFrameof 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
lookaheadof1. This quantity is needed to prevent training data from leaking into the test boundary.train_size – Amount of data in
dfto use for training, where the maxtrain_sizeis1. For example, atrain_sizeof0.9would result in 90% of data indfbeing 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:
IteratorofWalkforwardWindows containing train and test data.
- class WalkforwardWindow(train_data: ndarray[tuple[int, ...], dtype[int64]], test_data: ndarray[tuple[int, ...], dtype[int64]])[source]
Bases:
NamedTupleContains
train_dataandtest_dataof a time window used for Walkforward Analysis.- train_data
Train data.
- Type:
numpy.ndarray[tuple[int, …], numpy.dtype[numpy.int64]]
- test_data
Test data.
- Type:
numpy.ndarray[tuple[int, …], numpy.dtype[numpy.int64]]