API Documentation

Curve

class curves.Curve(curve=None, /, *, id='', _op=None, _other=None)[source]

Bases: object

Curve object with algebraic operations

Parameters:
  • curve – inner curve or curve value or curve variable

  • id – id of curve (optional), if given, id must be unique for all curve instances

This turns any function (aka curve) into an algebraic object which can handle operators +, -, * , / and @.

>>> from curves import Curve
>>> eye = Curve()  # identity function
>>> eye(123.456)
123.456
>>> zero = Curve(0.0)  # constant function
>>> zero(123.456)
0.0
>>> one = Curve(1.0)
>>> one(123.456)
1.0
>>> X = Curve('X') # variable
>>> X
X
>>> p = 2 * X ** 2 + 3 * X + 1
>>> p
2 * X ** 2 + 3 * X + 1
>>> p(123.456)
30854.135872
>>> q = p(X - 1)
>>> q
(2 * X ** 2 + 3 * X + 1)(X - 1)
>>> q1 = p @ (X - 1)
>>> q1
(2 * X ** 2 + 3 * X + 1)(X - 1)
>>> q2 = 2 * (X - 1) ** 2 + 3 * (X - 1) + 1
>>> q2
2 * (X - 1) ** 2 + 3 * (X - 1) + 1
>>> q(123.456)
30359.311872
>>> q1(123.456)
30359.311872
>>> q2(123.456)
30359.311872

and for constant curves

>>> int(Curve(1))
1
>>> float(Curve(1))
1.0
>>> int(Curve(1.7))
1
>>> float(Curve(1.7))
1.7

Using identifier argument id

>>> y = Curve(1., id='γ')
>>> str(y)
'γ'

but

>>> repr(y)
'1.0'

Any identifier must be unique for all curve instances

>>> Curve(2., id='γ')
Traceback (most recent call last):
...
ValueError: Curve(γ) already defined
logger()

logging function to enable logging of elementary instance operations for instances with an id attribute

>>> from curves import Curve
>>> Curve.logger = print
>>> c = Curve(99, id='MyCurve')
Curve(99, id='MyCurve')
>>> _ = c(0)
99 = MyCurve(0)
>>> c.curve = 100
MyCurve = 100
>>> _ = float(c)
100.0 = float(MyCurve)
>>> c += 4
MyCurve += 4

for more examples see Tutorial

curves.init(curve, /, *, id='')[source]

initialize Curve instance

Parameters:

curve – item to initialize, i.e. turn into a curves.curves.Curve instance if curve isn’t already one.

Returns:

curves.curves.Curve instance

>>> from curves import init

for functions

>>> from math import exp
>>> f = init(exp)
>>> f
exp
>>> type(f)
<class 'curves.curves.Curve'>
>>> f == exp
False
>>> f is init(f)
True

for numbers

>>> n = init(1.23)
>>> n
1.23
>>> type(n)
<class 'curves.curves.Curve'>
>>> n == 1.23
False
>>> n is init(n)
True

for more examples see Tutorial

Plotting Curves

curves.lin(start: int | float | slice | list | tuple = 1.0, stop: int | float | None = None, step: int | float | None = None, num: int = 1000)[source]

generate grid of values

Parameters:
  • start – (float, slice, list or tuple) first grid point (included)

  • stop – (float) last grid point (excluded)

  • step – (float) step size between points (optional)

  • num – (int) number of grid points if step is None (optional: default is 1_000)

Returns:

list of grid points as float

stop and step are ignored if start is slice or tuple since their values are taken from start entries.

>>> from curves import lin
>>> lin(1.0, step=0.25)
[0.0, 0.25, 0.5, 0.75]
>>> lin(1.1, step=0.25)
[0.0, 0.25, 0.5, 0.75, 1.0]
>>> lin(0.25, 1.0, step=0.5)
[0.25, 0.75]
>>> lin([0.25, 1.0, 0.5])
[0.25, 0.75]
>>> lin(slice(0.25, 1.0, 0.5))
[0.25, 0.75]
>>> lin(0.25, 1.0, num=3)
[0.25, 0.5, 0.75]
curves.plot(x, *curve, legend=True, kind='plot', params=None, xlim=(), ylim=(), aspect=False, ax=None, figsize=None, show=True, **curves)[source]

