Skip to content

Exceptions

All basanos exceptions inherit from BasanosError, so callers can catch the base class or a specific subclass as needed.

BasanosError

basanos.BasanosError

Bases: Exception

Base class for all Basanos domain errors.

Source code in src/basanos/exceptions.py
class BasanosError(Exception):
    """Base class for all Basanos domain errors."""

Input-validation errors

basanos.ColumnMismatchError

Bases: BasanosError, ValueError

Raised when two DataFrames have different column sets.

Parameters:

Name Type Description Default
prices_columns list[str]

Columns of the prices DataFrame.

required
mu_columns list[str]

Columns of the mu DataFrame.

required

Examples:

>>> raise ColumnMismatchError(["A", "B"], ["A", "C"])
Traceback (most recent call last):
    ...
basanos.exceptions.ColumnMismatchError: 'prices' and 'mu' must have identical columns...
Source code in src/basanos/exceptions.py
class ColumnMismatchError(BasanosError, ValueError):
    """Raised when two DataFrames have different column sets.

    Args:
        prices_columns: Columns of the prices DataFrame.
        mu_columns: Columns of the mu DataFrame.

    Examples:
        >>> raise ColumnMismatchError(["A", "B"], ["A", "C"])  # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        basanos.exceptions.ColumnMismatchError: 'prices' and 'mu' must have identical columns...
    """

    def __init__(self, prices_columns: list[str], mu_columns: list[str]) -> None:
        """Initialize with the column lists of the two mismatched DataFrames."""
        super().__init__(
            f"'prices' and 'mu' must have identical columns; got {sorted(prices_columns)} vs {sorted(mu_columns)}."
        )
        self.prices_columns = prices_columns
        self.mu_columns = mu_columns

__init__(prices_columns, mu_columns)

Initialize with the column lists of the two mismatched DataFrames.

Source code in src/basanos/exceptions.py
def __init__(self, prices_columns: list[str], mu_columns: list[str]) -> None:
    """Initialize with the column lists of the two mismatched DataFrames."""
    super().__init__(
        f"'prices' and 'mu' must have identical columns; got {sorted(prices_columns)} vs {sorted(mu_columns)}."
    )
    self.prices_columns = prices_columns
    self.mu_columns = mu_columns

basanos.DimensionMismatchError

Bases: BasanosError, ValueError

Raised when vector and matrix dimensions are incompatible.

Parameters:

Name Type Description Default
vector_size int

Length of the offending vector.

required
matrix_size int

Expected dimension inferred from the matrix.

required

Examples:

>>> raise DimensionMismatchError(3, 2)
Traceback (most recent call last):
    ...
basanos.exceptions.DimensionMismatchError: Vector length 3 does not match matrix dimension 2.
Source code in src/basanos/exceptions.py
class DimensionMismatchError(BasanosError, ValueError):
    """Raised when vector and matrix dimensions are incompatible.

    Args:
        vector_size: Length of the offending vector.
        matrix_size: Expected dimension inferred from the matrix.

    Examples:
        >>> raise DimensionMismatchError(3, 2)
        Traceback (most recent call last):
            ...
        basanos.exceptions.DimensionMismatchError: Vector length 3 does not match matrix dimension 2.
    """

    def __init__(self, vector_size: int, matrix_size: int) -> None:
        """Initialize with the offending vector and matrix sizes."""
        super().__init__(f"Vector length {vector_size} does not match matrix dimension {matrix_size}.")
        self.vector_size = vector_size
        self.matrix_size = matrix_size

__init__(vector_size, matrix_size)

Initialize with the offending vector and matrix sizes.

Source code in src/basanos/exceptions.py
def __init__(self, vector_size: int, matrix_size: int) -> None:
    """Initialize with the offending vector and matrix sizes."""
    super().__init__(f"Vector length {vector_size} does not match matrix dimension {matrix_size}.")
    self.vector_size = vector_size
    self.matrix_size = matrix_size

basanos.ExcessiveNullsError

Bases: BasanosError, ValueError

Raised when an asset column contains too many null values.

Parameters:

Name Type Description Default
asset str

Name of the offending asset column.

required
null_fraction float

Observed fraction of null values (0.0 to 1.0).

required
max_fraction float

Maximum allowed fraction of null values.

required

Examples:

>>> raise ExcessiveNullsError("A", 1.0, 0.9)
Traceback (most recent call last):
    ...
