<a id="skfolio-descriptor-ewdownsidebeta"></a>

# skfolio.descriptor.EWDownsideBeta

<a id="skfolio.descriptor.EWDownsideBeta"></a>

### *class* skfolio.descriptor.EWDownsideBeta(half_life=60.0, min_acceptable_return=0.0, min_periods=None, eps=1e-12)

Exponentially weighted downside beta descriptor.

Measures the sensitivity of each asset to market downturns using lower partial
co-moments. Unlike standard beta, which treats up-moves and down-moves
symmetrically, downside beta captures how much an asset tends to drop when the
market drops [[1]](#r884431b3d256-1) [[2]](#r884431b3d256-2).

The lower partial co-moment formulation is:

$$
\[
\begin{aligned}
D_i(t)
    &= \min(r_i(t) - \text{mar},\; 0) \\[0.75em]
D_m(t)
    &= \min(r_m(t) - \text{mar},\; 0) \\[0.75em]
\beta^{\text{down}}_i(t)
    &= \frac{\text{EWMA}(D_i \cdot D_m)}
            {\text{EWMA}(D_m^2)}
\end{aligned}
\]
$$

where $\text{mar}$ is the minimum acceptable return threshold and the EWMA
uses decay $\lambda = \exp(-\ln(2) / \text{half\_life})$.

The EWMA is updated at every observation. Returns above `mar` add zero downside
co-moment for that observation, while previous downside co-moments still decay.
This avoids freezing the estimator during calm periods, unlike a conditional
estimator that updates only on down-market days.

* **Parameters:**
  **half_life** *float, default=60.0*
  : EWMA half-life in observations. Controls how fast old observations decay. The
    default of 60 trading days (~3 months) balances responsiveness and stability.
    Adjust for other frequencies (e.g. `half_life=12` for weekly data).

  **min_acceptable_return** *float, default=0.0*
  : Threshold below which returns are considered “downside”. The default of `0.0`
    defines downside as negative returns (losses).

  **min_periods** *int, optional*
  : Minimum number of market observations and valid asset returns required before
    computing downside betas. Until both counts reach this value, the asset’s output
    is NaN. This warm-up period avoids exposing early EWMA values before the
    downside beta estimate has sufficiently converged from its zero initialization.
    If `None`, defaults to $\lceil\text{half\_life}\rceil$, with a minimum
    of 1.

  **eps** *float, default=1e-12*
  : Small constant for numerical stability in $1 / \text{EWMA}(D_m^2)$.
* **Attributes:**
  **n_assets_** *int*
  : Number of assets seen during fitting.

  **asset_names_** *ndarray of shape (n_assets,)*
  : Asset names seen during fitting.

  **downside_beta_** *ndarray of shape (n_assets,)*
  : Last fitted downside beta value for each asset.

### Methods

| [`fit_transform`](#skfolio.descriptor.EWDownsideBeta.fit_transform)(X[, y])         | Compute exponentially weighted downside betas.              |
|--------------------------------------------------------------------------------|-------------------------------------------------------------|
| [`get_metadata_routing`](#skfolio.descriptor.EWDownsideBeta.get_metadata_routing)()        | Get metadata routing of this object.                        |
| [`get_params`](#skfolio.descriptor.EWDownsideBeta.get_params)([deep])            | Get parameters for this estimator.                          |
| [`partial_fit_transform`](#skfolio.descriptor.EWDownsideBeta.partial_fit_transform)(X[, y]) | Update EWMA state and return downside betas for this batch. |
| [`set_params`](#skfolio.descriptor.EWDownsideBeta.set_params)(\*\*params)        | Set the parameters of this estimator.                       |

### Notes

The EWMA is initialized to zero (no bias correction). Since the initialization bias
is identical across all assets at each time step, cross-sectional rankings are
unaffected.

The market downside variance is updated at every observation. Asset co-moments are
updated only for assets with valid (non-NaN) returns and each asset’s
valid-observation count controls when its output starts. This avoids emitting
initialized values for late-listed or sparsely observed assets. The `active_mask`
property of [`AssetPanel`](https://skfolio.org/generated/skfolio.containers.AssetPanel.html.md#skfolio.containers.AssetPanel) distinguishes holidays from
delistings.

Market returns are computed from the estimation universe (`estimation_mask` of
[`AssetPanel`](https://skfolio.org/generated/skfolio.containers.AssetPanel.html.md#skfolio.containers.AssetPanel)). If no estimable asset has both finite
returns and finite `market_cap` at an observation, the market return is undefined
and a `ValueError` is raised.

### References

* <a id='r884431b3d256-1'>**[1]**</a> “Downside risk” The Review of Financial Studies. Ang, A., Chen, J., & Xing, Y. (2006).
* <a id='r884431b3d256-2'>**[2]**</a> “Systematic risk in emerging markets: the D-CAPM”. Emerging Markets Review. Estrada, J. (2002).

### Examples

```pycon
>>> from skfolio.datasets import make_synthetic_characteristics
>>> from skfolio.descriptor import EWDownsideBeta
>>>
>>> X = make_synthetic_characteristics()
>>>
>>> # Standard downside beta (losses only)
>>> descriptor = EWDownsideBeta()
>>> downside_beta = descriptor.fit_transform(X)
>>>
>>> # Custom threshold
>>> descriptor = EWDownsideBeta(min_acceptable_return=-0.01)
>>> downside_beta = descriptor.fit_transform(X)
```

<a id="skfolio.descriptor.EWDownsideBeta.fit_transform"></a>

#### fit_transform(X, y=None, \*\*fit_params)

Compute exponentially weighted downside betas.

* **Parameters:**
  **X** *AssetPanel*
  : Input panel containing `returns` and `market_cap`.

  **y** *None*
  : Ignored. Present for compatibility with scikit-learn’s API.

  **\*\*fit_params** *dict*
  : Additional fit parameters. Ignored.
* **Returns:**
  **downside_beta** *ndarray of shape (n_observations, n_assets)*
  : Downside beta for each observation and asset.

<a id="skfolio.descriptor.EWDownsideBeta.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.descriptor.EWDownsideBeta.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.descriptor.EWDownsideBeta.partial_fit_transform"></a>

#### partial_fit_transform(X, y=None, \*\*fit_params)

Update EWMA state and return downside betas for this batch.

This method supports online updates by continuing from the current fitted state.
Use `fit_transform` to start from a clean state.

* **Parameters:**
  **X** *AssetPanel*
  : Input panel containing `returns` and `market_cap`.

  **y** *None*
  : Ignored. Present for compatibility with scikit-learn’s API.

  **\*\*fit_params** *dict*
  : Additional fit parameters. Ignored.
* **Returns:**
  **downside_beta** *ndarray of shape (n_observations, n_assets)*
  : Downside beta for each observation and asset.

<a id="skfolio.descriptor.EWDownsideBeta.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.