plot curves with ‘matplotlib’

Parameters:
  • x – (int, float, list, tuple or slice) if x is either int, float or slice curves.lin() is invoked to generate x values.

  • curve – (callable) function to be plotted with labels given by str representation

  • legend – (bool) if True the legend is shown (optional: default is True)

  • kind – (str) kind of plot type, e.g. ‘dots’, ‘bars’ (optional: default is ‘plot’)

  • params – (dict) additional parameters to define curve display style (optional: no default)

  • xlim – (tuple[float, float]) (optional: no default)

  • ylim – (tuple[float, float]) (optional: no default)

  • aspect – (float) defines box aspect ratio (optional: default is None)

  • ax – (ax or None) (optional: default is current ax)

  • figsize – (tuple[float, float] or None) if given, a figure with given figsize is created. (optional: no default)

  • show – (bool) (optional: default is True)

  • curves – (callable) function to be plotted with labels given by key values

Returns:

ax

>>> from math import sqrt, pi
>>> from curves import X, plot, lin
>>> from curves.functions import sin, cos, exp

set x values

>>> x = lin(-5, 5, num=500)  # x values from -1 to 1

define the function

>>> std_norm_pdf = 1 / sqrt(2 * pi) * exp(-(X ** 2) / 2)

and plot it

>>> plot(x, phi=std_norm_pdf)

as simple as

>>> plot(x, sin, -sin, cos, -cos)

for more examples see Tutorial

curves.plotter(*curve, legend=None, kind=None, params=None, xlim=(), ylim=(), aspect=None, **curves)

plotter instance

for more examples see Tutorial

Predefined Curves

The functions subpackage provides standard function as predefined in standard package math. For instance

curves.functions.exp(x)
curves.functions.log(x)
curves.functions.sin(x)
curves.functions.cos(x)
curves.functions.tan(x)
curves.functions.gamma(x)

for more examples see Tutorial

and more may … (actually any function in math that may be invoked with a float value).

Mathematical constants like pi or e define constant functions.

curves.functions.e(x)
curves.functions.pi(x)

In addition, there is the ramp function and step function, too.

curves.functions.ramp(x)
curves.functions.step(x)

for more examples see Tutorial

Numerical Operators

class curves.operators.Integral(curve, a=0)[source]

Bases: object

integral of function

Parameters:
  • curve – (callable) function \(f\) to integrate

  • a – (float) lower bound \(a\) of integral

calculates the integral

\[F_a(x) = \int_a^x f(s) ds\]

for more examples see Tutorial

class curves.operators.Derivative(curve, h=1e-07)[source]

Bases: object

frist derivative of a function

Parameters:
  • curve – (callable) function \(f\) to differentiate

  • h – (float) step size \(\eta\) for finte differences (optional)

calculates the (first) derivative via finite differences