basanos.exceptions.ExcessiveNullsError: Asset 'A' has 100% null values,...
Source code in src/basanos/exceptions.py
class ExcessiveNullsError(BasanosError, ValueError):
    """Raised when an asset column contains too many null values.

    Args:
        asset: Name of the offending asset column.
        null_fraction: Observed fraction of null values (0.0 to 1.0).
        max_fraction: Maximum allowed fraction of null values.

    Examples:
        >>> raise ExcessiveNullsError("A", 1.0, 0.9)  # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        basanos.exceptions.ExcessiveNullsError: Asset 'A' has 100% null values,...
    """

    def __init__(self, asset: str, null_fraction: float, max_fraction: float) -> None:
        """Initialize with the asset name and the observed/maximum null fractions."""
        super().__init__(
            f"Asset '{asset}' has {null_fraction:.0%} null values, "
            f"exceeding the maximum allowed fraction of {max_fraction:.0%}."
        )
        self.asset = asset
        self.null_fraction = null_fraction
        self.max_fraction = max_fraction

__init__(asset, null_fraction, max_fraction)

Initialize with the asset name and the observed/maximum null fractions.

Source code in src/basanos/exceptions.py
def __init__(self, asset: str, null_fraction: float, max_fraction: float) -> None:
    """Initialize with the asset name and the observed/maximum null fractions."""
    super().__init__(
        f"Asset '{asset}' has {null_fraction:.0%} null values, "
        f"exceeding the maximum allowed fraction of {max_fraction:.0%}."
    )
    self.asset = asset
    self.null_fraction = null_fraction
    self.max_fraction = max_fraction

basanos.InsufficientDataError

Bases: BasanosError, ValueError

Raised when there are too few finite entries to perform a computation.

Examples:

>>> raise InsufficientDataError("All diagonal entries are non-finite.")
Traceback (most recent call last):
    ...
basanos.exceptions.InsufficientDataError: All diagonal entries are non-finite.
Source code in src/basanos/exceptions.py
class InsufficientDataError(BasanosError, ValueError):
    """Raised when there are too few finite entries to perform a computation.

    Examples:
        >>> raise InsufficientDataError("All diagonal entries are non-finite.")
        Traceback (most recent call last):
            ...
        basanos.exceptions.InsufficientDataError: All diagonal entries are non-finite.
    """

    def __init__(self, detail: str = "") -> None:
        """Initialize with an optional detail message that overrides the default."""
        msg = "Insufficient finite data to complete the computation."
        if detail:
            msg = detail
        super().__init__(msg)

__init__(detail='')

Initialize with an optional detail message that overrides the default.

Source code in src/basanos/exceptions.py
def __init__(self, detail: str = "") -> None:
    """Initialize with an optional detail message that overrides the default."""
    msg = "Insufficient finite data to complete the computation."
    if detail:
        msg = detail
    super().__init__(msg)

basanos.MissingDateColumnError

Bases: BasanosError, ValueError

Raised when a required 'date' column is absent from a DataFrame.

Parameters:

Name Type Description Default
frame_name str

Descriptive name of the frame missing the column (e.g. "prices").

required

Examples:

>>> raise MissingDateColumnError("prices")
Traceback (most recent call last):
    ...
basanos.exceptions.MissingDateColumnError: DataFrame 'prices' is missing the required 'date' column.
Source code in src/basanos/exceptions.py
class MissingDateColumnError(BasanosError, ValueError):
    """Raised when a required ``'date'`` column is absent from a DataFrame.

    Args:
        frame_name: Descriptive name of the frame missing the column (e.g. ``"prices"``).

    Examples:
        >>> raise MissingDateColumnError("prices")
        Traceback (most recent call last):
            ...
        basanos.exceptions.MissingDateColumnError: DataFrame 'prices' is missing the required 'date' column.
    """

    def __init__(self, frame_name: str) -> None:
        """Initialize with the name of the frame that is missing the column."""
        super().__init__(f"DataFrame '{frame_name}' is missing the required 'date' column.")
        self.frame_name = frame_name

__init__(frame_name)

Initialize with the name of the frame that is missing the column.

Source code in src/basanos/exceptions.py
def __init__(self, frame_name: str) -> None:
    """Initialize with the name of the frame that is missing the column."""
    super().__init__(f"DataFrame '{frame_name}' is missing the required 'date' column.")
    self.frame_name = frame_name

basanos.MonotonicPricesError

Bases: BasanosError, ValueError

Raised when an asset's price series is strictly monotonic.

