quantlab.factor.predefined.neutralized.NeutralizedFactor#
- class quantlab.factor.predefined.neutralized.NeutralizedFactor(config)[source]#
Bases:
FactorThe outputs of
config.factor, neutralized against industry and size.On every bar, each output
yof the wrapped factor becomes:ZScore(y - intercept[industry] - b * log(marketcap))
the residual of an ordinary least-squares regression over every symbol with a finite
yand present exposures, z-scored across symbols (ddof=1).config.regressorspicks the regression: one intercept per industry plus a slope on size (the default), the industry means alone, or one intercept plus the size slope. The wrapped stock alphas already z-score their outputs, so the full chain is z-score, neutralize, z-score; the outputs are again in cross-sectional standard deviations.The exposures are read from
config.dataseton the bars of the wrapped factor’s panel, bar t’s market cap and industry for bar t. A symbol the exposures lack on a bar, or whose market cap is not positive, or whose industry code is missing, is NaN there (only the regressors in use count). A secondary share class that carries no market cap of its own (Sharadar’s GOOG beside GOOGL) is therefore NaN under size neutralization. The panel is float32, like a KunQuant factor’s.The wrapper has a store of its own (
config.file_path), written bybuildandextendand read byread, so a model that reads its factors from their stores reads the neutralized values. It is batch only: there is no stream mode, and it cannot be resampled.- Parameters:
- configNeutralizedConfig
The factor config: the wrapped
factor, the exposuresdatasetand the column names and regressors.
Examples
With
alpha158anAlpha158Stockover Sharadar prices on the permaticker axis,dailyaSharadarDailyDatasetandindustryaSharadarIndustryDataset:>>> neutral = NeutralizedFactor(NeutralizedConfig( ... factor=alpha158, dataset=[daily, industry], ... file_path="factor/alpha158_neutral.zarr", ... )) >>> neutral.get_factor_names() == alpha158.get_factor_names() True >>> neutral.build("2012-01-01", "2024-12-31") >>> panel = neutral.read("2020-01-01", "2020-12-31")
- bar_after(date, n)[source]#
Return the bar
nbars afterdateon the wrapped factor’s calendar.See
Factor.bar_afterfor the rules.Examples
>>> neutral.bar_after("2020-01-03", 1) == alpha158.bar_after("2020-01-03", 1) True
- bar_before(date, n)[source]#
Return the bar
nbars beforedateon the wrapped factor’s calendar.See
Factor.bar_beforefor the rules and errors.Examples
>>> neutral.bar_before("2020-01-06", 1) == alpha158.bar_before("2020-01-06", 1) True
- calendar(start, end)[source]#
Return the wrapped factor’s bars from
starttoend, both inclusive.The neutralized panel is on the wrapped factor’s bars, not on the exposures dataset’s; see
Factor.calendar.Examples
>>> neutral.calendar("2020-01-01", "2020-12-31").equals(alpha158.calendar("2020-01-01", "2020-12-31")) True
- compute(start, end)[source]#
Compute the neutralized outputs from
starttoend, both inclusive.The wrapped factor is computed over the range with its own warm-up; the exposures are read over the same range and placed on its bars and symbols. See
Factor.computefor the arguments.- Raises:
- ValueError
If
startis afterend.- KeyError
If the exposures dataset has no variable named by
size_columnorindustry_columnwhere that regressor is in use.
Examples
>>> panel = neutral.compute("2024-02-01", "2024-02-29") >>> tuple(panel.data_vars) == neutral.get_factor_names() True
- config_cls#
The config class
from_configrebuilds this factor with.alias of
NeutralizedConfig