numeraire.core.sorts.assign_portfolio_bins#

numeraire.core.sorts.assign_portfolio_bins(signal: DataFrame, *, n_bins: int = 10, breakpoint_universe: DataFrame | None = None, eligibility: DataFrame | None = None) SortAssignments[source]#

Freeze formation-time portfolio memberships without consulting realized returns.

signal is (date x asset). eligibility optionally restricts which assets may be assigned; missing mask entries mean ineligible. breakpoint_universe optionally restricts which eligible signals define the cutoffs, while the cutoffs are still applied to all eligible assets. Both masks are aligned to signal by pandas labels, so their input order is irrelevant.

Every date must have at least n_bins finite, eligible breakpoint observations and at least n_bins distinct signal values, and its empirical quantiles must populate every requested bin. An empty, thin, or tie-degenerate breakpoint universe raises rather than silently switching to all-name breakpoints or emitting collapsed portfolios.