A monotonic series (all non-decreasing or all non-increasing) has no variance in its return sign, indicating malformed or synthetic data.

Parameters:

Name Type Description Default
asset str

Name of the offending asset column.

required

Examples:

>>> raise MonotonicPricesError("A")
Traceback (most recent call last):
    ...
basanos.exceptions.MonotonicPricesError: Asset 'A' has monotonic prices...
Source code in src/basanos/exceptions.py
class MonotonicPricesError(BasanosError, ValueError):
    """Raised when an asset's price series is strictly monotonic.

    A monotonic series (all non-decreasing or all non-increasing) has no
    variance in its return sign, indicating malformed or synthetic data.

    Args:
        asset: Name of the offending asset column.

    Examples:
        >>> raise MonotonicPricesError("A")  # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        basanos.exceptions.MonotonicPricesError: Asset 'A' has monotonic prices...
    """

    def __init__(self, asset: str) -> None:
        """Initialize with the name of the asset that has monotonic prices."""
        super().__init__(
            f"Asset '{asset}' has monotonic prices "
            "(all non-decreasing or all non-increasing), indicating malformed or synthetic data."
        )
        self.asset = asset

__init__(asset)

Initialize with the name of the asset that has monotonic prices.

Source code in src/basanos/exceptions.py
def __init__(self, asset: str) -> None:
    """Initialize with the name of the asset that has monotonic prices."""
    super().__init__(
        f"Asset '{asset}' has monotonic prices "
        "(all non-decreasing or all non-increasing), indicating malformed or synthetic data."
    )
    self.asset = asset

basanos.NonPositivePricesError

Bases: BasanosError, ValueError

Raised when an asset column contains zero or negative prices.

Log-return computation requires strictly positive prices.

Parameters:

Name Type Description Default
asset str

Name of the asset with the offending values.

required

Examples:

>>> raise NonPositivePricesError("A")
Traceback (most recent call last):
    ...
basanos.exceptions.NonPositivePricesError: Asset 'A' contains non-positive...
Source code in src/basanos/exceptions.py
class NonPositivePricesError(BasanosError, ValueError):
    """Raised when an asset column contains zero or negative prices.

    Log-return computation requires strictly positive prices.

    Args:
        asset: Name of the asset with the offending values.

    Examples:
        >>> raise NonPositivePricesError("A")  # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        basanos.exceptions.NonPositivePricesError: Asset 'A' contains non-positive...
    """

    def __init__(self, asset: str) -> None:
        """Initialize with the name of the asset that contains non-positive prices."""
        super().__init__(f"Asset '{asset}' contains non-positive prices; strictly positive values are required.")
        self.asset = asset

__init__(asset)

Initialize with the name of the asset that contains non-positive prices.

Source code in src/basanos/exceptions.py
def __init__(self, asset: str) -> None:
    """Initialize with the name of the asset that contains non-positive prices."""
    super().__init__(f"Asset '{asset}' contains non-positive prices; strictly positive values are required.")
    self.asset = asset

basanos.NonSquareMatrixError

Bases: BasanosError, ValueError

Raised when a matrix is required to be square but is not.

Parameters:

Name Type Description Default
rows int

Number of rows in the offending matrix.

required
cols int

Number of columns in the offending matrix.

required

Examples:

>>> raise NonSquareMatrixError(3, 2)
Traceback (most recent call last):
    ...
basanos.exceptions.NonSquareMatrixError: Matrix must be square, got shape (3, 2).
Source code in src/basanos/exceptions.py
class NonSquareMatrixError(BasanosError, ValueError):
    """Raised when a matrix is required to be square but is not.

    Args:
        rows: Number of rows in the offending matrix.
        cols: Number of columns in the offending matrix.

    Examples:
        >>> raise NonSquareMatrixError(3, 2)
        Traceback (most recent call last):
            ...
        basanos.exceptions.NonSquareMatrixError: Matrix must be square, got shape (3, 2).
    """

    def __init__(self, rows: int, cols: int) -> None:
        """Initialize with the offending matrix shape."""
        super().__init__(f"Matrix must be square, got shape ({rows}, {cols}).")
        self.rows = rows
        self.cols = cols

__init__(rows, cols)

Initialize with the offending matrix shape.

Source code in src/basanos/exceptions.py
def __init__(self, rows: int, cols: int) -> None:
    """Initialize with the offending matrix shape."""
    super().__init__(f"Matrix must be square, got shape ({rows}, {cols}).")
    self.rows = rows
    self.cols = cols

