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.