fuggers_py.math

Numerical infrastructure used by the pricing and analytics layers.

.. py:module:: fuggers_py.math

Float- and NumPy-oriented numerical utilities for fuggers_py.

The public surface is organized around root finding, interpolation, extrapolation, linear algebra, and lightweight optimization. These helpers use plain float values and numpy arrays, and they treat tolerances and residuals as absolute values unless a specific callable documents a different convention.

.. py:exception:: MathError :module: fuggers_py.math :canonical: fuggers_py.math.errors.MathError

Base exception for all math-layer failures.

.. py:method:: MathError.convergence_failed(iterations, residual) :module: fuggers_py.math :classmethod:

  Construct a convergence failure with iteration count and residual.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.errors.ConvergenceFailed\``

.. py:method:: MathError.invalid_input(reason) :module: fuggers_py.math :classmethod:

  Construct an invalid-input error with the supplied reason.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.errors.InvalidInput\``

.. py:method:: MathError.insufficient_data(required, actual) :module: fuggers_py.math :classmethod:

  Construct an insufficient-data error with the required and actual counts.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.errors.InsufficientData\``

.. py:exception:: ConvergenceFailed(iterations, residual) :module: fuggers_py.math :canonical: fuggers_py.math.errors.ConvergenceFailed

Raised when an iterative algorithm stops before meeting tolerance.

.. attribute:: iterations

  Number of iterations completed before the failure was detected.

.. attribute:: residual

  Absolute residual or objective measure at the last iterate.

.. py:exception:: InvalidBracket(a, b, fa, fb) :module: fuggers_py.math :canonical: fuggers_py.math.errors.InvalidBracket

Raised when a bracketed root solver does not receive a valid bracket.

The bracket is valid only when the endpoint function values have opposite signs or one endpoint is already a root.

.. py:exception:: DivisionByZero(value) :module: fuggers_py.math :canonical: fuggers_py.math.errors.DivisionByZero

Raised when an algorithm divides by a zero or numerically zero pivot.

.. py:exception:: SingularMatrix() :module: fuggers_py.math :canonical: fuggers_py.math.errors.SingularMatrix

Raised when a linear system or factorization is numerically singular.

.. py:exception:: DimensionMismatch(rows1, cols1, rows2, cols2) :module: fuggers_py.math :canonical: fuggers_py.math.errors.DimensionMismatch

Raised when two arrays or matrices have incompatible dimensions.

.. py:exception:: ExtrapolationNotAllowed(x, min, max) :module: fuggers_py.math :canonical: fuggers_py.math.errors.ExtrapolationNotAllowed

Raised when a value is requested outside the supported interpolation range.

.. py:exception:: InsufficientData(required, actual) :module: fuggers_py.math :canonical: fuggers_py.math.errors.InsufficientData

Raised when an algorithm needs more observations than were supplied.

.. py:exception:: InvalidInput(reason) :module: fuggers_py.math :canonical: fuggers_py.math.errors.InvalidInput

Raised when an argument is finite but semantically invalid.

.. py:exception:: MathOverflow(operation) :module: fuggers_py.math :canonical: fuggers_py.math.errors.MathOverflow

Raised when a numerical operation overflows floating-point range.

.. py:exception:: MathUnderflow(operation) :module: fuggers_py.math :canonical: fuggers_py.math.errors.MathUnderflow

Raised when a numerical operation underflows floating-point range.

.. py:class:: SolverConfig(tolerance=1e-10, max_iterations=100) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.types.SolverConfig

Configuration for scalar root-finding algorithms.

.. attribute:: tolerance

  Absolute stopping threshold applied to the scalar residual ``|f(x)|``.

.. attribute:: max_iterations

  Maximum number of iterations allowed before raising convergence failure.

.. py:method:: SolverConfig.with_tolerance(tolerance) :module: fuggers_py.math

  Return a copy with ``tolerance`` replaced.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverConfig\``

.. py:method:: SolverConfig.with_max_iterations(max_iterations) :module: fuggers_py.math

  Return a copy with ``max_iterations`` replaced.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverConfig\``

.. py:class:: SolverResult(root, iterations, residual, converged) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.types.SolverResult

Result returned by scalar root-finding algorithms.

.. attribute:: root

  Best root estimate.