\[\frac{\partial f}{\partial x} =f'(x)\approx\frac{f(x+\eta)-f(x)}{\eta}\]

for more examples see Tutorial

Numerical Operations

curves.numerics.finite_difference(f, x, h=1e-07)[source]

Numerically differentiate the function f at point x using the finite difference method.

Parameters:
  • f – (function) The function to differentiate.

  • x – (float) The point at which to differentiate the function.

  • h – (float, optional) The step size to use. Default is 1e-7.

Returns:

float: The numerical derivative of f at point x.

curves.numerics.trapezoidal_rule(f, a, b, n)[source]

Numerically integrate the function f from a to b using the trapezoidal rule with n intervals.

Parameters:
  • f – (function) The function to integrate.

  • a – (float) The start point of the interval.

  • b – (float) The end point of the interval.

  • n – (int) The number of intervals to divide [a, b] into.

Returns:

float: The numerical integral of f from a to b.

curves.numerics.quadrature(f, a, b)[source]

Numerically integrate the function f from a to b using the quadrature rule.

Parameters:
  • f – (function) The function to integrate.

  • a – (float) The start point of the interval.

  • b – (float) The end point of the interval.

Returns:

float: The numerical integral of f from a to b.

curves.numerics.integrate(f, a, b)

Numerically integrate the function f from a to b using the quadrature rule.

Parameters:
  • f – (function) The function to integrate.

  • a – (float) The start point of the interval.

  • b – (float) The end point of the interval.

Returns:

float: The numerical integral of f from a to b.

curves.numerics.newton_raphson(f, a, tol=1e-08, max_iter=1000)[source]

Newton-Raphson method to find the root of a function.

Parameters:
  • f – (callable) function

  • a – (float) Initial guess

  • tol – (float) Tolerance for convergence

  • max_iter – (int) Maximum number of iterations

Returns:

float : The root of the function

curves.numerics.bisection_method(f, a, b, tol=1e-08, max_iter=1000)[source]

Bisection method to find the root of a function.

Parameters:
  • f – (callable) function

  • a – (float) Left endpoint of the initial interval

  • b – (float) Right endpoint of the initial interval

  • tol – (float) Tolerance for convergence

  • max_iter – (int) Maximum number of iterations

Returns:

float : The root of the function

curves.numerics.secant_method(f, a, b, tol=1e-08, max_iter=1000)[source]

Secant method to find the root of a function.

Parameters:
  • f – (callable) function

  • a – (float) First initial guess

  • b – (float) Second initial guess

  • tol – (float) Tolerance for convergence

  • max_iter – (int) Maximum number of iterations

Returns:

float : The root of the function

curves.numerics.solve(f, method='secant_method', *args, **kwargs)[source]

solver providing function

Parameters:
  • f – (callable) function

  • method – (str or callable) solver method

  • argsmethod arguments

  • kwargsmethod keyword arguments

Returns:

Interpolations

curves.interpolation.fit(curve, grid, err_func, target_list=None, interpolation_type=None, method='secant_method', *args, **kwargs)[source]

fit according to calibration routine to target values

>>> from functools import partial
>>> from math import exp
>>> from curves import Curve, fit
>>> yc = Curve(0.0)
>>> grid = 1, 2, 3, 4
>>> err_func = [partial(yc / 2, t) for t in grid]
>>> # equivalent to err_func = yc / 2 (see below)
>>> fit(yc, grid, err_func, target_list=grid)
{1.0: 1.99..., 2.0: 3.99..., 3.0: 6.00..., 4.0: 8.00...}
>>> fit(yc, grid, yc / 2, target_list=grid)
{1.0: 1.99..., 2.0: 3.99..., 3.0: 6.00..., 4.0: 8.00...}
class curves.interpolation.plist(iterable=(), /)[source]

Bases: list

pretty print list

class curves.interpolation.base_interpolation(x_list=(), y_list=())[source]

Bases: UserDict

interpolation class

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

property x_list
property y_list
class curves.interpolation.flat(y=0.0)[source]

Bases: base_interpolation

flat or constant interpolation

Parameters:

y – constant return float \(\hat{y}\)

A curves.interpolation.flat object is a function \(f\) returning a constant float \(\hat{y}\).

\[f(x)=\hat{y}\text{ const.}\]
for all \(x\).

>>> from curves.interpolation import flat
>>> c = flat(1.1)
>>> c(0)
1.1
>>> c(2.1)
1.1
class curves.interpolation.identity(x_list=(), y_list=())[source]

Bases: base_interpolation

interpolation class

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

class curves.interpolation.no(x_list=(), y_list=())[source]

Bases: _default_value_interpolation

no interpolation at all

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.no object is a function \(f\) returning at \(x\) the float \(y_i\) with \(i\) to be the first matching index such that \(x=x_i\)

\[f(x)=y_i\text{ for } x=x_i \text{ else None}\]

>>> from curves.interpolation import no
>>> # c = no([1,2,3,1], [1,2,3,4])
>>> c = no([1,2,3], [1,2,3])
>>> c(1)
1.0
>>> c(2)
2.0
>>> c(4)
class curves.interpolation.zero(x_list=(), y_list=())[source]

Bases: _default_value_interpolation

interpolation by filling with zeros between points

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.zero object is a function \(f\) returning at \(x\) the float \(y_i\) if \(x=x_i\) else zero. with \(i\) to be the first matching index such that

\[f(x)=y_i\text{ for } x=x_i \text{ else } 0\]

>>> from curves.interpolation import zero
>>> # c = zero([1,2,3,1], [1,2,3,4])
>>> c = zero([1,2,3], [1,2,3])
>>> c(1)
1.0
>>> c(1.1)
0.0
>>> c(2)
2.0
>>> c(4)
0.0
class curves.interpolation.left(x_list=(), y_list=())[source]

Bases: base_interpolation

left interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.left object is a function \(f\) returning at \(x\) the last given float \(y_i\) reading from left to right, i.e. with \(i\) to be the matching index such that

\[f(x)=y_i\text{ for } x_i \leq x < x_{i+1}\]
or \(y_1\) if \(x<x_1\).

>>> from curves.interpolation import left
>>> c = left([1,3], [1,2])
>>> c(0)
1.0
>>> c(1)
1.0
>>> c(2)
1.0
>>> c(4)
2.0
class curves.interpolation.constant(x_list=(), y_list=())[source]

Bases: left

constant interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

Same as curves.interpolation.left.

class curves.interpolation.right(x_list=(), y_list=())[source]

Bases: base_interpolation

right interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.right object is a function \(f\) returning at \(x\) the last given float \(y_i\) reading from right to left, i.e. with \(i\) to be the matching index such that

\[f(x)=y_i\text{ for } x_i < x \leq x_{i+1}\]
or \(y_n\) if \(x_n < x\).

>>> from curves.interpolation import right
>>> c = right([1,3], [1,2])
>>> c(0)
1.0
>>> c(1)
1.0
>>> c(2)
2.0
>>> c(4)
2.0
class curves.interpolation.nearest(x_list=(), y_list=())[source]

Bases: base_interpolation

nearest interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.nearest object is a function \(f\) returning at \(x\) the given float \(y_i\) of the nearest \(x_i\) from both left and right, i.e. with \(i\) to be the matching index such that

\[f(x)=y_i \text{ for } \mid x_i -x \mid = \min_j \mid x_j -x \mid\]

>>> from curves.interpolation import nearest
>>> c = nearest([1,2,3], [1,2,3])
>>> c(0)
1.0
>>> c(1)
1.0
>>> c(1.5)
1.0
>>> c(1.51)
2.0
>>> c(2)
2.0
>>> c(4)
3.0
class curves.interpolation.linear(x_list=(), y_list=())[source]

Bases: base_interpolation

linear interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.linear object is a function \(f\) returning at \(x\) the linear interpolated float of \(y_i\) and \(y_{i+1}\) when \(x_i \leq x < x_{i+1}\), i.e.

\[f(x)=(y_{i+1}-y_i) \cdot \frac{x-x_i}{x_{i+1}-x_i}\]

>>> from curves.interpolation import linear
>>> c = linear([1,2,3], [2,3,4])
>>> c(0)
1.0
>>> c(1)
2.0
>>> c(1.5)
2.5
>>> c(1.51)
2.51
>>> c(2)
3.0
>>> c(4)
5.0
class curves.interpolation.piecewise_linear(x_list=(), y_list=())[source]

Bases: linear

piecewise linear curve

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.piecewise_linear object is a function \(f\) returning at \(x\) the linear interpolated float of \(y_i\) and \(y_{i+1}\) when \(x_i \leq x < x_{i+1}\), i.e.

\[f(x)=(y_{i+1}-y_i) \cdot \frac{x-x_i}{x_{i+1}-x_i}\]

and

\(y_1\) if \(x \leq x_1\)

as well as

\(y_n\) if \(x_n <x\).

>>> from curves.interpolation import piecewise_linear
>>> c = piecewise_linear([1.,2.,3.], [2.,3.,4.])
>>> c(0.)
2.0
>>> c(1.)
2.0
>>> c(1.5)
2.5
>>> c(1.51)
2.51
>>> c(2.)
3.0
>>> c(3.)
4.0
>>> c(4)
4.0
class curves.interpolation.loglinear(x_list=(), y_list=())[source]

Bases: linear

log-linear interpolation

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.loglinear object is a function \(f\) returning at \(x\) the float \(\exp(y)\) of the linear interpolated float \(y\) of \(\log(y_i)\) and \(\log(y_{i+1})\) when \(x_i \leq x < x_{i+1}\), i.e.

\[f(x)=\exp\Big((\log(y_{i+1})-\log(y_i)) \cdot \frac{x-x_i}{x_{i+1}-x_i}\Big)\]

>>> from math import log, exp
>>> from curves.interpolation import loglinear
>>> c = loglinear([1,2,3], [exp(2),exp(3),exp(4)])
>>> log(c(0))
1.0
>>> log(c(1))
2.0
>>> log(c(1.5))
2.5
>>> log(c(1.51))
2.51
>>> log(c(2))
3.0
>>> log(c(4))
5.0

Note

loglinear requires strictly positive values \(0<y_1 \dots y_n\).

class curves.interpolation.loglinearrate(x_list=(), y_list=())[source]

Bases: linear

log-linear interpolation by annual rates

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.loglinearrate object is a function \(f\) returning at \(x\) the float \(\exp(x \cdot y)\) of the linear interpolated float \(y\) of \(\log(\frac{y_i}{x_i})\) and \(\log(\frac{y_{i+1}}{x_{i+1}})\) when \(x_i \leq x < x_{i+1}\), i.e.

\[f(x)=\exp\Big(x \cdot (\log(\frac{y_{i+1}}{x_{i+1}})-\log(\frac{y_i}{x_i})) \cdot \frac{x-x_i}{x_{i+1}-x_i}\Big)\]

>>> from math import log, exp
>>> from curves.interpolation import loglinear
>>> c = loglinear([1,2,3], [exp(1*2),exp(2*3),exp(2*4)])
>>> log(c(0))
-2.0
>>> log(c(1))
2.0
>>> log(c(1.5))
4.0
>>> log(c(1.51))
4.04
>>> log(c(2))
6.0
>>> log(c(4))
10.0

Note

loglinear requires strictly positive values \(0<y_1 \dots y_n\).

class curves.interpolation.logconstantrate(x_list=(), y_list=())[source]

Bases: constant

log-constant interpolation by annual rates

Parameters:
  • x_list – points \(x_1 \dots x_n\)

  • y_list – values \(y_1 \dots y_n\)

A curves.interpolation.logconstantrate object is a function \(f\) returning at \(x\) the float \(\exp(x \cdot y)\) of the constant interpolated float \(y\) of \(\log(\frac{y_i}{x_i})\) when \(x_i \leq x < x_{i+1}\), i.e.

\[f(x)=\exp\Big(x \cdot \log(\frac{y_i}{x_i})\Big)\]

>>> from math import log, exp
>>> from curves.interpolation import logconstantrate
>>> c = logconstantrate([1,2,3], [exp(1*2),exp(2*3),exp(2*4)])
>>> log(c(1))
2.0
>>> log(c(1.5))
3.0
>>> log(c(1.51))
3.02
>>> log(c(2))
6.0
>>> log(c(3))
8.0

Note

logconstantrate requires strictly positive values \(0<y_1 \dots y_n\).

class curves.interpolation.base_extrapolation(mid, left=None, right=None)[source]

Bases: object

curves.interpolation.extrapolation(x_list, y_list, mid=<class 'curves.interpolation.linear'>, left=None, right=None)[source]
class curves.interpolation.waterfall_extrapolation(mid, *higher, left=None, right=None)[source]

Bases: base_extrapolation

curves.interpolation.waterfall(*mid, left=None, right=None)[source]