Source code for skfolio.descriptor._earnings_quality._analyst_dispersion_to_price
"""Analyst forecast dispersion to price descriptor."""
# Copyright (c) 2023-2026
# Author: Hugo Delatte <hugo.delatte@skfoliolabs.com>
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
import numpy as np
from skfolio.containers import AssetPanel
from skfolio.descriptor._base import BaseDescriptor
from skfolio.typing import FloatArray
from skfolio.utils.stats import safe_divide
from skfolio.utils.validation import validate_asset_panel
[docs]
class AnalystDispersionToPrice(BaseDescriptor, stateless=True):
r"""Analyst forecast dispersion to price descriptor.
Computes the ratio of analyst earnings forecast dispersion to the split-adjusted
close price:
.. math::
\text{analyst\_dispersion\_to\_price}(t) =
\frac{\text{eps\_ntm\_std}(t)}{\text{adj\_close}(t)}
Higher values indicate greater disagreement among analysts about a firm's forward
earnings relative to its price. Forecast dispersion is a proxy for earnings
uncertainty and information asymmetry. Empirically, stocks with high analyst
disagreement tend to be overpriced and earn lower future returns [1]_.
This descriptor uses per-share quantities (standard deviation of per-share EPS
forecasts divided by split-adjusted price) because analyst consensus data is
natively reported on a per-share basis.
Parameters
----------
None
Attributes
----------
n_assets_ : int
Number of assets seen during fitting.
asset_names_ : ndarray of shape (n_assets,)
Asset names seen during fitting.
Notes
-----
`eps_ntm_std` is the cross-analyst standard deviation of NTM EPS estimates,
typically provided by consensus data vendors. It should use the same
split-adjustment basis as `adj_close`.
See Also
--------
ForwardEarningsToPrice : Level of forward earnings to price.
References
----------
.. [1] "Differences of opinion and the cross section of stock returns"
The Journal of Finance. Diether, K. B., Malloy, C. J., & Scherbina, A. (2002).
Examples
--------
>>> from skfolio.datasets import make_synthetic_characteristics
>>> from skfolio.descriptor import AnalystDispersionToPrice
>>>
>>> X = make_synthetic_characteristics()
>>>
>>> descriptor = AnalystDispersionToPrice()
>>> analyst_dispersion_to_price = descriptor.fit_transform(X)
"""