Source code for merton.exceptions

"""Exception hierarchy for merton.

Every numerical or operational failure raises a :class:`MertonError` subclass.
Each carries an optional ``suggested_fix`` attribute that gets rendered when
the exception is printed.

Examples
--------
>>> raise CalibrationConvergenceError(
...     "Vassalou-Xing did not converge after 200 steps",
...     suggested_fix="Increase max_iter or relax tol.",
... )
Traceback (most recent call last):
    ...
merton.exceptions.CalibrationConvergenceError: Vassalou-Xing did not converge ...
"""

from __future__ import annotations


[docs] class MertonError(Exception): """Base class for every error raised by merton.""" def __init__(self, message: str = "", *, suggested_fix: str | None = None) -> None: super().__init__(message)
[docs] self.suggested_fix = suggested_fix
def __str__(self) -> str: base = super().__str__() if self.suggested_fix: return f"{base}\nSuggested fix: {self.suggested_fix}" return base
# --- Input / data quality -----------------------------------------------------
[docs] class MertonInputError(MertonError, ValueError): """Invalid input values supplied by the caller (NaN, negative debt, etc.)."""
[docs] class DimensionMismatchError(MertonInputError): """Two or more input arrays have incompatible shapes."""
[docs] class NonFiniteInputError(MertonInputError): """An input contains NaN or infinity where finite values are required."""
[docs] class DataQualityError(MertonError): """A passed-in panel of market data is too sparse or contains stale ticks."""
[docs] class InsufficientDataError(DataQualityError): """Not enough observations to fit / calibrate."""
# --- Calibration --------------------------------------------------------------
[docs] class CalibrationError(MertonError): """Calibration failed for some reason."""
[docs] class CalibrationConvergenceError(CalibrationError): """Iterative calibration did not converge inside ``max_iter``."""
# --- Backend dispatch ---------------------------------------------------------
[docs] class BackendError(MertonError): """Something went wrong with the array-backend dispatch layer."""
[docs] class BackendNotAvailableError(BackendError): """The requested backend extra is not installed."""
[docs] class BackendDispatchError(BackendError): """A function could not be dispatched to any available backend."""
# --- Extensions ---------------------------------------------------------------
[docs] class ExtensionError(MertonError): """An extension model (Black-Cox, Geske, …) raised an error."""
# --- Excel --------------------------------------------------------------------
[docs] class ExcelError(MertonError): """Something went wrong with the Excel integration path."""
[docs] class ManifestInstallError(ExcelError): """The Office.js add-in manifest could not be installed."""
[docs] class ServerStartupError(ExcelError): """The xlwings Server failed to start."""
# --- Warnings -----------------------------------------------------------------
[docs] class MertonWarning(UserWarning): """Base class for non-fatal warnings emitted by merton."""
[docs] class MertonBackendFallbackWarning(MertonWarning): """A requested backend was unavailable; we fell back to another."""
[docs] class MertonNumericalWarning(MertonWarning): """Iterative solver hit a numerical edge case (near-zero σ, etc.)."""
__all__ = [ "BackendDispatchError", "BackendError", "BackendNotAvailableError", "CalibrationConvergenceError", "CalibrationError", "DataQualityError", "DimensionMismatchError", "ExcelError", "ExtensionError", "InsufficientDataError", "ManifestInstallError", "MertonBackendFallbackWarning", "MertonError", "MertonInputError", "MertonNumericalWarning", "MertonWarning", "NonFiniteInputError", "ServerStartupError", ]