<a id="skfolio-seriation-spectralseriation"></a>

# skfolio.seriation.SpectralSeriation

<a id="skfolio.seriation.SpectralSeriation"></a>

### *class* skfolio.seriation.SpectralSeriation

Sort assets by spectral coordinates with persistent orientation.

The spectral approach is based on Atkins, Boman and Hendrickson [[1]](#r18db3246187e-1).
Each `partial_fit` recomputes coordinates from the complete current
distance matrix. Previous coordinates and ordering align the orientation
and resolve ties on assets shared with the previous snapshot. `fit` starts
a new ordering and discards this history.

For recursive portfolio allocation, spectral seriation can reduce turnover
compared with hierarchical seriation. It derives coordinates from the full
distance matrix without discrete cluster merges. Small distance changes can
then leave allocation groups unchanged. Preserving the previous solution
through `partial_fit` also avoids arbitrary changes between equivalent
spectral solutions. See [Seriation and Turnover](https://skfolio.org/user_guide/seriation.html.md#seriation-turnover) for the benefits and limits.

* **Attributes:**
  **ordering_** *ndarray of shape (n_investable_assets,)*
  : Positions in the original input matrix, listed in the computed order.
    Each investable asset appears exactly once. Empty when no assets are
    investable. A single investable asset produces its original position.

  **investable_mask_** *ndarray of shape (n_assets,)*
  : Boolean mask selecting investable assets for the current ordering.

  **coordinates_** *ndarray of shape (n_assets,)*
  : Spectral coordinates, with NaN for non-investable assets. The vector over
    investable assets has unit Euclidean norm when at least two assets are
    investable. A single investable asset has coordinate zero.

  **eigenvalue_multiplicity_** *int*
  : Dimension of the selected eigenspace. Zero for fewer than two investable
    assets.

  **spectral_gap_** *float*
  : Relative separation of the two largest nonconstant eigenvalues of the
    scaled Laplacian, $(\lambda_1 - \lambda_2) / \lambda_1$. Zero when
    these eigenvalues are numerically tied. NaN for fewer than three
    investable assets or when all distances are zero.

  **n_features_in_** *int*
  : Number of assets in the full schema.

  **feature_names_in_** *ndarray of shape (`n_features_in_`,)*
  : Asset names, defined when the input names are all strings.

### Methods

| [`fit`](#skfolio.seriation.SpectralSeriation.fit)(X[, y])            | Start a new ordering from a distance snapshot.                 |
|-------------------------------------------------------------------------|----------------------------------------------------------------|
| [`get_metadata_routing`](#skfolio.seriation.SpectralSeriation.get_metadata_routing)() | Get metadata routing of this object.                           |
| [`get_params`](#skfolio.seriation.SpectralSeriation.get_params)([deep])     | Get parameters for this estimator.                             |
| [`partial_fit`](#skfolio.seriation.SpectralSeriation.partial_fit)(X[, y])    | Order a replacement snapshot aligned to the previous ordering. |
| [`set_params`](#skfolio.seriation.SpectralSeriation.set_params)(\*\*params) | Set the parameters of this estimator.                          |

### Notes

For the investable distance matrix $D$, form $B=(D/\max(D))^2$
and $L=\mathrm{diag}(B\mathbf{1})-B$. When all distances are zero,
set $B=0$. Select the largest-eigenvalue eigenspace of $L$ on
the subspace orthogonal to the constant vector. For all-zero distances,
this is the whole nonconstant subspace.

The selected subspace is the Fiedler eigenspace of the unnormalized
Laplacian of the affinity $A=\mathbf{1}\mathbf{1}^{\mathsf{T}}-B$.
This also holds for repeated eigenvalues. With angular distances, it is
the same Fiedler subspace as the dense affinity $(1+\rho)/2$ used by
Peter Cotton’s allocation package [[2]](#r18db3246187e-2).

Repeated eigenspaces use projected previous coordinates, or a deterministic
projected anchor when history is unavailable. Ties use input positions.
Surviving assets preserve their previous relative order within coordinate
ties. Asset names are used for schema validation and do not affect the
computed coordinates or ordering.

Coordinates can change sharply when the leading eigenvalues are close, and
sorting can change allocation groups when coordinates cross. The estimator
does not minimize turnover or guarantee continuous weights.

A small `spectral_gap_` indicates weak separation of the leading direction.
A repeated leading eigenvalue gives a zero gap even if its eigenspace is
separated from the remaining directions. Small perturbations can split that
eigenvalue and change the selected coordinates. The gap is not a turnover
prediction.

Dense decomposition costs $O(k^3)$ time and $O(k^2)$ working memory
for $k$ investable assets. Only $O(n_{assets})$ orientation history
persists.

### References

* <a id='r18db3246187e-1'>**[1]**</a> “A Spectral Algorithm for Seriation and the Consecutive Ones Problem”. Jonathan E. Atkins, Erik G. Boman and Bruce Hendrickson, SIAM Journal on Computing (1998).
* <a id='r18db3246187e-2'>**[2]**</a> “allocation: Streaming online portfolio construction”. Peter Cotton (2026). [https://github.com/microprediction/allocation](https://github.com/microprediction/allocation)

<a id="skfolio.seriation.SpectralSeriation.fit"></a>

#### fit(X, y=None)

Start a new ordering from a distance snapshot.

* **Parameters:**
  **X** *array-like of shape (n_assets, n_assets)*
  : Distance snapshot. NaN diagonal entries mark non-investable assets.

  **y** *Ignored*
  : Not used, present for API consistency by convention.
* **Returns:**
  **self** *SpectralSeriation*
  : Fitted estimator.

<a id="skfolio.seriation.SpectralSeriation.get_metadata_routing"></a>

#### get_metadata_routing()

Get metadata routing of this object.

Please check [User Guide](https://skfolio.org/user_guide/metadata_routing.html.md#metadata-routing) on how the routing
mechanism works.

* **Returns:**
  **routing** *MetadataRequest*
  : A `MetadataRequest` encapsulating
    routing information.

<a id="skfolio.seriation.SpectralSeriation.get_params"></a>

#### get_params(deep=True)

Get parameters for this estimator.

* **Parameters:**
  **deep** *bool, default=True*
  : If True, will return the parameters for this estimator and
    contained subobjects that are estimators.
* **Returns:**
  **params** *dict*
  : Parameter names mapped to their values.

<a id="skfolio.seriation.SpectralSeriation.partial_fit"></a>

#### partial_fit(X, y=None)

Order a replacement snapshot aligned to the previous ordering.

Recompute spectral coordinates from the complete current distance
matrix. Use `fit` to change the full asset universe or discard history.

* **Parameters:**
  **X** *array-like of shape (n_assets, n_assets)*
  : Complete distance matrix with the same assets in the same row and
    column order as previous calls. NaN diagonal entries mark assets
    that are currently non-investable.

  **y** *Ignored*
  : Not used, present for API consistency by convention.
* **Returns:**
  **self** *SpectralSeriation*
  : Updated estimator.

<a id="skfolio.seriation.SpectralSeriation.set_params"></a>

#### set_params(\*\*params)

Set the parameters of this estimator.

The method works on simple estimators as well as on nested objects
(such as `Pipeline`). The latter have
parameters of the form `<component>__<parameter>` so that it’s
possible to update each component of a nested object.

* **Parameters:**
  **\*\*params** *dict*
  : Estimator parameters.
* **Returns:**
  **self** *estimator instance*
  : Estimator instance.

