OpenBB-finance/OpenBB · error · OpenBBError

Error: Moneyness must be expressed as a percentage between 0

Error message

Error: Moneyness must be expressed as a percentage between 0 and 100

What it means

Raised in OptionsChainsData._get_nearest_otm_strikes (used for ITM/OTM strike boundaries). moneyness is a percentage: values in (0, 100) exclusive are divided by 100 to a fraction; a value > 100 or < 0 after that normalization raises this error. Note the edge: exactly 0 or exactly 100 are accepted as-is (0 stays 0), and passing 0.25 means 0.25% because 0<0.25<100 triggers /100.

Source

Thrown at openbb_platform/core/openbb_core/provider/utils/options_chains_properties.py:545

        underlying_price: Optional[float]
            Only supply this is if the underlying price is not a returned field.

        Returns
        -------
        Dict[str, float]
            Dictionary of the upper (call) and lower (put) strike prices.
        """
        # pylint: disable=import-outside-toplevel
        from pandas import Series

        if moneyness is None:
            moneyness = 0.25

        if 0 < moneyness < 100:
            moneyness = moneyness / 100

        if moneyness > 100 or moneyness < 0:
            raise OpenBBError(
                "Error: Moneyness must be expressed as a percentage between 0 and 100"
            )

        df = self.dataframe

        if underlying_price is None and not hasattr(df, "underlying_price"):
            raise OpenBBError(
                "Error: underlying_price must be provided if underlying_price is not available"
            )

        if date is not None:
            date = self._get_nearest_expiration(date)
            df = df[df.expiration.astype(str) == date]
            strikes = Series(df.strike.unique().tolist())

        last_price = (
            underlying_price
            if underlying_price is not None

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Pass the value as a percent in (0, 100): moneyness=25 for 25%
  2. Do not pass fractions — 0.25 is treated as 0.25%, not 25%
  3. Clamp/validate user input on your side to 0 < moneyness < 100 before the call

Example fix

# before
strikes = res.filter_data(moneyness=0.25)  # treated as 0.25%, not 25%; 250 would raise

# after
strikes = res.filter_data(moneyness=25)  # 25 percent
Defensive patterns

Strategy: validation

Validate before calling

def normalize_moneyness(m) -> float:
    if m is None:
        return 25.0
    if not 0 < m < 100 and m not in (0, 100):
        raise ValueError("moneyness must be a percent in [0, 100]")
    return m

moneyness = normalize_moneyness(user_moneyness)

Type guard

def is_valid_moneyness(m) -> bool:
    return isinstance(m, (int, float)) and 0 <= m <= 100

Try / catch

from openbb_core.app.model.abstract.error import OpenBBError

try:
    strikes = res.filter_data(moneyness=moneyness)
except OpenBBError as e:
    if "Moneyness must be expressed" in str(e):
        strikes = res.filter_data(moneyness=25)  # default 25 percent
    else:
        raise

Prevention

When it happens

Trigger: Calling methods that take moneyness= (e.g. filter_data(moneyness=...)) with 250 (meaning 2.5x), -5, or a fraction intended as already-normalized like 0.25 (which gets re-interpreted as 0.25%). Values above 100 after no division, like moneyness=150, raise.

Common situations: Confusion between percent (25) and fraction (0.25) conventions; passing monetary strike offsets or multipliers instead of percentages.

Related errors


AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14). Data as JSON: /api/errors/aebfa8f1c5d49636. Report an issue: GitHub.