quantlab.portfolio.predefined.topk_dropout.TopkDropoutConstructor#
- class quantlab.portfolio.predefined.topk_dropout.TopkDropoutConstructor(config)[source]#
Bases:
PortfolioConstructorQlib’s TopkDropout on each rebalance bar.
For a book holding the symbols
last:today: then_drop + topk - len(last)best-scored symbols that are tradable, have a finite score and are not held.sell: the holdings among then_dropworst oflastandtodayranked together, so a holding is sold only for a better symbol. A holding without a finite score ranks worst. A locked position (held, not tradable) is never sold and keeps its weight.buy: the firstlen(sell) + topk - len(last)oftoday, so an empty or short book fills up totopk.
Kept holdings stay at their current weight (
context.current_weights); the buys split equally what the kept holdings leave of the book’s budget, or the sold weight when that is more (a side that drifted above its budget spends its sale proceeds, as qlib spends its cash). Long-short, the whole book stays within a gross of 1: the two sides’ buys share what the kept book leaves of it, and a kept book above it is scaled down, its locked positions excepted (seebook). A book holding more thantopk(locked positions) gets no candidates, so it only sells down towardtopk. Withdirection="long_only"the budget is 1; with"long_short"each side has 0.5, the short side runs the same rule on the negated scores, and its candidates exclude every holding and the bar’s long buys, so the two books never share a symbol. Ties rank by symbol order. qlib’shold_thresh, random methods and price-limit rules are not reproduced.- Parameters:
- configTopkDropoutConfig
direction,topk,n_dropandscore_label, the label ranking the symbols (Nonefor the predictor’s first label).
- Raises:
- ValueError
If
directionis not"long_only"or"long_short",topkis smaller than 1 orn_dropis negative.
Examples
>>> import numpy as np, pandas as pd, xarray as xr >>> from quantlab.portfolio.config import TopkDropoutConfig >>> from quantlab.portfolio.base import PortfolioContext >>> rule = TopkDropoutConstructor(TopkDropoutConfig(direction="long_only", topk=2, n_drop=1)) >>> symbols = ["AAA", "BBB", "CCC", "DDD"] >>> def on_symbols(values): ... return xr.DataArray(values, dims="symbol", coords={"symbol": symbols}) >>> context = PortfolioContext( ... timestamp=pd.Timestamp("2024-01-02"), ... predictions=xr.Dataset({"ret": on_symbols([0.3, 0.1, 0.2, 0.4])}), ... tradable=on_symbols([True] * 4), ... current_weights=on_symbols([0.55, 0.45, 0.0, 0.0]), ... ) >>> rule.construct(context).values # BBB makes way for DDD; AAA keeps its weight array([0.55, 0. , 0. , 0.45])
- bind(labels)[source]#
Refuse empty label specs, or specs without
score_label.Any scale ranks, so a spec’s
scaleis not read.- Raises:
- ValueError
If
labelsis empty, orscore_labelis set and not one of them; the message lists the labels.
Examples
>>> from quantlab.runs.prediction_panel import LabelSpec >>> rule = TopkDropoutConstructor(TopkDropoutConfig("long_only", 2, 1, score_label="ret_20")) >>> rule.bind([LabelSpec("ret_5", "raw", 1, 5)]) Traceback (most recent call last): ValueError: score_label 'ret_20' is not one of the predicted labels ['ret_5']
- book(scores, current, tradable, locked)[source]#
Return the book of one bar from arrays on its symbols: the rule of the class docstring.
Long-short, the book never exceeds a gross of 1: a kept book above it (the shorts lost, or a side drifted past its half) has its positions that can trade scaled down to it, and the two sides’ buys share what the kept book leaves, in the ratio of what each would spend alone. Without such a drift every weight is the one-side rule’s.
Examples
>>> rule = TopkDropoutConstructor(TopkDropoutConfig("long_short", topk=1, n_drop=0)) >>> rule.book(np.array([0.9, -0.9]), np.array([0.5, -0.51]), np.ones(2, bool), np.zeros(2, bool)).round(4) array([ 0.495, -0.505])
- config_cls#
alias of
TopkDropoutConfig
- construct(context)[source]#
Return the TopkDropout book of the context’s bar.
See the class docstring for the rule and an example.
- Parameters:
- contextPortfolioContext
The bar’s predictions, tradability and current weights.
- Returns:
- xr.DataArray
One finite weight per symbol of
context.symbols.
Examples
>>> import numpy as np, pandas as pd, xarray as xr >>> symbols = ["AAA", "BBB", "CCC", "DDD"] >>> def on_symbols(values): ... return xr.DataArray(values, dims="symbol", coords={"symbol": symbols}) >>> context = PortfolioContext( ... timestamp=pd.Timestamp("2024-01-02"), ... predictions=xr.Dataset({"ret": on_symbols([0.3, 0.1, 0.2, 0.4])}), ... tradable=on_symbols([True] * 4), ... current_weights=on_symbols([0.0] * 4), ... ) >>> rule = TopkDropoutConstructor(TopkDropoutConfig("long_short", topk=1, n_drop=1)) >>> rule.construct(context).values array([ 0. , -0.5, 0. , 0.5])