.. attribute:: iterations

  Number of iterations completed.

.. attribute:: residual

  Absolute residual ``|f(root)|`` at the returned point.

.. attribute:: converged

  Whether the solver met its stopping criteria.

.. py:attribute:: MathResult :module: fuggers_py.math

alias of :py:class:~fuggers_py.math.solvers.types.SolverResult

.. py:class:: RootFinder(*args, **kwargs) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.types.RootFinder

Protocol for objects exposing a scalar root-finding entry point.

Implementations should return a :class:SolverResult and follow the same absolute-residual convention as the free functions in this package.

.. py:attribute:: Solver :module: fuggers_py.math

alias of :py:class:~fuggers_py.math.solvers.types.RootFinder

.. py:class:: BisectionSolver(*, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.bisection.BisectionSolver

Callable wrapper around :func:bisection with a stored configuration.

.. py:method:: BisectionSolver.find_root(f, a, b) :module: fuggers_py.math

  Dispatch to :func:`bisection` using the stored configuration.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverResult\``

.. py:class:: BrentSolver(*, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.brent.BrentSolver

Callable wrapper around :func:brent with a stored configuration.

.. py:method:: BrentSolver.find_root(f, a, b) :module: fuggers_py.math

  Dispatch to :func:`brent` using the stored configuration.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverResult\``

.. py:class:: HybridSolver(*, config=SolverConfig(tolerance=1e-10, max_iterations=100), df=None, h=1e-06) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.hybrid.HybridSolver

Callable wrapper around the safeguarded Newton root solvers.

.. py:method:: HybridSolver.find_root(f, a, b, x0) :module: fuggers_py.math

  Dispatch to :func:`hybrid` or :func:`hybrid_numerical`.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverResult\``

.. py:class:: NewtonSolver(*, config=SolverConfig(tolerance=1e-10, max_iterations=100), df=None, h=1e-06) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.newton.NewtonSolver

Callable wrapper around the Newton solvers with an optional derivative.

.. py:method:: NewtonSolver.find_root(f, x0) :module: fuggers_py.math

  Dispatch to the analytic or numerical Newton solver.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverResult\``

.. py:class:: SecantSolver(*, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math :canonical: fuggers_py.math.solvers.secant.SecantSolver

Callable wrapper around :func:secant with a stored configuration.

.. py:method:: SecantSolver.find_root(f, x0, x1) :module: fuggers_py.math

  Dispatch to :func:`secant` using the stored configuration.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.solvers.types.SolverResult\``

.. py:function:: bisection(f, a, b, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math

Find a scalar root with the bisection method.

The method requires a sign-changing bracket and repeatedly halves the interval until either the residual or the interval width falls below config.tolerance.

:type f: :sphinx_autodoc_typehints_type:\:py\:class\:\~collections.abc.Callable`\ \[\[:py:class:`float`], :py:class:`float`]    :param f: Scalar function whose root is sought.    :type a: :sphinx_autodoc_typehints_type::py:class:`float`    :param a: Bracketing endpoints. They must be finite, distinct, and either bracket              a sign change or hit a root exactly.    :type b: :sphinx_autodoc_typehints_type::py:class:`float`    :param b: Bracketing endpoints. They must be finite, distinct, and either bracket              a sign change or hit a root exactly.    :type config: :sphinx_autodoc_typehints_type::py:class:`~fuggers_py.math.solvers.types.SolverConfig`` :param config: Iteration cap and absolute residual tolerance.

:returns: Root estimate, iteration count, residual |f(root)|, and convergence flag. :rtype: SolverResult

:raises InvalidBracket: If f(a) and f(b) do not have opposite signs. :raises ConvergenceFailed: If the tolerance is not met within config.max_iterations.

.. py:function:: brent(f, a, b, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math

Find a scalar root with Brent’s bracketed hybrid method.

The implementation combines inverse quadratic interpolation, secant steps, and bisection fallback. The returned residual is the absolute function value at the final iterate. A sign-changing bracket is required.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:function:: secant(f, x0, x1, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math

Find a scalar root with the secant method.

The solver uses two starting points and updates the pair by the standard secant recurrence. The residual in the result is the absolute function value at the final iterate. A bracket is not required, but the method can fail if consecutive function values become equal.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:function:: newton_raphson(f, df, x0, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math

Find a scalar root with Newton-Raphson iteration.

The method applies the analytic derivative at each iterate and stops when |f(x)| is within config.tolerance. It requires a non-zero derivative at every evaluated iterate.

:type f: :sphinx_autodoc_typehints_type:\:py\:class\:\~collections.abc.Callable`\ \[\[:py:class:`float`], :py:class:`float`]    :param f: Scalar function whose root is sought.    :type df: :sphinx_autodoc_typehints_type::py:class:`~collections.abc.Callable`\ \[\[:py:class:`float`], :py:class:`float`]    :param df: Analytic derivative of ``f``.    :type x0: :sphinx_autodoc_typehints_type::py:class:`float`    :param x0: Initial guess.    :type config: :sphinx_autodoc_typehints_type::py:class:`~fuggers_py.math.solvers.types.SolverConfig`` :param config: Absolute residual tolerance and iteration cap.

:raises DivisionByZero: If the derivative evaluates to zero at an iterate. :raises ConvergenceFailed: If the solver exhausts the iteration budget before meeting tolerance.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:function:: newton_raphson_numerical(f, x0, config=SolverConfig(tolerance=1e-10, max_iterations=100), *, h=1e-06) :module: fuggers_py.math

Find a scalar root with Newton-Raphson using finite-difference slopes.

The derivative is approximated with a central finite difference using the supplied step size h.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:function:: hybrid(f, df, a, b, x0, config=SolverConfig(tolerance=1e-10, max_iterations=100)) :module: fuggers_py.math

Find a scalar root with safeguarded Newton iteration inside a bracket.

The method keeps a valid sign-changing bracket and falls back to bisection whenever a Newton step would leave the bracket. The residual is the absolute scalar function value at the returned iterate. A valid bracket is required, and the starting guess is projected into the bracket when needed.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:function:: hybrid_numerical(f, a, b, x0, config=SolverConfig(tolerance=1e-10, max_iterations=100), *, h=1e-06) :module: fuggers_py.math

Find a scalar root with safeguarded Newton iteration and numerical slopes.

The derivative is approximated with a central finite difference using the supplied step size h.

:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~fuggers_py.math.solvers.types.SolverResult``

.. py:class:: Interpolator(*args, **kwargs) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.base.Interpolator

Protocol for one-dimensional interpolators.

Implementations are expected to accept finite scalar x values and return scalar interpolated values and derivatives. allows_extrapolation reports whether points outside the native knot range are accepted. The axis is assumed to be ordered and finite.

.. py:class:: LinearInterpolator(xs, ys, allow_extrapolation=False) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.linear.LinearInterpolator

Piecewise-linear interpolator for finite 1D data.

The interpolator requires strictly increasing xs and finite ys. By default it refuses extrapolation outside the knot range; use :meth:with_extrapolation to opt in to endpoint extrapolation.

.. py:method:: LinearInterpolator.new(xs, ys) :module: fuggers_py.math :classmethod:

  Construct a linear interpolator from knot and value arrays.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.linear.LinearInterpolator\``

.. py:method:: LinearInterpolator.with_extrapolation() :module: fuggers_py.math

  Return a copy that allows evaluation outside the knot range.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.linear.LinearInterpolator\``

.. py:method:: LinearInterpolator.interpolate(x) :module: fuggers_py.math

  Interpolate the value at ``x`` with piecewise linear segments.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: LinearInterpolator.derivative(x) :module: fuggers_py.math

  Return the slope of the active linear segment at ``x``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: LogLinearInterpolator(xs, ys, allow_extrapolation=False) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.log_linear.LogLinearInterpolator

Interpolate y values in log space to preserve positivity.

The inputs must be strictly increasing in x and strictly positive in y. Extrapolation is opt-in and follows the same log-linear rule.

.. py:method:: LogLinearInterpolator.new(xs, ys) :module: fuggers_py.math :classmethod:

  Construct a log-linear interpolator from knot and value arrays.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.log\_linear.LogLinearInterpolator\``

.. py:method:: LogLinearInterpolator.with_extrapolation() :module: fuggers_py.math

  Return a copy that allows evaluation outside the knot range.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.log\_linear.LogLinearInterpolator\``

.. py:method:: LogLinearInterpolator.y_values() :module: fuggers_py.math

  Return a copy of the original positive values.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: LogLinearInterpolator.interpolate(x) :module: fuggers_py.math

  Interpolate the value at ``x`` by linearly interpolating ``log(y)``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: LogLinearInterpolator.derivative(x) :module: fuggers_py.math

  Return the derivative implied by the log-linear interpolant.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: CubicSpline(xs, ys, allow_extrapolation=False) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.cubic_spline.CubicSpline

Natural cubic spline interpolator with zero second derivatives at endpoints.

.. py:method:: CubicSpline.new(xs, ys) :module: fuggers_py.math :classmethod:

  Construct a natural cubic spline from knot and value arrays.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.cubic\_spline.CubicSpline\``

.. py:method:: CubicSpline.with_extrapolation() :module: fuggers_py.math

  Return a copy that allows evaluation outside the knot range.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.cubic\_spline.CubicSpline\``

.. py:method:: CubicSpline.interpolate(x) :module: fuggers_py.math

  Evaluate the spline at ``x``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: CubicSpline.derivative(x) :module: fuggers_py.math

  Evaluate the first derivative of the spline at ``x``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: FlatForward(tenors, zero_rates, allow_extrapolation=False) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.flat_forward.FlatForward

Interpolate zero rates while keeping forward rates constant by segment.

The input curve is interpreted as zero rates at strictly increasing positive tenors. Between pillars the implied instantaneous forward rate is held constant; extrapolation beyond the last tenor reuses the last forward rate when enabled.

.. py:method:: FlatForward.new(tenors, zero_rates) :module: fuggers_py.math :classmethod:

  Construct a flat-forward interpolator from tenors and zero rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.flat\_forward.FlatForward\``

.. py:method:: FlatForward.with_extrapolation() :module: fuggers_py.math

  Return a copy that allows evaluation outside the tenor range.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.flat\_forward.FlatForward\``

.. py:method:: FlatForward.tenors() :module: fuggers_py.math

  Return a copy of the tenor grid.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: FlatForward.zero_rates() :module: fuggers_py.math

  Return a copy of the input zero rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: FlatForward.forward_rates_vec() :module: fuggers_py.math

  Return the cached piecewise-constant forward rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: FlatForward.forward_rate(t) :module: fuggers_py.math

  Return the instantaneous forward rate implied at tenor ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: FlatForward.interpolate(t) :module: fuggers_py.math

  Return the zero rate implied at tenor ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: FlatForward.derivative(t) :module: fuggers_py.math

  Return the derivative of the zero-rate curve at tenor ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: MonotoneConvex(times, zero_rates, allow_extrapolation=False) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.monotone_convex.MonotoneConvex

Hagan-West-inspired monotone-convex interpolation of zero rates.

The implementation expects strictly increasing positive times and finite zero rates. It preserves non-negative discrete forwards and allows optional extrapolation beyond the last pillar.

.. py:method:: MonotoneConvex.new(times, zero_rates) :module: fuggers_py.math :classmethod:

  Construct a monotone-convex interpolator from times and zero rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.monotone\_convex.MonotoneConvex\``

.. py:method:: MonotoneConvex.with_extrapolation() :module: fuggers_py.math

  Return a copy that allows evaluation outside the time range.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.monotone\_convex.MonotoneConvex\``

.. py:method:: MonotoneConvex.times() :module: fuggers_py.math

  Return a copy of the knot times.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: MonotoneConvex.zero_rates() :module: fuggers_py.math

  Return a copy of the input zero rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: MonotoneConvex.discrete_forwards() :module: fuggers_py.math

  Return the cached discrete forward rates.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~numpy.ndarray\`\\ \\\[\:py\:class\:\`tuple\`\\ \\\[\:py\:data\:\`\~typing.Any\`\, \:py\:data\:\`...\<Ellipsis\>\`\]\, \:py\:class\:\`\~numpy.dtype\`\\ \\\[\:py\:class\:\`\~numpy.float64\`\]\]`

.. py:method:: MonotoneConvex.forward_rate(t) :module: fuggers_py.math

  Return the instantaneous forward rate implied at time ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: MonotoneConvex.interpolate(t) :module: fuggers_py.math

  Return the zero rate implied at time ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: MonotoneConvex.derivative(t) :module: fuggers_py.math

  Return a finite-difference derivative of the interpolated zero curve.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: NelsonSiegel(beta0, beta1, beta2, tau, _allow_extrapolation=True) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.parametric.NelsonSiegel

Nelson-Siegel zero-rate parameterization.

.. attribute:: beta0, beta1, beta2

  Level, slope, and curvature factors.

.. attribute:: tau

  Positive decay parameter controlling the curve shape.

.. py:method:: NelsonSiegel.new(beta0, beta1, beta2, tau) :module: fuggers_py.math :classmethod:

  Construct a Nelson-Siegel curve from factor loadings and decay.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.parametric.NelsonSiegel\``

.. py:method:: NelsonSiegel.interpolate(t) :module: fuggers_py.math

  Evaluate the zero-rate curve at tenor ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: NelsonSiegel.derivative(t) :module: fuggers_py.math

  Evaluate the first derivative of the Nelson-Siegel curve.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: Svensson(beta0, beta1, beta2, beta3, tau1, tau2, _allow_extrapolation=True) :module: fuggers_py.math :canonical: fuggers_py.math.interpolation.parametric.Svensson

Svensson zero-rate parameterization with two curvature terms.

.. py:method:: Svensson.new(beta0, beta1, beta2, beta3, tau1, tau2) :module: fuggers_py.math :classmethod:

  Construct a Svensson curve from factor loadings and decay values.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~fuggers\_py.math.interpolation.parametric.Svensson\``

.. py:method:: Svensson.interpolate(t) :module: fuggers_py.math

  Evaluate the zero-rate curve at tenor ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: Svensson.derivative(t) :module: fuggers_py.math

  Evaluate the first derivative of the Svensson curve.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: Extrapolator(*args, **kwargs) :module: fuggers_py.math :canonical: fuggers_py.math.extrapolation.base.Extrapolator

Protocol for one-dimensional extrapolators.

Implementations should accept a scalar query point and return the extrapolated value together with the implied first derivative.

.. py:class:: ExtrapolationMethod(value) :module: fuggers_py.math :canonical: fuggers_py.math.extrapolation.base.ExtrapolationMethod

Supported extrapolation schemes for curve construction.

.. py:class:: FlatExtrapolator(level) :module: fuggers_py.math :canonical: fuggers_py.math.extrapolation.flat.FlatExtrapolator

Return a constant level outside the interpolation range.

This is the simplest extrapolation scheme: the value is held constant and the derivative is zero.

.. py:method:: FlatExtrapolator.extrapolate(x) :module: fuggers_py.math

  Return the stored constant level.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: FlatExtrapolator.derivative(x) :module: fuggers_py.math

  Return the zero derivative implied by constant extrapolation.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: LinearExtrapolator(x0, y0, slope) :module: fuggers_py.math :canonical: fuggers_py.math.extrapolation.linear.LinearExtrapolator

Extend a straight line defined by (x0, y0) and slope.

The value is extended with the same slope beyond the observed range, so the derivative is constant everywhere.

.. py:method:: LinearExtrapolator.extrapolate(x) :module: fuggers_py.math

  Evaluate the extrapolated line at ``x``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: LinearExtrapolator.derivative(x) :module: fuggers_py.math

  Return the constant line slope.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: SmithWilson(maturities, discount_factors, *, ufr, alpha) :module: fuggers_py.math :canonical: fuggers_py.math.extrapolation.smith_wilson.SmithWilson

Smith-Wilson discount-factor extrapolator.

The constructor fits the Wilson weights that reproduce the supplied market discount factors and force the long end to converge toward the specified ultimate forward rate (UFR).

.. py:method:: SmithWilson.discount_factor(t) :module: fuggers_py.math

  Return the extrapolated discount factor at time ``t``.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: SmithWilson.extrapolate(x) :module: fuggers_py.math

  Alias for :meth:`discount_factor`.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:method:: SmithWilson.derivative(x) :module: fuggers_py.math

  Return a finite-difference derivative of the discount-factor curve.


  :rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`float\``

.. py:class:: OptimizationConfig(tolerance=1e-10, max_iterations=100, step_size=1e-08, armijo_c=0.5, backtracking_beta=0.5, min_step=1e-15, lm_initial_damping=0.001, lm_damping_increase=10.0, lm_damping_decrease=0.1) :module: fuggers_py.math :canonical: fuggers_py.math.optimization.types.OptimizationConfig

Configuration for gradient-based and least-squares optimization.

.. attribute:: tolerance

  Absolute stopping threshold used for gradient norms, objective changes,
  or similar residual measures.

.. attribute:: max_iterations

  Maximum number of outer iterations.

.. attribute:: step_size

  Finite-difference step used when approximating derivatives.

.. attribute:: armijo_c

  Armijo sufficient-decrease constant for backtracking line search.

.. attribute:: backtracking_beta

  Multiplicative factor applied to the step length during backtracking.

.. attribute:: min_step

  Smallest step length accepted by backtracking before declaring failure.

.. attribute:: lm_initial_damping

  Initial Levenberg-Marquardt damping factor.

.. attribute:: lm_damping_increase

  Multiplicative increase applied when a LM trial step is rejected.

.. attribute:: lm_damping_decrease

  Multiplicative decrease applied when a LM trial step is accepted.

.. py:class:: OptimizationResult(parameters, objective_value, iterations, converged) :module: fuggers_py.math :canonical: fuggers_py.math.optimization.types.OptimizationResult

Result returned by the optimization routines.

.. attribute:: parameters

  Best parameter vector found.

.. attribute:: objective_value

  Objective value at ``parameters``.

.. attribute:: iterations

  Number of outer iterations completed.

.. attribute:: converged

  Whether the stopping criteria were satisfied before the iteration cap.

.. py:function:: gradient_descent(objective, gradient, initial_params, config=OptimizationConfig(tolerance=1e-10, max_iterations=100, step_size=1e-08, armijo_c=0.5, backtracking_beta=0.5, min_step=1e-15, lm_initial_damping=0.001, lm_damping_increase=10.0, lm_damping_decrease=0.1)) :module: fuggers_py.math

Minimize a scalar objective with gradient descent.

The routine uses a steepest-descent step direction and Armijo backtracking to keep each accepted update monotone in the objective value. It stops when the gradient norm falls below config.tolerance, or when backtracking can no longer find an acceptable step.

:type objective: :sphinx_autodoc_typehints_type:\:py\:class\:\~collections.abc.Callable`\ \[\[:py:class:`~numpy.ndarray`\ \[:py:class:`tuple`\ \[:py:data:`~typing.Any`, :py:data:`…<Ellipsis>`], :py:class:`~numpy.dtype`\ \[:py:class:`~numpy.float64`]]], :py:class:`float`]    :param objective: Scalar objective function of the parameter vector.    :type gradient: :sphinx_autodoc_typehints_type::py:class:`~collections.abc.Callable`\ \[\[:py:class:`~numpy.ndarray`\ \[:py:class:`tuple`\ \[:py:data:`~typing.Any`, :py:data:`…<Ellipsis>`], :py:class:`~numpy.dtype`\ \[:py:class:`~numpy.float64`]]], :py:class:`~numpy.ndarray`\ \[:py:class:`tuple`\ \[:py:data:`~typing.Any`, :py:data:`…<Ellipsis>`], :py:class:`~numpy.dtype`\ \[:py:class:`~numpy.float64`]]]    :param gradient: Gradient of ``objective`` with the same shape as the parameters.    :type initial_params: :sphinx_autodoc_typehints_type::py:data:`~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]    :param initial_params: One-dimensional starting point.    :type config: :sphinx_autodoc_typehints_type::py:class:`~fuggers_py.math.optimization.types.OptimizationConfig`` :param config: Absolute tolerance, iteration cap, and backtracking parameters.

:returns: Best parameter vector found, objective value at that point, iteration count, and convergence flag. If backtracking fails, the result is returned with converged=False instead of raising. :rtype: OptimizationResult

:raises InvalidInput: If the parameters are not one-dimensional or the configuration values are not positive where required.

.. py:function:: gauss_newton(residuals_fn, x0, config=OptimizationConfig(tolerance=1e-10, max_iterations=100, step_size=1e-08, armijo_c=0.5, backtracking_beta=0.5, min_step=1e-15, lm_initial_damping=0.001, lm_damping_increase=10.0, lm_damping_decrease=0.1)) :module: fuggers_py.math

Solve a nonlinear least-squares problem with Gauss-Newton iteration.

The objective optimized is one half of the squared 2-norm of the residual vector. Residuals and Jacobians are evaluated on 1D parameter vectors. The solver uses the normal equations and falls back to finite-difference Jacobians when no analytic Jacobian is provided.

:returns: Best parameter vector, objective value, iteration count, and convergence flag. If the iteration budget is exhausted, the final state is returned with converged=False. :rtype: OptimizationResult

:raises InvalidInput: If the parameter vector is not one-dimensional or the configuration contains invalid values.

.. py:function:: levenberg_marquardt(residuals_fn, x0, config=OptimizationConfig(tolerance=1e-10, max_iterations=100, step_size=1e-08, armijo_c=0.5, backtracking_beta=0.5, min_step=1e-15, lm_initial_damping=0.001, lm_damping_increase=10.0, lm_damping_decrease=0.1)) :module: fuggers_py.math

Solve a nonlinear least-squares problem with a damped Gauss-Newton step.

The damping parameter is adapted multiplicatively: rejected steps increase damping, while accepted steps reduce it. Residuals and Jacobians are evaluated on 1D parameter vectors. This variant is more forgiving than plain Gauss-Newton on poorly scaled problems because the diagonal damping term keeps the linear solve well conditioned.

:returns: Best parameter vector, objective value, iteration count, and convergence flag. If the iteration budget is exhausted, the final state is returned with converged=False. :rtype: OptimizationResult

:raises InvalidInput: If the parameter vector is not one-dimensional or any damping-related configuration value is invalid.

.. py:function:: lu_decomposition(a) :module: fuggers_py.math

Compute the LU decomposition with partial pivoting.

:type a: :sphinx_autodoc_typehints_type:\:py\:data\:\~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]` :param a: Square matrix to factorize.

:returns: (P, L, U) such that P @ A = L @ U where P is a permutation matrix, L is unit lower triangular, and U is upper triangular. :rtype: tuple of numpy.ndarray

:raises InvalidInput: If a is not a finite square matrix. :raises SingularMatrix: If the pivot tolerance indicates that the matrix is numerically singular.

.. py:function:: solve_linear_system(a, b) :module: fuggers_py.math

Solve A x = b using LU decomposition with partial pivoting.

:type a: :sphinx_autodoc_typehints_type:\:py\:data\:\~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]    :param a: Square coefficient matrix.    :type b: :sphinx_autodoc_typehints_type::py:data:`~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]` :param b: Right-hand-side vector.

:returns: Solution vector x. :rtype: numpy.ndarray

:raises DimensionMismatch: If b does not have the same length as a has rows. :raises InvalidInput: If the inputs are not finite or have incompatible shapes. :raises SingularMatrix: If the matrix is singular or numerically singular.

.. py:function:: solve_tridiagonal(lower, diag, upper, rhs) :module: fuggers_py.math

Solve a tridiagonal linear system with the Thomas algorithm.

:type lower: :sphinx_autodoc_typehints_type:\:py\:data\:\~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]    :param lower: Sub-diagonal entries with length ``n - 1``.    :type diag: :sphinx_autodoc_typehints_type::py:data:`~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]    :param diag: Main diagonal entries with length ``n``.    :type upper: :sphinx_autodoc_typehints_type::py:data:`~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]    :param upper: Super-diagonal entries with length ``n - 1``.    :type rhs: :sphinx_autodoc_typehints_type::py:data:`~typing.Union`\ \[:py:class:`~numpy._typing._array_like._Buffer`, :py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]], :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`~numpy._typing._array_like._SupportsArray`\ \[:py:class:`~numpy.dtype`\ \[:py:data:`~typing.Any`]]], :py:class:`complex`, :py:class:`bytes`, :py:class:`str`, :py:class:`~numpy._typing._nested_sequence._NestedSequence`\ \[:py:class:`complex` | :py:class:`bytes` | :py:class:`str`]]` :param rhs: Right-hand-side vector with length n.

:returns: Solution vector. :rtype: numpy.ndarray

:raises DivisionByZero: If a pivot is zero or numerically zero during elimination or back substitution. :raises InvalidInput: If the arrays are not finite, not one-dimensional, or have mismatched lengths.