sf_quant.backtester.backtest_sequential#
- sf_quant.backtester.backtest_sequential(data: DataFrame, constraints: list[Constraint], gamma: float = 2) DataFrame#
Run a sequential backtest of portfolio optimization.
This function iterates through unique dates in the input dataset, constructs the covariance matrix for each date, and solves a mean– variance optimization (MVE) problem subject to user-specified constraints. The optimized portfolios are concatenated into a single Polars DataFrame.
Parameters#
- datapl.DataFrame
Input dataset containing at least the following columns:
date: datetime-like, the date of each observation.barrid: str, unique identifier for each asset.alpha: float, expected return (alpha) for each asset.predicted_beta: float, optional, factor exposures for constraints.
- constraintslist[Constraint]
A list of constraints (e.g.,
FullInvestment,LongOnly) to be enforced in the optimization.- gammafloat, optional
Risk aversion parameter. Higher values penalize portfolio variance more strongly. Default is 2.
Returns#
- pl.DataFrame
A PortfolioSchema-validated Polars DataFrame containing optimized portfolio weights for each date, with the following columns:
date: datetime, backtest date.barrid: str, asset identifier.weight: float, optimized portfolio weight.
Notes#
The optimization is solved using
mve_optimizer().The factor model components are constructed using
construct_factor_model_components().Results are validated against
PortfolioSchema.
See Also#
backtest_parallel : Parallelized version using Ray for faster execution. dynamic_backtest_parallel : Parallel version with active risk calibration.
Examples#
>>> import sf_quant.data as sfd >>> import sf_quant.backtester as sfb >>> import sf_quant.optimizer as sfo >>> import polars as pl >>> import datetime as dt >>> start = dt.date(2024, 1, 1) >>> end = dt.date(2024, 1, 10) >>> columns = [ ... 'date', ... 'barrid', ... ] >>> data = ( ... sfd.load_assets( ... start=start, ... end=end, ... in_universe=True, ... columns=columns ... ) ... .with_columns( ... pl.lit(0).alias('alpha') ... ) ... ) >>> constraints = [ ... sfo.FullInvestment() ... ] >>> weights = sfb.backtest_sequential( ... data=data, ... constraints=constraints, ... gamma=2, ... ) >>> weights.head() shape: (5, 3) ┌────────────┬─────────┬───────────┐ │ date ┆ barrid ┆ weight │ │ --- ┆ --- ┆ --- │ │ date ┆ str ┆ f64 │ ╞════════════╪═════════╪═══════════╡ │ 2024-01-02 ┆ USA06Z1 ┆ -0.000639 │ │ 2024-01-03 ┆ USA06Z1 ┆ -0.000644 │ │ 2024-01-04 ┆ USA06Z1 ┆ -0.000641 │ │ 2024-01-05 ┆ USA06Z1 ┆ -0.000666 │ │ 2024-01-08 ┆ USA06Z1 ┆ -0.000666 │ └────────────┴─────────┴───────────┘