basanos.ShapeMismatchError

Bases: BasanosError, ValueError

Raised when two DataFrames have incompatible shapes.

Parameters:

Name Type Description Default
prices_shape tuple[int, int]

Shape of the prices DataFrame.

required
mu_shape tuple[int, int]

Shape of the mu DataFrame.

required

Examples:

>>> raise ShapeMismatchError((10, 3), (9, 3))
Traceback (most recent call last):
    ...
basanos.exceptions.ShapeMismatchError: 'prices' and 'mu' must have the same shape, got (10, 3) vs (9, 3).
Source code in src/basanos/exceptions.py
class ShapeMismatchError(BasanosError, ValueError):
    """Raised when two DataFrames have incompatible shapes.

    Args:
        prices_shape: Shape of the prices DataFrame.
        mu_shape: Shape of the mu DataFrame.

    Examples:
        >>> raise ShapeMismatchError((10, 3), (9, 3))
        Traceback (most recent call last):
            ...
        basanos.exceptions.ShapeMismatchError: 'prices' and 'mu' must have the same shape, got (10, 3) vs (9, 3).
    """

    def __init__(self, prices_shape: tuple[int, int], mu_shape: tuple[int, int]) -> None:
        """Initialize with the shapes of the two mismatched DataFrames."""
        super().__init__(f"'prices' and 'mu' must have the same shape, got {prices_shape} vs {mu_shape}.")
        self.prices_shape = prices_shape
        self.mu_shape = mu_shape

__init__(prices_shape, mu_shape)

Initialize with the shapes of the two mismatched DataFrames.

Source code in src/basanos/exceptions.py
def __init__(self, prices_shape: tuple[int, int], mu_shape: tuple[int, int]) -> None:
    """Initialize with the shapes of the two mismatched DataFrames."""
    super().__init__(f"'prices' and 'mu' must have the same shape, got {prices_shape} vs {mu_shape}.")
    self.prices_shape = prices_shape
    self.mu_shape = mu_shape

basanos.SingularMatrixError

Bases: BasanosError, ValueError

Raised when a matrix is (numerically) singular and cannot be inverted.

This wraps LinAlgError to provide domain-specific context.

Examples:

>>> raise SingularMatrixError()
Traceback (most recent call last):
    ...
basanos.exceptions.SingularMatrixError: Matrix is singular and cannot be solved.
Source code in src/basanos/exceptions.py
class SingularMatrixError(BasanosError, ValueError):
    """Raised when a matrix is (numerically) singular and cannot be inverted.

    This wraps `LinAlgError` to provide domain-specific
    context.

    Examples:
        >>> raise SingularMatrixError()
        Traceback (most recent call last):
            ...
        basanos.exceptions.SingularMatrixError: Matrix is singular and cannot be solved.
    """

    def __init__(self, detail: str = "") -> None:
        """Initialize with an optional extra detail string."""
        msg = "Matrix is singular and cannot be solved."
        if detail:
            msg = f"{msg} {detail}"
        super().__init__(msg)

__init__(detail='')

Initialize with an optional extra detail string.

Source code in src/basanos/exceptions.py
def __init__(self, detail: str = "") -> None:
    """Initialize with an optional extra detail string."""
    msg = "Matrix is singular and cannot be solved."
    if detail:
        msg = f"{msg} {detail}"
    super().__init__(msg)

Model errors

basanos.FactorModelError

Bases: BasanosError, ValueError

Raised when FactorModel arguments fail validation.

Covers shape mismatches between factor loadings, factor covariance, and idiosyncratic variance arrays, non-positive idiosyncratic variances, invalid return matrix dimensionality, and out-of-range factor counts.

Examples:

>>> raise FactorModelError("factor_loadings must be 2-D, got ndim=1.")
Traceback (most recent call last):
    ...
basanos.exceptions.FactorModelError: factor_loadings must be 2-D, got ndim=1.
Source code in src/basanos/exceptions.py
class FactorModelError(BasanosError, ValueError):
    """Raised when `FactorModel` arguments fail validation.

    Covers shape mismatches between factor loadings, factor covariance, and
    idiosyncratic variance arrays, non-positive idiosyncratic variances,
    invalid return matrix dimensionality, and out-of-range factor counts.

    Examples:
        >>> raise FactorModelError("factor_loadings must be 2-D, got ndim=1.")
        Traceback (most recent call last):
            ...
        basanos.exceptions.FactorModelError: factor_loadings must be 2-D, got ndim=1.
    """