sf_quant.backtester.backtest_parallel#
- sf_quant.backtester.backtest_parallel(data: DataFrame, constraints: list[Constraint], gamma: float = 2, n_cpus: int | None = None) DataFrame#
Run a parallelized backtest of portfolio optimization using Ray.
This function distributes portfolio construction tasks across multiple CPUs with Ray, solving mean–variance optimization problems for each date in parallel. A Ray-based progress bar tracks computation progress.
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]
List of portfolio constraints to enforce during optimization.
- gammafloat, optional
Risk aversion parameter. Higher values penalize portfolio variance more strongly. Default is 2.
- n_cpusint, optional
Number of CPUs to allocate to Ray. If
None, defaults toos.cpu_count()but is capped at the number of unique dates.
Returns#
- pl.DataFrame
A PortfolioSchema-validated Polars DataFrame containing optimized portfolio weights across all backtest dates, with columns:
date: datetime, portfolio date.barrid: str, asset identifier.weight: float, optimized portfolio weight.
Notes#
Ray is initialized with
ignore_reinit_error=True, allowing safe re-invocation within the same process.The number of CPUs is automatically limited to the number of unique dates to avoid unnecessary idle workers.
See Also#
backtest_sequential : Sequential version for smaller datasets or debugging. 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_parallel( ... data=data, ... constraints=constraints, ... gamma=2, ... ) shape: (5, 3) ┌────────────┬─────────┬───────────┐ │ date ┆ barrid ┆ weight │ │ --- ┆ --- ┆ --- │ │ date ┆ str ┆ f64 │ ╞════════════╪═════════╪═══════════╡ │ 2024-01-02 ┆ USA06Z1 ┆ -0.000639 │ │ 2024-01-02 ┆ USA0771 ┆ -0.000083 │ │ 2024-01-02 ┆ USA0C11 ┆ -0.003044 │ │ 2024-01-02 ┆ USA0SY1 ┆ -0.002177 │ │ 2024-01-02 ┆ USA11I1 ┆ 0.001475 │ └────────────┴─────────┴───────────┘