sf_quant.research.vol_scale_ports#

sf_quant.research.vol_scale_ports(df: DataFrame, target_vol: float = 0.05, window: int = 22) DataFrame#

Scale portfolio returns to a target volatility level in place.

This function standardizes portfolio returns by scaling them to achieve a specified target volatility based on rolling historical volatility. The scaling factor is computed using a rolling window and annualized assuming 252 trading days per year. Original return columns are replaced with their scaled versions.

Parameters#

dfpl.DataFrame

Portfolio returns data containing columns starting with p_ or named spread. Additional columns are preserved.

target_volfloat, optional

Target annualized volatility level (default: 0.05 for 5%). Returns are scaled to achieve this volatility.

windowint, optional

Rolling window size in days for volatility calculation (default: 22). Typically set to one month of trading days.

Returns#

pl.DataFrame

The DataFrame with volatility-scaled return columns:

  • p_1, p_2, …, p_{num_bins} (float): Vol-scaled returns.

  • spread (float): Vol-scaled long-short spread.

Notes#

  • Scaling factor = target_vol / (rolling_std * sqrt(252))

  • Only columns starting with p_ or named spread are scaled.

  • Original return values are replaced with scaled versions.

  • Early rows (< window size) will have null scaled values.

Examples#

>>> import polars as pl
>>> import sf_quant.research as sfr
>>> import datetime as dt
>>> ports = pl.DataFrame({
...     'date': [dt.date(2024, 1, i) for i in range(1, 30)],
...     'p_1': [0.01] * 29,
...     'p_10': [0.02] * 29,
...     'spread': [0.01] * 29
... })
>>> scaled = sfr.vol_scale_ports(ports, target_vol=0.10, window=20)
>>> scaled.columns
['date', 'p_1', 'p_10', 'spread']