Skip to content

API Reference

finance

Module containing components for financial mathematics, including derivative pricing models.

BinomialPricingModel

Bases: DiscretePricingModel

A class modeling a binomial pricing model.

The base constructor is not meant to be called directly by users. Instead, the user should call the generate class method. See the Examples section below for usage.

Examples:

>>> from sigalg.finance import BinomialPricingModel

Given parameters of a binomial model, enumerate all length-3 price trajectories in dense enumeration mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     enum_mode="dense",
...     mode="enum",
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0  110.000000  121.000000  133.100000
1      100.0  110.000000  121.000000  110.000000
2      100.0  110.000000  100.000000  110.000000
3      100.0  110.000000  100.000000   90.909091
4      100.0   90.909091  100.000000  110.000000
5      100.0   90.909091  100.000000   90.909091
6      100.0   90.909091   82.644628   90.909091
7      100.0   90.909091   82.644628   75.131480

Enumerate all length-3 price trajectories in sparse enumeration mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     enum_mode="sparse",
...     mode="enum",
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0  110.000000  121.000000  133.100000
1      100.0   90.909091  100.000000  110.000000
2      100.0   90.909091   82.644628   90.909091
3      100.0   90.909091   82.644628   75.131480

Simulate ten length-3 trajectories in sim mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     mode="sim",
...     n_trajectories=10,
...     random_state=42,
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0   90.909091  100.000000   90.909091
1      100.0  110.000000  121.000000  110.000000
2      100.0   90.909091   82.644628   90.909091
3      100.0  110.000000  121.000000  110.000000
4      100.0  110.000000  100.000000  110.000000
5      100.0  110.000000  121.000000  133.100000
6      100.0   90.909091  100.000000   90.909091
7      100.0  110.000000  100.000000   90.909091
8      100.0   90.909091  100.000000  110.000000
9      100.0  110.000000  121.000000  133.100000

down_factor property

down_factor

Get the down-factor of the model.

Returns:

Name Type Description
down_factor Real

The down-factor of the model.

down_prob property

down_prob

Get the probability of a downward price movement.

Returns:

Name Type Description
down_prob Real

The probability of a downward price movement.

enum_mode property

enum_mode

Get the enumeration mode of the model.

Returns:

Name Type Description
enum_mode Literal['dense', 'sparse']

The enumeration mode of the model.

initial_price property

initial_price

Get the initial price of the asset.

Returns:

Name Type Description
initial_price Real

The initial price of the asset.

risk_free_gross_return property

risk_free_gross_return

Get the per-period risk-free gross return of the model.

Returns:

Name Type Description
risk_free_gross_return Real

The per-period risk-free gross return.

risk_free_rate property

risk_free_rate

Get the per-period risk-free rate.

Returns:

Name Type Description
risk_free_rate Real

The risk-free rate.

up_factor property

up_factor

Get the up-factor of the model.

Returns:

Name Type Description
up_factor Real

The up-factor of the model.

up_prob property

up_prob

Get the probability of an upward price movement.

Returns:

Name Type Description
up_prob Real

The probability of an upward price movement.

B

B(claim, **kwargs)

Get the price process of the non-risky asset in the replicating portfolio of a claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose price process of the non-risky claim is to be computed.

required

Returns:

Name Type Description
B StochasticProcess

The price process of the non-risky asset of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(S.B(claim=euro_call))
Stochastic process 'B':
t              0          1          2
omega
0     -61.564626 -77.108844 -95.238095
1     -61.564626 -77.108844 -95.238095
2     -61.564626 -77.108844 -38.142857
3     -61.564626 -77.108844 -38.142857
4     -61.564626 -27.244898 -38.142857
5     -61.564626 -27.244898 -38.142857
6     -61.564626 -27.244898   0.000000
7     -61.564626 -27.244898   0.000000

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(S.B(claim=american_put))
Stochastic process 'B':
t             0          1          2
omega
0      49.73275  13.594104   0.000000
1      49.73275  13.594104   0.000000
2      49.73275  13.594104  57.095238
3      49.73275  13.594104  57.095238
4      49.73275  88.401361  57.095238
5      49.73275  88.401361  57.095238
6      49.73275  88.401361  95.238095
7      49.73275  88.401361  95.238095

continuation_process

continuation_process(claim, **kwargs)

Get the continuation/value process of the replicating portfolio of a claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose continuation/price process is to be computed.

required

Returns:

Name Type Description
continuation_process StochasticProcess

The continuation/value process of the replicating portfolio of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral continuation process of the call option.

>>> print(S.continuation_process(claim=euro_call))
Stochastic process 'V':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral continuation process of the put option.

>>> print(american_put.continuation_process())
Stochastic process 'V':
t             0         1          2     3
omega
0      2.822319  0.617914   0.000000   0.0
1      2.822319  0.617914   0.000000   0.0
2      2.822319  0.617914   2.595238   0.0
3      2.822319  0.617914   2.595238  10.9
4      2.822319  6.377551   2.595238   0.0
5      2.822319  6.377551   2.595238  10.9
6      2.822319  6.377551  14.238095  10.9
7      2.822319  6.377551  14.238095  27.1

delta

delta(claim, **kwargs)

Get the delta process of the replicating portfolio of a claim.

Parameters:

Name Type Description Default
claim Claim

The claim whose delta process is to be computed.

required

Returns:

Name Type Description
delta StochasticProcess

The delta process of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(S.delta(claim=euro_call))
Stochastic process 'Delta':
t             0         1         2
omega
0      0.768707  0.882035  1.000000
1      0.768707  0.882035  1.000000
2      0.768707  0.882035  0.449495
3      0.768707  0.882035  0.449495
4      0.768707  0.353175  0.449495
5      0.768707  0.353175  0.449495
6      0.768707  0.353175 -0.000000
7      0.768707  0.353175 -0.000000

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(S.delta(claim=american_put))
Stochastic process 'Delta':
t             0         1         2
omega
0     -0.469104 -0.117965 -0.000000
1     -0.469104 -0.117965 -0.000000
2     -0.469104 -0.117965 -0.550505
3     -0.469104 -0.117965 -0.550505
4     -0.469104 -0.911376 -0.550505
5     -0.469104 -0.911376 -0.550505
6     -0.469104 -0.911376 -1.000000
7     -0.469104 -0.911376 -1.000000

emm

emm(*args, **kwargs)

Get the equivalent martingale measure of the model.

Returns:

Name Type Description
emm ProbabilityMeasure

The equivalent martingale measure of the model.

Examples:

>>> from sigalg.finance import BinomialPricingModel

Define the parameters of a binomial pricing model.

>>> S_0 = 100
>>> r = 0.05
>>> p = 0.55
>>> u = 1.1
>>> d = 0.9
>>> T = 2

Exhaustively generate all price trajectories and print them.

>>> S = BinomialPricingModel.generate(
...     initial_price=S_0,
...     risk_free_rate=r,
...     up_prob=p,
...     up_factor=u,
...     down_factor=d,
...     mode="enum",
...     length=T,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2
omega
0      100.0  110.0  121.0
1      100.0  110.0   99.0
2      100.0   90.0   99.0
3      100.0   90.0   81.0

Print the equivalent martingale measure.

>>> Q = S.emm()
>>> print(Q)
Probability measure 'Q':
            Q
omega
0      0.5625
1      0.1875
2      0.1875
3      0.0625

Check that the discounted model is a martingale with respect to the EMM.

>>> S.discount(r).is_martingale(prob_measure=Q)
True

exercise_time

exercise_time(claim, **kwargs)

Get the exercise time of a claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose exercise times are to be compute.

required

Returns:

Name Type Description
exercise_time StoppingTime

The exercise time of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(S.exercise_time(claim=euro_call))
Stopping time 'tau':
       tau
omega
0      3.0
1      3.0
2      3.0
3      inf
4      3.0
5      inf
6      inf
7      inf

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(S.exercise_time(claim=american_put))
Stopping time 'tau':
       tau
omega
0      inf
1      inf
2      inf
3      3.0
4      1.0
5      1.0
6      1.0
7      1.0

generate

generate(
    initial_price,
    up_factor,
    down_factor=None,
    up_prob=0.5,
    risk_free_rate=None,
    risk_free_gross_return=None,
    enum_mode="dense",
    mode="sim",
    n_trajectories=None,
    domain_name=None,
    index=None,
    length=None,
    name="S",
    random_state=None,
)

Generate trajectories of the binomial pricing model by either exhaustive enumeration (in sparse or dense mode) or Monte Carlo simulation.

Parameters:

Name Type Description Default
initial_price Real

The initial price of the asset.

required
up_factor Real

The up-factor of the model.

required
down_factor Real | None

The down-factor of the model. If None, then it will be set to the reciprocal of the up-factor.

None
up_prob Real

The probability of an upward move in the price.

0.5
risk_free_rate Real | None

The per-period risk-free rate. If None, the risk-free gross return must be given.

None
risk_free_gross_return Real | None

The per-period risk-free gross return. If None, the risk-free rate must be given.

None
enum_mode Literal['dense', 'sparse']

The mode of enumeration. If the generation mode is set to sim, this parameter is ignore.

"dense"
mode Literal['enum', 'sim']

Whether to generate trajectories by exhuastive enumeration or Monte Carlo simulation.

'sim'
n_trajectories int | None

The number of trajectories to simulate. If the generation mode is set to enum, this parameter is ignored.

None
index IndexLike | None

The index of the stochastic process. One of index or length must be provided; if both are provided, the length of index must match length.

None
length int | None

The length of the trajectories of the stochastic process. One of index or length must be provided; if both are provided, the length of index must match length.

None
name Hashable

The name of the stochastic process.

"S"
random_state int | Generator | None

An optional random state for reproducibility.

None

Returns:

Name Type Description
info dict[str, object]

A dictionary containing the names of the BinomialPricingModel-specific parameters and their values.

Examples:

>>> from sigalg.finance import BinomialPricingModel

Given parameters of a binomial model, enumerate all length-3 price trajectories in dense enumeration mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     enum_mode="dense",
...     mode="enum",
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0  110.000000  121.000000  133.100000
1      100.0  110.000000  121.000000  110.000000
2      100.0  110.000000  100.000000  110.000000
3      100.0  110.000000  100.000000   90.909091
4      100.0   90.909091  100.000000  110.000000
5      100.0   90.909091  100.000000   90.909091
6      100.0   90.909091   82.644628   90.909091
7      100.0   90.909091   82.644628   75.131480

Enumerate all length-3 price trajectories in sparse enumeration mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     enum_mode="sparse",
...     mode="enum",
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0  110.000000  121.000000  133.100000
1      100.0   90.909091  100.000000  110.000000
2      100.0   90.909091   82.644628   90.909091
3      100.0   90.909091   82.644628   75.131480

Simulate ten length-3 trajectories in sim mode.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     risk_free_rate=0.01,
...     up_factor=1.1,
...     up_prob=0.7,
...     length=3,
...     mode="sim",
...     n_trajectories=10,
...     random_state=42,
... )
>>> print(S)
Binomial price process 'S':
t          0           1           2           3
omega
0      100.0   90.909091  100.000000   90.909091
1      100.0  110.000000  121.000000  110.000000
2      100.0   90.909091   82.644628   90.909091
3      100.0  110.000000  121.000000  110.000000
4      100.0  110.000000  100.000000  110.000000
5      100.0  110.000000  121.000000  133.100000
6      100.0   90.909091  100.000000   90.909091
7      100.0  110.000000  100.000000   90.909091
8      100.0   90.909091  100.000000  110.000000
9      100.0  110.000000  121.000000  133.100000

price

price(claim, **kwargs)

Get the risk-neutral price of a claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim to price.

required

Returns:

Name Type Description
price Real

The risk-neutral price of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral price of the call option.

>>> S.price(claim=euro_call)
15.306122448979611

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral price of the put option.

>>> S.price(claim=american_put)
2.822319403952058

price_process

price_process(claim, **kwargs)

Get the risk-neutral price process of a claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose price process is to be computed.

required

Returns:

Name Type Description
price_process StochasticProcess

The risk-neutral price process of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral price process of the call option.

>>> print(S.price_process(claim=euro_call))
Stochastic process 'X':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral price process of the put option.

>>> print(S.price_process(claim=american_put))
Stochastic process 'X':
t             0          1          2     3
omega
0      2.822319   0.617914   0.000000   0.0
1      2.822319   0.617914   0.000000   0.0
2      2.822319   0.617914   2.595238   0.0
3      2.822319   0.617914   2.595238  10.9
4      2.822319  10.000000   2.595238   0.0
5      2.822319  10.000000   2.595238  10.9
6      2.822319  10.000000  19.000000  10.9
7      2.822319  10.000000  19.000000  27.1

replicating_portfolio

replicating_portfolio(claim, **kwargs)

Compute the replicating portfolio for a given contingent claim.

Parameters:

Name Type Description Default
claim Claim

The contingent claim for which to compute the replicating portfolio.

required

Returns:

Name Type Description
replicating_portfolio tuple[StochasticProcess, StochasticProcess, StochasticProcess]

Three processes Delta, B, and V. The first gives the number of units of the risky asset, the second gives the cash value of the position in the non-risky asset, and the third is the value process of the two-asset portfolio.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Generate the replicating portfolio for the European call.

>>> Delta, B, V = S.replicating_portfolio(claim=euro_call)

Print the Delta and B price processes of the hedging portfolio, along with its value process V.

>>> print(Delta)
Stochastic process 'Delta':
t             0         1         2
omega
0      0.768707  0.882035  1.000000
1      0.768707  0.882035  1.000000
2      0.768707  0.882035  0.449495
3      0.768707  0.882035  0.449495
4      0.768707  0.353175  0.449495
5      0.768707  0.353175  0.449495
6      0.768707  0.353175 -0.000000
7      0.768707  0.353175 -0.000000
>>> print(B)
Stochastic process 'B':
t              0          1          2
omega
0     -61.564626 -77.108844 -95.238095
1     -61.564626 -77.108844 -95.238095
2     -61.564626 -77.108844 -38.142857
3     -61.564626 -77.108844 -38.142857
4     -61.564626 -27.244898 -38.142857
5     -61.564626 -27.244898 -38.142857
6     -61.564626 -27.244898   0.000000
7     -61.564626 -27.244898   0.000000
>>> print(V)
Stochastic process 'V':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Now define an Asian put option with early-exercise and the same strike.

>>> asian_put = Claim.asian_option(strike=100, model=S, type="put", early_exercise=True, name="asian_put")
>>> print(asian_put)
Asian option 'asian_put':
t        0    1         2       3
omega
0      0.0  0.0  0.000000   0.000
1      0.0  0.0  0.000000   0.000
2      0.0  0.0  0.000000   0.000
3      0.0  0.0  0.000000   0.475
4      0.0  5.0  3.666667   0.525
5      0.0  5.0  3.666667   5.475
6      0.0  5.0  9.666667   9.975
7      0.0  5.0  9.666667  14.025

Compute and print the replicating portfolio.

>>> Delta, B, V = S.replicating_portfolio(claim=asian_put)
>>> print(Delta)
Stochastic process 'Delta':
t             0         1        2
omega
0     -0.254181 -0.005141 -0.00000
1     -0.254181 -0.005141 -0.00000
2     -0.254181 -0.005141 -0.02399
3     -0.254181 -0.005141 -0.02399
4     -0.254181 -0.377646 -0.25000
5     -0.254181 -0.377646 -0.25000
6     -0.254181 -0.377646 -0.25000
7     -0.254181 -0.377646 -0.25000
>>> print(B)
Stochastic process 'B':
t              0          1          2
omega
0      26.654114   0.592404   0.000000
1      26.654114   0.592404   0.000000
2      26.654114   0.592404   2.488095
3      26.654114   0.592404   2.488095
4      26.654114  39.098639  26.428571
5      26.654114  39.098639  26.428571
6      26.654114  39.098639  30.714286
7      26.654114  39.098639  30.714286
>>> print(V)
Stochastic process 'V':
t            0         1          2       3
omega
0      1.23603  0.026927   0.000000   0.000
1      1.23603  0.026927   0.000000   0.000
2      1.23603  0.026927   0.113095   0.000
3      1.23603  0.026927   0.113095   0.475
4      1.23603  5.110544   1.678571   0.525
5      1.23603  5.110544   1.678571   5.475
6      1.23603  5.110544  10.464286   9.975
7      1.23603  5.110544  10.464286  14.025

risk_neutral_probs

risk_neutral_probs(*args, **kwargs)

Get the risk-neutral probabilities of the model.

Returns:

Name Type Description
risk_neutral_probs tuple[Real, Real]

The risk neutral probabilities as a tuple (q_u, q_d), where q_u is the risk-neutral probability of an up move, and q_d is the risk-neutral probability of a down move.

Examples:

>>> from sigalg.finance import BinomialPricingModel

Define the parameters of a binomial pricing model.

>>> S_0 = 100
>>> r = 0.05
>>> p = 0.55
>>> u = 1.1
>>> d = 0.9
>>> T = 2

Exhaustively generate all price trajectories and print them.

>>> S = BinomialPricingModel.generate(
...     initial_price=S_0,
...     risk_free_rate=r,
...     up_prob=p,
...     up_factor=u,
...     down_factor=d,
...     mode="enum",
...     length=T,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2
omega
0      100.0  110.0  121.0
1      100.0  110.0   99.0
2      100.0   90.0   99.0
3      100.0   90.0   81.0

Get the risk-neutral probabilities of the model.

>>> S.risk_neutral_probs()
(0.7499999999999999, 0.2500000000000001)

Claim

Bases: StochasticProcess

Base class for contingent claims.

The base constructor is not meant to be called directly by users. Instead, the user should call the from_stochastic_process or `from_random_variables_ class methods. See the Examples section below for usage.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Create a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create a stochastic process representing an American-style Asian call option.

>>> process = (S.cumavg() - 100).max(0)
>>> print(process)
Stochastic process 'max((S_cumavg - 100), 0)':
t        0    1          2       3
omega
0      0.0  5.0  10.333333  16.025
1      0.0  5.0  10.333333   9.975
2      0.0  5.0   3.000000   4.475
3      0.0  5.0   3.000000   0.000
4      0.0  0.0   0.000000   0.000
5      0.0  0.0   0.000000   0.000
6      0.0  0.0   0.000000   0.000
7      0.0  0.0   0.000000   0.000

Construct the contingent claim.

>>> Phi = Claim.from_stochastic_process(process=process, model=S, name="Phi")
>>> print(Phi)
Claim 'Phi':
t        0    1          2       3
omega
0      0.0  5.0  10.333333  16.025
1      0.0  5.0  10.333333   9.975
2      0.0  5.0   3.000000   4.475
3      0.0  5.0   3.000000   0.000
4      0.0  0.0   0.000000   0.000
5      0.0  0.0   0.000000   0.000
6      0.0  0.0   0.000000   0.000
7      0.0  0.0   0.000000   0.000

Create the payoff random variable of a European call with strike K=100.

>>> Phi_3 = (S[3] - 100).max(0)
>>> print(Phi_3)
Random variable 'max((S_3 - 100), 0)':
        max((S_3 - 100), 0)
omega
0                     33.1
1                      8.9
2                      8.9
3                      0.0
4                      8.9
5                      0.0
6                      0.0
7                      0.0

Create an instance of Claim from the random variable.

>>> Phi = Claim.from_random_variables(rvs=[Phi_3], times=[3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Create the payoff random variable of a European call with strike K=100 at time t=2.

>>> Phi_2 = (S[2] - 100).max(0)
>>> print(Phi_2)
Random variable 'max((S_2 - 100), 0)':
        max((S_2 - 100), 0)
omega
0                     21.0
1                     21.0
2                      0.0
3                      0.0
4                      0.0
5                      0.0
6                      0.0
7                      0.0

Combine the random variables Phi_3 and Phi_2 into a single instance of Claim that allows exercise at times t=2 and t=3.

>>> Phi = Claim.from_random_variables(rvs=[Phi_2, Phi_3], times=[2, 3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1     2     3
omega
0      0.0  0.0  21.0  33.1
1      0.0  0.0  21.0   8.9
2      0.0  0.0   0.0   8.9
3      0.0  0.0   0.0   0.0
4      0.0  0.0   0.0   8.9
5      0.0  0.0   0.0   0.0
6      0.0  0.0   0.0   0.0
7      0.0  0.0   0.0   0.0

is_early_exercise property

is_early_exercise

Return whether the claim allows early exercise or not.

Returns:

Name Type Description
is_early_exercise bool

Whether the claim allows early exercise or not.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Create a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create the payoff random variable of a European call with strike K=100.

>>> Phi_3 = (S[3] - 100).max(0)
>>> print(Phi_3)
Random variable 'max((S_3 - 100), 0)':
        max((S_3 - 100), 0)
omega
0                     33.1
1                      8.9
2                      8.9
3                      0.0
4                      8.9
5                      0.0
6                      0.0
7                      0.0

Create an instance of Claim from the random variable and check whether it allows early exercise.

>>> Phi = Claim.from_random_variables(rvs=[Phi_3], times=[3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0
>>> Phi.is_early_exercise
False

Create the payoff random variable of a European call with strike K=100 at time t=2.

>>> Phi_2 = (S[2] - 100).max(0)
>>> print(Phi_2)
Random variable 'max((S_2 - 100), 0)':
        max((S_2 - 100), 0)
omega
0                     21.0
1                     21.0
2                      0.0
3                      0.0
4                      0.0
5                      0.0
6                      0.0
7                      0.0

Combine the random variables Phi_3 and Phi_2 into a single instance of Claim that allows exercise at times t=2 and t=3.

>>> Phi = Claim.from_random_variables(rvs=[Phi_2, Phi_3], times=[2, 3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1     2     3
omega
0      0.0  0.0  21.0  33.1
1      0.0  0.0  21.0   8.9
2      0.0  0.0   0.0   8.9
3      0.0  0.0   0.0   0.0
4      0.0  0.0   0.0   8.9
5      0.0  0.0   0.0   0.0
6      0.0  0.0   0.0   0.0
7      0.0  0.0   0.0   0.0
>>> Phi.is_early_exercise
True

PricingData dataclass

Data class for pricing data for contingent claims.

B

B(**kwargs)

Get the price process of the non-risky asset of the claim.

Returns:

Name Type Description
B StochasticProcess

The price process of the non-risky asset of the claim.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(euro_call.B())
Stochastic process 'B':
t              0          1          2
omega
0     -61.564626 -77.108844 -95.238095
1     -61.564626 -77.108844 -95.238095
2     -61.564626 -77.108844 -38.142857
3     -61.564626 -77.108844 -38.142857
4     -61.564626 -27.244898 -38.142857
5     -61.564626 -27.244898 -38.142857
6     -61.564626 -27.244898   0.000000
7     -61.564626 -27.244898   0.000000

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(american_put.B())
Stochastic process 'B':
t             0          1          2
omega
0      49.73275  13.594104   0.000000
1      49.73275  13.594104   0.000000
2      49.73275  13.594104  57.095238
3      49.73275  13.594104  57.095238
4      49.73275  88.401361  57.095238
5      49.73275  88.401361  57.095238
6      49.73275  88.401361  95.238095
7      49.73275  88.401361  95.238095

american_option classmethod

american_option(strike, model, type='call', name='Phi')

Create an Asian option.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create an Asian call option with strike K=100 and no early exercise.

>>> K = 100
>>> Phi_call_no_early = Claim.asian_option(
...     strike=100, model=S, type="call", early_exercise=False, name="Phi_call_no_early"
... )
>>> print(Phi_call_no_early)
Asian option 'Phi_call_no_early':
t        0    1    2       3
omega
0      0.0  0.0  0.0  16.025
1      0.0  0.0  0.0   9.975
2      0.0  0.0  0.0   4.475
3      0.0  0.0  0.0   0.000
4      0.0  0.0  0.0   0.000
5      0.0  0.0  0.0   0.000
6      0.0  0.0  0.0   0.000
7      0.0  0.0  0.0   0.000

Create an Asian call with the same strike and with early exercise.

>>> Phi_call_early = Claim.asian_option(
...     strike=100, model=S, type="call", early_exercise=True, name="Phi_call_early"
... )
>>> print(Phi_call_early)
Asian option 'Phi_call_early':
t        0    1          2       3
omega
0      0.0  5.0  10.333333  16.025
1      0.0  5.0  10.333333   9.975
2      0.0  5.0   3.000000   4.475
3      0.0  5.0   3.000000   0.000
4      0.0  0.0   0.000000   0.000
5      0.0  0.0   0.000000   0.000
6      0.0  0.0   0.000000   0.000
7      0.0  0.0   0.000000   0.000

Create an Asian put with the same strike and no early exercise.

>>> Phi_put_no_early = Claim.asian_option(
...     strike=100, model=S, type="put", early_exercise=False, name="Phi_put_no_early"
... )
>>> print(Phi_put_no_early)
Asian option 'Phi_put_no_early':
t        0    1    2       3
omega
0      0.0  0.0  0.0   0.000
1      0.0  0.0  0.0   0.000
2      0.0  0.0  0.0   0.000
3      0.0  0.0  0.0   0.475
4      0.0  0.0  0.0   0.525
5      0.0  0.0  0.0   5.475
6      0.0  0.0  0.0   9.975
7      0.0  0.0  0.0  14.025

Create an Asian put with the same strike and early exercise.

>>> Phi_put_early = Claim.asian_option(
...     strike=100, model=S, type="put", early_exercise=True, name="Phi_put_early"
... )
>>> print(Phi_put_early)
Asian option 'Phi_put_early':
t        0    1         2       3
omega
0      0.0  0.0  0.000000   0.000
1      0.0  0.0  0.000000   0.000
2      0.0  0.0  0.000000   0.000
3      0.0  0.0  0.000000   0.475
4      0.0  5.0  3.666667   0.525
5      0.0  5.0  3.666667   5.475
6      0.0  5.0  9.666667   9.975
7      0.0  5.0  9.666667  14.025

asian_option classmethod

asian_option(
    strike,
    model,
    type="call",
    early_exercise=False,
    name="Phi",
)

Pass.

continuation_process

continuation_process(**kwargs)

Get the continuation process of the claim.

Returns:

Name Type Description
continuation_process StochasticProcess

The continuation process of the claim relative to the underlying price model.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral continuation process of the call option.

>>> print(euro_call.continuation_process())
Stochastic process 'V':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral continuation process of the put option.

>>> print(american_put.continuation_process())
Stochastic process 'V':
t             0         1          2     3
omega
0      2.822319  0.617914   0.000000   0.0
1      2.822319  0.617914   0.000000   0.0
2      2.822319  0.617914   2.595238   0.0
3      2.822319  0.617914   2.595238  10.9
4      2.822319  6.377551   2.595238   0.0
5      2.822319  6.377551   2.595238  10.9
6      2.822319  6.377551  14.238095  10.9
7      2.822319  6.377551  14.238095  27.1

delta

delta(**kwargs)

Get the delta process of the claim.

Returns:

Name Type Description
delta StochasticProcess

The delta process of the claim relative to the underlying price model.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(euro_call.delta())
Stochastic process 'Delta':
t             0         1         2
omega
0      0.768707  0.882035  1.000000
1      0.768707  0.882035  1.000000
2      0.768707  0.882035  0.449495
3      0.768707  0.882035  0.449495
4      0.768707  0.353175  0.449495
5      0.768707  0.353175  0.449495
6      0.768707  0.353175 -0.000000
7      0.768707  0.353175 -0.000000

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(american_put.delta())
Stochastic process 'Delta':
t             0         1         2
omega
0     -0.469104 -0.117965 -0.000000
1     -0.469104 -0.117965 -0.000000
2     -0.469104 -0.117965 -0.550505
3     -0.469104 -0.117965 -0.550505
4     -0.469104 -0.911376 -0.550505
5     -0.469104 -0.911376 -0.550505
6     -0.469104 -0.911376 -1.000000
7     -0.469104 -0.911376 -1.000000

european_option classmethod

european_option(strike, model, type='call', name='Phi')

Create a European option.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create a European call option with strike K=100.

>>> K = 100
>>> Phi_call = Claim.european_option(strike=K, model=S, type="call", name="Phi_call")
>>> print(Phi_call)
European option 'Phi_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Create a European put option with the same strike.

>>> Phi_put = Claim.european_option(strike=K, model=S, type="put", name="Phi_put")
>>> print(Phi_put)
European option 'Phi_put':
t        0    1    2     3
omega
0      0.0  0.0  0.0   0.0
1      0.0  0.0  0.0   0.0
2      0.0  0.0  0.0   0.0
3      0.0  0.0  0.0  10.9
4      0.0  0.0  0.0   0.0
5      0.0  0.0  0.0  10.9
6      0.0  0.0  0.0  10.9
7      0.0  0.0  0.0  27.1

exercise_time

exercise_time(**kwargs)

Get the exercise time of the claim.

Returns:

Name Type Description
exercise_time StoppingTime

The exercise time of the claim relative to the underlying price model.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the exercise time of the call option.

>>> print(euro_call.exercise_time())
Stopping time 'tau':
       tau
omega
0      3.0
1      3.0
2      3.0
3      inf
4      3.0
5      inf
6      inf
7      inf

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(american_put.exercise_time())
Stopping time 'tau':
       tau
omega
0      inf
1      inf
2      inf
3      3.0
4      1.0
5      1.0
6      1.0
7      1.0

from_random_variables classmethod

from_random_variables(rvs, times, model, name='Phi')

Construct a contingent claim from a list of random variables and a list of times.

The random variables are inserted into the claim at the specified times. Any unspecified times are filled with the 0 random variable. See the Examples section below.

Parameters:

Name Type Description Default
rvs list[RandomVariable]

The list of random variables to include as the components of the contingent claim.

required
times list[Real]

The list of times corresponding to the random variables.

required
model DiscretePricingModel

The pricing model.

required
name Hashable

The name for the claim.

"Phi"

Returns:

Name Type Description
claim Claim

The contingent claim created from the random variables.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Create a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create the payoff random variable of a European call with strike K=100.

>>> Phi_3 = (S[3] - 100).max(0)
>>> print(Phi_3)
Random variable 'max((S_3 - 100), 0)':
       max((S_3 - 100), 0)
omega
0                     33.1
1                      8.9
2                      8.9
3                      0.0
4                      8.9
5                      0.0
6                      0.0
7                      0.0

Create an instance of Claim from the random variable.

>>> Phi = Claim.from_random_variables(rvs=[Phi_3], times=[3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Create the payoff random variable of a European call with strike K=100 at time t=2.

>>> Phi_2 = (S[2] - 100).max(0)
>>> print(Phi_2)
Random variable 'max((S_2 - 100), 0)':
       max((S_2 - 100), 0)
omega
0                     21.0
1                     21.0
2                      0.0
3                      0.0
4                      0.0
5                      0.0
6                      0.0
7                      0.0

Combine the random variables Phi_3 and Phi_2 into a single instance of Claim that allows exercise at times t=2 and t=3.

>>> Phi = Claim.from_random_variables(rvs=[Phi_2, Phi_3], times=[2, 3], model=S)
>>> print(Phi)
Claim 'Phi':
t        0    1     2     3
omega
0      0.0  0.0  21.0  33.1
1      0.0  0.0  21.0   8.9
2      0.0  0.0   0.0   8.9
3      0.0  0.0   0.0   0.0
4      0.0  0.0   0.0   8.9
5      0.0  0.0   0.0   0.0
6      0.0  0.0   0.0   0.0
7      0.0  0.0   0.0   0.0

from_stochastic_process classmethod

from_stochastic_process(process, model, name=None)

Construct a contingent claim from a stochastic process.

Parameters:

Name Type Description Default
process StochasticProcess

The stochastic process used to generate the contingent claim.

required
model DiscretePricingModel

The pricing model.

required
name Hashable | None

The name for the claim. If None, the pre-existing name of the stochastic process will be used.

None

Returns:

Name Type Description
claim Claim

The contingent claim created from the stochastic process

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Create a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_prob=0.7,
...     up_factor=1.1,
...     down_factor=0.9,
...     risk_free_rate=0.05,
...     enum_mode="dense",
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Create a stochastic process representing an American-style Asian call option.

>>> process = (S.cumavg() - 100).max(0)
>>> print(process)
Stochastic process 'max((S_cumavg - 100), 0)':
t        0    1          2       3
omega
0      0.0  5.0  10.333333  16.025
1      0.0  5.0  10.333333   9.975
2      0.0  5.0   3.000000   4.475
3      0.0  5.0   3.000000   0.000
4      0.0  0.0   0.000000   0.000
5      0.0  0.0   0.000000   0.000
6      0.0  0.0   0.000000   0.000
7      0.0  0.0   0.000000   0.000

Construct the contingent claim.

>>> Phi = Claim.from_stochastic_process(process=process, model=S, name="Phi")
>>> print(Phi)
Claim 'Phi':
t        0    1          2       3
omega
0      0.0  5.0  10.333333  16.025
1      0.0  5.0  10.333333   9.975
2      0.0  5.0   3.000000   4.475
3      0.0  5.0   3.000000   0.000
4      0.0  0.0   0.000000   0.000
5      0.0  0.0   0.000000   0.000
6      0.0  0.0   0.000000   0.000
7      0.0  0.0   0.000000   0.000

price

price(**kwargs)

Get the price of the claim.

Returns:

Name Type Description
price Real

The price of the claim relative to the underlying price model.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral price of the call option.

>>> euro_call.price()
15.306122448979611

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral price of the put option.

>>> american_put.price()
2.822319403952058

price_process

price_process(**kwargs)

Get the price process of the claim.

Returns:

Name Type Description
price_process StochasticProcess

The price process of the claim relative to the underlying price model.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Get the risk-neutral price process of the call option.

>>> print(euro_call.price_process())
Stochastic process 'X':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   1.0   0.0
3      0.0   0.0   1.0  10.9
4      0.0  10.0   1.0   0.0
5      0.0  10.0   1.0  10.9
6      0.0  10.0  19.0  10.9
7      0.0  10.0  19.0  27.1

Get the risk-neutral price process of the put option.

>>> print(american_put.price_process())
Stochastic process 'X':
t             0          1          2     3
omega
0      2.822319   0.617914   0.000000   0.0
1      2.822319   0.617914   0.000000   0.0
2      2.822319   0.617914   2.595238   0.0
3      2.822319   0.617914   2.595238  10.9
4      2.822319  10.000000   2.595238   0.0
5      2.822319  10.000000   2.595238  10.9
6      2.822319  10.000000  19.000000  10.9
7      2.822319  10.000000  19.000000  27.1

replicating_portfolio

replicating_portfolio(**kwargs)

Compute the replicating portfolio of the claim.

Returns:

Name Type Description
replicating_portfolio tuple[StochasticProcess, StochasticProcess, StochasticProcess]

Three processes Delta, B, and V. The first gives the number of units of the risky asset, the second gives the cash value of the position in the non-risky asset, and the third is the value process of the two-asset portfolio.

Examples:

>>> from sigalg.finance import BinomialPricingModel, Claim

Define a binomial pricing model.

>>> S = BinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     down_factor=0.9,
...     up_prob=0.7,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Binomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  108.9
2      100.0  110.0   99.0  108.9
3      100.0  110.0   99.0   89.1
4      100.0   90.0   99.0  108.9
5      100.0   90.0   99.0   89.1
6      100.0   90.0   81.0   89.1
7      100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0   8.9
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0   0.0
4      0.0  0.0  0.0   8.9
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   0.0
7      0.0  0.0  0.0   0.0

Generate the replicating portfolio for the European call.

>>> Delta, B, V = euro_call.replicating_portfolio()

Print the Delta and B price processes of the hedging portfolio, along with its value process V.

>>> print(Delta)
Stochastic process 'Delta':
t             0         1         2
omega
0      0.768707  0.882035  1.000000
1      0.768707  0.882035  1.000000
2      0.768707  0.882035  0.449495
3      0.768707  0.882035  0.449495
4      0.768707  0.353175  0.449495
5      0.768707  0.353175  0.449495
6      0.768707  0.353175 -0.000000
7      0.768707  0.353175 -0.000000
>>> print(B)
Stochastic process 'B':
t              0          1          2
omega
0     -61.564626 -77.108844 -95.238095
1     -61.564626 -77.108844 -95.238095
2     -61.564626 -77.108844 -38.142857
3     -61.564626 -77.108844 -38.142857
4     -61.564626 -27.244898 -38.142857
5     -61.564626 -27.244898 -38.142857
6     -61.564626 -27.244898   0.000000
7     -61.564626 -27.244898   0.000000
>>> print(V)
Stochastic process 'V':
t              0          1          2     3
omega
0      15.306122  19.914966  25.761905  33.1
1      15.306122  19.914966  25.761905   8.9
2      15.306122  19.914966   6.357143   8.9
3      15.306122  19.914966   6.357143   0.0
4      15.306122   4.540816   6.357143   8.9
5      15.306122   4.540816   6.357143   0.0
6      15.306122   4.540816   0.000000   0.0
7      15.306122   4.540816   0.000000   0.0

Now define an Asian put option with early-exercise and the same strike.

>>> asian_put = Claim.asian_option(strike=100, model=S, type="put", early_exercise=True, name="asian_put")
>>> print(asian_put)
Asian option 'asian_put':
t        0    1         2       3
omega
0      0.0  0.0  0.000000   0.000
1      0.0  0.0  0.000000   0.000
2      0.0  0.0  0.000000   0.000
3      0.0  0.0  0.000000   0.475
4      0.0  5.0  3.666667   0.525
5      0.0  5.0  3.666667   5.475
6      0.0  5.0  9.666667   9.975
7      0.0  5.0  9.666667  14.025

Compute and print the replicating portfolio.

>>> Delta, B, V = asian_put.replicating_portfolio()
>>> print(Delta)
Stochastic process 'Delta':
t             0         1        2
omega
0     -0.254181 -0.005141 -0.00000
1     -0.254181 -0.005141 -0.00000
2     -0.254181 -0.005141 -0.02399
3     -0.254181 -0.005141 -0.02399
4     -0.254181 -0.377646 -0.25000
5     -0.254181 -0.377646 -0.25000
6     -0.254181 -0.377646 -0.25000
7     -0.254181 -0.377646 -0.25000
>>> print(B)
Stochastic process 'B':
t              0          1          2
omega
0      26.654114   0.592404   0.000000
1      26.654114   0.592404   0.000000
2      26.654114   0.592404   2.488095
3      26.654114   0.592404   2.488095
4      26.654114  39.098639  26.428571
5      26.654114  39.098639  26.428571
6      26.654114  39.098639  30.714286
7      26.654114  39.098639  30.714286
>>> print(V)
Stochastic process 'V':
t            0         1          2       3
omega
0      1.23603  0.026927   0.000000   0.000
1      1.23603  0.026927   0.000000   0.000
2      1.23603  0.026927   0.113095   0.000
3      1.23603  0.026927   0.113095   0.475
4      1.23603  5.110544   1.678571   0.525
5      1.23603  5.110544   1.678571   5.475
6      1.23603  5.110544  10.464286   9.975
7      1.23603  5.110544  10.464286  14.025

TrinomialPricingModel

Bases: DiscretePricingModel

A class modeling a trinomial pricing model.

The base constructor is not meant to be called directly by users. Instead, the user should call the generate class method. See the Examples section below for usage.

Examples:

>>> from sigalg.finance import TrinomialPricingModel

Given parameters of a trinomial model, generate all length-2 price trajectories in enum mode.

>>> S_0 = 4
>>> u = 1.2
>>> m = 1.1
>>> d = 0.9
>>> p_u = 0.6
>>> p_d = 0.1
>>> r = 0.01
>>> S = TrinomialPricingModel.generate(
...     mode="enum",
...     initial_price=S_0,
...     up_factor=u,
...     middle_factor=m,
...     down_factor=d,
...     up_prob=p_u,
...     down_prob=p_d,
...     risk_free_rate=r,
...     length=2,
... )
>>> print(S)
Trinomial price process 'S':
t         0    1     2
omega
0       4.0  4.8  5.76
1       4.0  4.8  5.28
2       4.0  4.8  4.32
3       4.0  4.4  5.28
4       4.0  4.4  4.84
5       4.0  4.4  3.96
6       4.0  3.6  4.32
7       4.0  3.6  3.96
8       4.0  3.6  3.24

Simulate ten length-2 trajectories in sim mode.

>>> S.n_trajectories = 10
>>> S.random_state = 42
>>> S.mode = "sim"
>>> S.regenerate()
>>> print(S)
Trinomial price process 'S':
t        0    1     2
omega
0      4.0  4.4  5.28
1      4.0  4.4  4.84
2      4.0  4.8  4.32
3      4.0  4.4  4.84
4      4.0  4.8  5.76
5      4.0  4.8  4.32
6      4.0  4.4  4.84
7      4.0  4.8  5.76
8      4.0  4.8  5.76
9      4.0  4.4  4.84

down_factor property

down_factor

Get the down-factor of the model.

Returns:

Name Type Description
down_factor Real

The down-factor of the model.

down_prob property

down_prob

Get the probability of a downward price movement.

Returns:

Name Type Description
down_prob Real

The probability of a downward price movement.

initial_price property

initial_price

Get the initial price of the asset.

Returns:

Name Type Description
initial_price Real

The initial price of the asset.

middle_factor property

middle_factor

Get the middle-factor of the model.

Returns:

Name Type Description
middle_factor Real

The middle-factor of the model.

middle_prob property

middle_prob

Get the probability of a middle price movement.

Returns:

Name Type Description
down_prob Real

The probability of a middle price movement.

risk_free_gross_return property

risk_free_gross_return

Get the per-period risk-free gross return of the model.

Returns:

Name Type Description
risk_free_gross_return Real

The per-period risk-free gross return.

risk_free_rate property

risk_free_rate

Get the per-period risk-free rate.

Returns:

Name Type Description
risk_free_rate Real

The risk-free rate.

up_factor property

up_factor

Get the up-factor of the model.

Returns:

Name Type Description
up_factor Real

The up-factor of the model.

up_prob property

up_prob

Get the probability of an upward price movement.

Returns:

Name Type Description
up_prob Real

The probability of an upward price movement.

B

B(*args, **kwargs)

Pass.

continuation_process

continuation_process(claim, theta, **kwargs)

Get the continuation/value process of the replicating portfolio of a claim given an equivalent martingale measure.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose continuation/price process is to be computed.

required
theta Real

A parameter in the open interval (0, 1) yielding a collection of risk-neutral probabilities of the model.

required

Returns:

Name Type Description
continuation_process StochasticProcess

The continuation/value process of the replicating portfolio of the claim.

Examples:

>>> from sigalg.finance import TrinomialPricingModel, Claim

Define a trinomial pricing model.

>>> S = TrinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     middle_factor=1.0,
...     down_factor=0.9,
...     up_prob=0.7,
...     down_prob=0.2,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Trinomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  121.0
2      100.0  110.0  121.0  108.9
3      100.0  110.0  110.0  121.0
4      100.0  110.0  110.0  110.0
5      100.0  110.0  110.0   99.0
6      100.0  110.0   99.0  108.9
7      100.0  110.0   99.0   99.0
8      100.0  110.0   99.0   89.1
9      100.0  100.0  110.0  121.0
10     100.0  100.0  110.0  110.0
11     100.0  100.0  110.0   99.0
12     100.0  100.0  100.0  110.0
13     100.0  100.0  100.0  100.0
14     100.0  100.0  100.0   90.0
15     100.0  100.0   90.0   99.0
16     100.0  100.0   90.0   90.0
17     100.0  100.0   90.0   81.0
18     100.0   90.0   99.0  108.9
19     100.0   90.0   99.0   99.0
20     100.0   90.0   99.0   89.1
21     100.0   90.0   90.0   99.0
22     100.0   90.0   90.0   90.0
23     100.0   90.0   90.0   81.0
24     100.0   90.0   81.0   89.1
25     100.0   90.0   81.0   81.0
26     100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0  21.0
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0  21.0
4      0.0  0.0  0.0  10.0
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   8.9
7      0.0  0.0  0.0   0.0
8      0.0  0.0  0.0   0.0
9      0.0  0.0  0.0  21.0
10     0.0  0.0  0.0  10.0
11     0.0  0.0  0.0   0.0
12     0.0  0.0  0.0  10.0
13     0.0  0.0  0.0   0.0
14     0.0  0.0  0.0   0.0
15     0.0  0.0  0.0   0.0
16     0.0  0.0  0.0   0.0
17     0.0  0.0  0.0   0.0
18     0.0  0.0  0.0   8.9
19     0.0  0.0  0.0   0.0
20     0.0  0.0  0.0   0.0
21     0.0  0.0  0.0   0.0
22     0.0  0.0  0.0   0.0
23     0.0  0.0  0.0   0.0
24     0.0  0.0  0.0   0.0
25     0.0  0.0  0.0   0.0
26     0.0  0.0  0.0   0.0

Get the risk-neutral continuation process of the call option for a specified parameter corresponding to risk-neutral probabilities.

>>> print(S.continuation_process(claim=euro_call, theta=0.2))
Stochastic process 'V':
t             0          1          2     3
omega
0      13.97158  19.358050  25.761905  33.1
1      13.97158  19.358050  25.761905  21.0
2      13.97158  19.358050  25.761905   8.9
3      13.97158  19.358050  14.809524  21.0
4      13.97158  19.358050  14.809524  10.0
5      13.97158  19.358050  14.809524   0.0
6      13.97158  19.358050   4.661905   8.9
7      13.97158  19.358050   4.661905   0.0
8      13.97158  19.358050   4.661905   0.0
9      13.97158   9.752834  14.809524  21.0
10     13.97158   9.752834  14.809524  10.0
11     13.97158   9.752834  14.809524   0.0
12     13.97158   9.752834   5.238095  10.0
13     13.97158   9.752834   5.238095   0.0
14     13.97158   9.752834   5.238095   0.0
15     13.97158   9.752834   0.000000   0.0
16     13.97158   9.752834   0.000000   0.0
17     13.97158   9.752834   0.000000   0.0
18     13.97158   2.441950   4.661905   8.9
19     13.97158   2.441950   4.661905   0.0
20     13.97158   2.441950   4.661905   0.0
21     13.97158   2.441950   0.000000   0.0
22     13.97158   2.441950   0.000000   0.0
23     13.97158   2.441950   0.000000   0.0
24     13.97158   2.441950   0.000000   0.0
25     13.97158   2.441950   0.000000   0.0
26     13.97158   2.441950   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   0.0   0.0
3      0.0   0.0   0.0   0.0
4      0.0   0.0   0.0   0.0
5      0.0   0.0   0.0   1.0
6      0.0   0.0   1.0   0.0
7      0.0   0.0   1.0   1.0
8      0.0   0.0   1.0  10.9
9      0.0   0.0   0.0   0.0
10     0.0   0.0   0.0   0.0
11     0.0   0.0   0.0   1.0
12     0.0   0.0   0.0   0.0
13     0.0   0.0   0.0   0.0
14     0.0   0.0   0.0  10.0
15     0.0   0.0  10.0   1.0
16     0.0   0.0  10.0  10.0
17     0.0   0.0  10.0  19.0
18     0.0  10.0   1.0   0.0
19     0.0  10.0   1.0   1.0
20     0.0  10.0   1.0  10.9
21     0.0  10.0  10.0   1.0
22     0.0  10.0  10.0  10.0
23     0.0  10.0  10.0  19.0
24     0.0  10.0  19.0  10.9
25     0.0  10.0  19.0  19.0
26     0.0  10.0  19.0  27.1

Get the risk-neutral continuation process of the put option.

>>> print(S.continuation_process(claim=american_put, theta=0.2))
Stochastic process 'V':
t             0         1          2     3
omega
0      0.770651  0.065760   0.000000   0.0
1      0.770651  0.065760   0.000000   0.0
2      0.770651  0.065760   0.000000   0.0
3      0.770651  0.065760   0.047619   0.0
4      0.770651  0.065760   0.047619   0.0
5      0.770651  0.065760   0.047619   1.0
6      0.770651  0.065760   0.900000   0.0
7      0.770651  0.065760   0.900000   1.0
8      0.770651  0.065760   0.900000  10.9
9      0.770651  0.682540   0.047619   0.0
10     0.770651  0.682540   0.047619   0.0
11     0.770651  0.682540   0.047619   1.0
12     0.770651  0.682540   0.476190   0.0
13     0.770651  0.682540   0.476190   0.0
14     0.770651  0.682540   0.476190  10.0
15     0.770651  0.682540   5.238095   1.0
16     0.770651  0.682540   5.238095  10.0
17     0.770651  0.682540   5.238095  19.0
18     0.770651  5.238095   0.900000   0.0
19     0.770651  5.238095   0.900000   1.0
20     0.770651  5.238095   0.900000  10.9
21     0.770651  5.238095   5.238095   1.0
22     0.770651  5.238095   5.238095  10.0
23     0.770651  5.238095   5.238095  19.0
24     0.770651  5.238095  14.238095  10.9
25     0.770651  5.238095  14.238095  19.0
26     0.770651  5.238095  14.238095  27.1

delta

delta(*args, **kwargs)

Pass.

emm

emm(theta=None, **kwargs)

Get the equivalent martingale measures of the model.

Parameters:

Name Type Description Default
theta Real | None

An optional real number in the open interval (0, 1) parameterizing the risk-neutral probabilities. If not None, an instance of ProbabilityMeasure is returned; otherwise, an instance of ParametrizedProbabilityMeasure is returned.

None

Returns:

Name Type Description
emm ProbabilityMeasure | ParametrizedProbabilityMeasure

The equivalent martingale measures of the model.

Examples:

>>> from sigalg.finance import TrinomialPricingModel

Define the parameters of a trinomial pricing model.

>>> S_0 = 4
>>> r = 0.01
>>> p_u = 0.6
>>> p_d = 0.1
>>> u = 1.2
>>> m = 1.1
>>> d = 0.9
>>> T = 2

Exhaustively generate all price trajectories and print them.

>>> S = TrinomialPricingModel.generate(
...     initial_price=S_0,
...     risk_free_rate=r,
...     up_prob=p_u,
...     down_prob=p_d,
...     up_factor=u,
...     middle_factor=m,
...     down_factor=d,
...     mode="enum",
...     length=T,
... )
>>> print(S)
Trinomial price process 'S':
t        0    1     2
omega
0      4.0  4.8  5.76
1      4.0  4.8  5.28
2      4.0  4.8  4.32
3      4.0  4.4  5.28
4      4.0  4.4  4.84
5      4.0  4.4  3.96
6      4.0  3.6  4.32
7      4.0  3.6  3.96
8      4.0  3.6  3.24

Get the equivalent martingale measures of the model as an instance of ParametrizedProbabilityMeasure.

>>> Q = S.emm()
>>> print(Q)
ParametrizedProbabilityMeasure(parameters=(theta), domain_vars=(omega), sig_alg=R, name=Q)

Get the EMM corresponding to a specific parameter value.

>>> print(Q(theta=0.2))
Probability measure 'Q(theta=0.2)':
       Q(theta=0.2)
omega
0          0.005378
1          0.032267
2          0.035689
3          0.032267
4          0.193600
5          0.214133
6          0.035689
7          0.214133
8          0.236844

Alternativaly, pass the parameter value directly into the emm method to get the same EMM.

>>> print(S.emm(theta=0.2))
Probability measure 'Q':
                  Q
omega
0          0.005378
1          0.032267
2          0.035689
3          0.032267
4          0.193600
5          0.214133
6          0.035689
7          0.214133
8          0.236844

Check that the discounted model is a martingale with repsect to an EMM.

>>> S.discount(r).is_martingale(prob_measure=Q(theta=0.2))
True

exercise_time

exercise_time(claim, theta, **kwargs)

Get the exercise time of a claim given an equivalent martingale measure.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose exercise times are to be compute.

required
theta Real

A parameter in the open interval (0, 1) yielding a collection of risk-neutral probabilities of the model.

required

Returns:

Name Type Description
exercise_time StoppingTime

The exercise time of the claim.

Examples:

>>> from sigalg.finance import TrinomialPricingModel, Claim

Define a trinomial pricing model.

>>> S = TrinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     middle_factor=1.0,
...     down_factor=0.9,
...     up_prob=0.7,
...     down_prob=0.2,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Trinomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  121.0
2      100.0  110.0  121.0  108.9
3      100.0  110.0  110.0  121.0
4      100.0  110.0  110.0  110.0
5      100.0  110.0  110.0   99.0
6      100.0  110.0   99.0  108.9
7      100.0  110.0   99.0   99.0
8      100.0  110.0   99.0   89.1
9      100.0  100.0  110.0  121.0
10     100.0  100.0  110.0  110.0
11     100.0  100.0  110.0   99.0
12     100.0  100.0  100.0  110.0
13     100.0  100.0  100.0  100.0
14     100.0  100.0  100.0   90.0
15     100.0  100.0   90.0   99.0
16     100.0  100.0   90.0   90.0
17     100.0  100.0   90.0   81.0
18     100.0   90.0   99.0  108.9
19     100.0   90.0   99.0   99.0
20     100.0   90.0   99.0   89.1
21     100.0   90.0   90.0   99.0
22     100.0   90.0   90.0   90.0
23     100.0   90.0   90.0   81.0
24     100.0   90.0   81.0   89.1
25     100.0   90.0   81.0   81.0
26     100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0  21.0
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0  21.0
4      0.0  0.0  0.0  10.0
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   8.9
7      0.0  0.0  0.0   0.0
8      0.0  0.0  0.0   0.0
9      0.0  0.0  0.0  21.0
10     0.0  0.0  0.0  10.0
11     0.0  0.0  0.0   0.0
12     0.0  0.0  0.0  10.0
13     0.0  0.0  0.0   0.0
14     0.0  0.0  0.0   0.0
15     0.0  0.0  0.0   0.0
16     0.0  0.0  0.0   0.0
17     0.0  0.0  0.0   0.0
18     0.0  0.0  0.0   8.9
19     0.0  0.0  0.0   0.0
20     0.0  0.0  0.0   0.0
21     0.0  0.0  0.0   0.0
22     0.0  0.0  0.0   0.0
23     0.0  0.0  0.0   0.0
24     0.0  0.0  0.0   0.0
25     0.0  0.0  0.0   0.0
26     0.0  0.0  0.0   0.0

Get the exercise time of the call option for a specified parameter corresponding to risk-neutral probabilities.

>>> print(S.exercise_time(claim=euro_call, theta=0.2))
Stopping time 'tau':
       tau
omega
0      3.0
1      3.0
2      3.0
3      3.0
4      3.0
5      inf
6      3.0
7      inf
8      inf
9      3.0
10     3.0
11     inf
12     3.0
13     inf
14     inf
15     inf
16     inf
17     inf
18     3.0
19     inf
20     inf
21     inf
22     inf
23     inf
24     inf
25     inf
26     inf

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   0.0   0.0
3      0.0   0.0   0.0   0.0
4      0.0   0.0   0.0   0.0
5      0.0   0.0   0.0   1.0
6      0.0   0.0   1.0   0.0
7      0.0   0.0   1.0   1.0
8      0.0   0.0   1.0  10.9
9      0.0   0.0   0.0   0.0
10     0.0   0.0   0.0   0.0
11     0.0   0.0   0.0   1.0
12     0.0   0.0   0.0   0.0
13     0.0   0.0   0.0   0.0
14     0.0   0.0   0.0  10.0
15     0.0   0.0  10.0   1.0
16     0.0   0.0  10.0  10.0
17     0.0   0.0  10.0  19.0
18     0.0  10.0   1.0   0.0
19     0.0  10.0   1.0   1.0
20     0.0  10.0   1.0  10.9
21     0.0  10.0  10.0   1.0
22     0.0  10.0  10.0  10.0
23     0.0  10.0  10.0  19.0
24     0.0  10.0  19.0  10.9
25     0.0  10.0  19.0  19.0
26     0.0  10.0  19.0  27.1

Get the exercise time of the put option.

>>> print(S.exercise_time(claim=american_put, theta=0.2))
Stopping time 'tau':
       tau
omega
0      inf
1      inf
2      inf
3      inf
4      inf
5      3.0
6      2.0
7      2.0
8      2.0
9      inf
10     inf
11     3.0
12     inf
13     inf
14     3.0
15     2.0
16     2.0
17     2.0
18     1.0
19     1.0
20     1.0
21     1.0
22     1.0
23     1.0
24     1.0
25     1.0
26     1.0

generate

generate(
    initial_price,
    up_factor,
    middle_factor,
    down_factor,
    up_prob=1 / 3,
    down_prob=1 / 3,
    risk_free_rate=None,
    risk_free_gross_return=None,
    mode="sim",
    n_trajectories=None,
    domain_name=None,
    index=None,
    length=None,
    name="S",
    random_state=None,
)

Generate trajectories of the trinomial pricing model by either exhaustive enumeration or Monte Carlo simulation.

See the Notes section below for the mathematical details.

Parameters:

Name Type Description Default
initial_price Real

The initial price of the asset.

required
up_factor Real

The up-factor of the model.

required
middle_factor Real

The middle-factor of the model.

required
down_factor Real

The down-factor of the model.

required
up_prob Real

The probability of an upward move in the price.

1 / 3
down_prob Real

The probability of an upward move in the price.

1 / 3
risk_free_rate Real | None

The per-period risk-free rate. If None, the risk-free gross return must be given.

None
risk_free_gross_return Real | None

The per-period risk-free gross return. If None, the risk-free rate must be given.

None
mode Literal['enum', 'sim']

Whether to generate trajectories by exhuastive enumeration or Monte Carlo simulation.

'sim'
n_trajectories int | None

The number of trajectories to simulate. If the generation mode is set to enum, this parameter is ignored.

None
index IndexLike | None

The index of the stochastic process. One of index or length must be provided; if both are provided, the length of index must match length.

None
length int | None

The length of the trajectories of the stochastic process. One of index or length must be provided; if both are provided, the length of index must match length.

None
name Hashable

The name of the stochastic process.

"S"
random_state int | Generator | None

An optional random state for reproducibility.

None

Returns:

Name Type Description
info dict[str, object]

A dictionary containing the names of the BinomialPricingModel-specific parameters and their values.

Examples:

>>> from sigalg.finance import TrinomialPricingModel

Given parameters of a trinomial model, generate all length-2 price trajectories in enum mode.

>>> S_0 = 4
>>> u = 1.2
>>> m = 1.1
>>> d = 0.9
>>> p_u = 0.6
>>> p_d = 0.1
>>> r = 0.01
>>> S = TrinomialPricingModel.generate(
...     mode="enum",
...     initial_price=S_0,
...     up_factor=u,
...     middle_factor=m,
...     down_factor=d,
...     up_prob=p_u,
...     down_prob=p_d,
...     risk_free_rate=r,
...     length=2,
... )
>>> print(S)
Trinomial price process 'S':
t         0    1     2
omega
0       4.0  4.8  5.76
1       4.0  4.8  5.28
2       4.0  4.8  4.32
3       4.0  4.4  5.28
4       4.0  4.4  4.84
5       4.0  4.4  3.96
6       4.0  3.6  4.32
7       4.0  3.6  3.96
8       4.0  3.6  3.24

Simulate ten length-2 trajectories in sim mode.

>>> S.n_trajectories = 10
>>> S.random_state = 42
>>> S.mode = "sim"
>>> S.regenerate()
>>> print(S)
Trinomial price process 'S':
t        0    1     2
omega
0      4.0  4.4  5.28
1      4.0  4.4  4.84
2      4.0  4.8  4.32
3      4.0  4.4  4.84
4      4.0  4.8  5.76
5      4.0  4.8  4.32
6      4.0  4.4  4.84
7      4.0  4.8  5.76
8      4.0  4.8  5.76
9      4.0  4.4  4.84

price

price(claim, theta, **kwargs)

Get the risk-neutral price of a claim given an equivalent martingale measure.

Parameters:

Name Type Description Default
claim Claim

The contingent claim to price.

required
theta Real

A parameter in the open interval (0, 1) yielding a collection of risk-neutral probabilities of the model.

required

Returns:

Name Type Description
price Real

The risk-neutral price of the claim.

Examples:

>>> from sigalg.finance import TrinomialPricingModel, Claim

Define a trinomial pricing model.

>>> S = TrinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     middle_factor=1.0,
...     down_factor=0.9,
...     up_prob=0.7,
...     down_prob=0.2,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Trinomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  121.0
2      100.0  110.0  121.0  108.9
3      100.0  110.0  110.0  121.0
4      100.0  110.0  110.0  110.0
5      100.0  110.0  110.0   99.0
6      100.0  110.0   99.0  108.9
7      100.0  110.0   99.0   99.0
8      100.0  110.0   99.0   89.1
9      100.0  100.0  110.0  121.0
10     100.0  100.0  110.0  110.0
11     100.0  100.0  110.0   99.0
12     100.0  100.0  100.0  110.0
13     100.0  100.0  100.0  100.0
14     100.0  100.0  100.0   90.0
15     100.0  100.0   90.0   99.0
16     100.0  100.0   90.0   90.0
17     100.0  100.0   90.0   81.0
18     100.0   90.0   99.0  108.9
19     100.0   90.0   99.0   99.0
20     100.0   90.0   99.0   89.1
21     100.0   90.0   90.0   99.0
22     100.0   90.0   90.0   90.0
23     100.0   90.0   90.0   81.0
24     100.0   90.0   81.0   89.1
25     100.0   90.0   81.0   81.0
26     100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0  21.0
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0  21.0
4      0.0  0.0  0.0  10.0
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   8.9
7      0.0  0.0  0.0   0.0
8      0.0  0.0  0.0   0.0
9      0.0  0.0  0.0  21.0
10     0.0  0.0  0.0  10.0
11     0.0  0.0  0.0   0.0
12     0.0  0.0  0.0  10.0
13     0.0  0.0  0.0   0.0
14     0.0  0.0  0.0   0.0
15     0.0  0.0  0.0   0.0
16     0.0  0.0  0.0   0.0
17     0.0  0.0  0.0   0.0
18     0.0  0.0  0.0   8.9
19     0.0  0.0  0.0   0.0
20     0.0  0.0  0.0   0.0
21     0.0  0.0  0.0   0.0
22     0.0  0.0  0.0   0.0
23     0.0  0.0  0.0   0.0
24     0.0  0.0  0.0   0.0
25     0.0  0.0  0.0   0.0
26     0.0  0.0  0.0   0.0

Get the risk-neutral price of the call option for a specified parameter corresponding to risk-neutral probabilities.

>>> S.price(claim=euro_call, theta=0.2)
13.971579743008329

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   0.0   0.0
3      0.0   0.0   0.0   0.0
4      0.0   0.0   0.0   0.0
5      0.0   0.0   0.0   1.0
6      0.0   0.0   1.0   0.0
7      0.0   0.0   1.0   1.0
8      0.0   0.0   1.0  10.9
9      0.0   0.0   0.0   0.0
10     0.0   0.0   0.0   0.0
11     0.0   0.0   0.0   1.0
12     0.0   0.0   0.0   0.0
13     0.0   0.0   0.0   0.0
14     0.0   0.0   0.0  10.0
15     0.0   0.0  10.0   1.0
16     0.0   0.0  10.0  10.0
17     0.0   0.0  10.0  19.0
18     0.0  10.0   1.0   0.0
19     0.0  10.0   1.0   1.0
20     0.0  10.0   1.0  10.9
21     0.0  10.0  10.0   1.0
22     0.0  10.0  10.0  10.0
23     0.0  10.0  10.0  19.0
24     0.0  10.0  19.0  10.9
25     0.0  10.0  19.0  19.0
26     0.0  10.0  19.0  27.1

Get the risk-neutral price of the put option.

>>> S.price(claim=american_put, theta=0.2)
0.7706511175898927

price_process

price_process(claim, theta, **kwargs)

Get the risk-neutral price process of a claim given an equivalent martingale measure.

Parameters:

Name Type Description Default
claim Claim

The contingent claim whose price process is to be computed.

required
theta Real

A parameter in the open interval (0, 1) yielding a collection of risk-neutral probabilities of the model.

required

Returns:

Name Type Description
price_process StochasticProcess

The risk-neutral price process of the claim.

Examples:

>>> from sigalg.finance import TrinomialPricingModel, Claim

Define a trinomial pricing model.

>>> S = TrinomialPricingModel.generate(
...     initial_price=100,
...     up_factor=1.1,
...     middle_factor=1.0,
...     down_factor=0.9,
...     up_prob=0.7,
...     down_prob=0.2,
...     risk_free_rate=0.05,
...     mode="enum",
...     length=3,
... )
>>> print(S)
Trinomial price process 'S':
t          0      1      2      3
omega
0      100.0  110.0  121.0  133.1
1      100.0  110.0  121.0  121.0
2      100.0  110.0  121.0  108.9
3      100.0  110.0  110.0  121.0
4      100.0  110.0  110.0  110.0
5      100.0  110.0  110.0   99.0
6      100.0  110.0   99.0  108.9
7      100.0  110.0   99.0   99.0
8      100.0  110.0   99.0   89.1
9      100.0  100.0  110.0  121.0
10     100.0  100.0  110.0  110.0
11     100.0  100.0  110.0   99.0
12     100.0  100.0  100.0  110.0
13     100.0  100.0  100.0  100.0
14     100.0  100.0  100.0   90.0
15     100.0  100.0   90.0   99.0
16     100.0  100.0   90.0   90.0
17     100.0  100.0   90.0   81.0
18     100.0   90.0   99.0  108.9
19     100.0   90.0   99.0   99.0
20     100.0   90.0   99.0   89.1
21     100.0   90.0   90.0   99.0
22     100.0   90.0   90.0   90.0
23     100.0   90.0   90.0   81.0
24     100.0   90.0   81.0   89.1
25     100.0   90.0   81.0   81.0
26     100.0   90.0   81.0   72.9

Define a European call option with strike K=100.

>>> K = 100
>>> euro_call = Claim.european_option(model=S, strike=K, type="call", name="euro_call")
>>> print(euro_call)
European option 'euro_call':
t        0    1    2     3
omega
0      0.0  0.0  0.0  33.1
1      0.0  0.0  0.0  21.0
2      0.0  0.0  0.0   8.9
3      0.0  0.0  0.0  21.0
4      0.0  0.0  0.0  10.0
5      0.0  0.0  0.0   0.0
6      0.0  0.0  0.0   8.9
7      0.0  0.0  0.0   0.0
8      0.0  0.0  0.0   0.0
9      0.0  0.0  0.0  21.0
10     0.0  0.0  0.0  10.0
11     0.0  0.0  0.0   0.0
12     0.0  0.0  0.0  10.0
13     0.0  0.0  0.0   0.0
14     0.0  0.0  0.0   0.0
15     0.0  0.0  0.0   0.0
16     0.0  0.0  0.0   0.0
17     0.0  0.0  0.0   0.0
18     0.0  0.0  0.0   8.9
19     0.0  0.0  0.0   0.0
20     0.0  0.0  0.0   0.0
21     0.0  0.0  0.0   0.0
22     0.0  0.0  0.0   0.0
23     0.0  0.0  0.0   0.0
24     0.0  0.0  0.0   0.0
25     0.0  0.0  0.0   0.0
26     0.0  0.0  0.0   0.0

Get the risk-neutral price process of the call option for a specified parameter corresponding to risk-neutral probabilities.

>>> print(S.price_process(claim=euro_call, theta=0.2))
Stochastic process 'X':
t             0          1          2     3
omega
0      13.97158  19.358050  25.761905  33.1
1      13.97158  19.358050  25.761905  21.0
2      13.97158  19.358050  25.761905   8.9
3      13.97158  19.358050  14.809524  21.0
4      13.97158  19.358050  14.809524  10.0
5      13.97158  19.358050  14.809524   0.0
6      13.97158  19.358050   4.661905   8.9
7      13.97158  19.358050   4.661905   0.0
8      13.97158  19.358050   4.661905   0.0
9      13.97158   9.752834  14.809524  21.0
10     13.97158   9.752834  14.809524  10.0
11     13.97158   9.752834  14.809524   0.0
12     13.97158   9.752834   5.238095  10.0
13     13.97158   9.752834   5.238095   0.0
14     13.97158   9.752834   5.238095   0.0
15     13.97158   9.752834   0.000000   0.0
16     13.97158   9.752834   0.000000   0.0
17     13.97158   9.752834   0.000000   0.0
18     13.97158   2.441950   4.661905   8.9
19     13.97158   2.441950   4.661905   0.0
20     13.97158   2.441950   4.661905   0.0
21     13.97158   2.441950   0.000000   0.0
22     13.97158   2.441950   0.000000   0.0
23     13.97158   2.441950   0.000000   0.0
24     13.97158   2.441950   0.000000   0.0
25     13.97158   2.441950   0.000000   0.0
26     13.97158   2.441950   0.000000   0.0

Define an American put option with the same strike.

>>> american_put = Claim.american_option(model=S, strike=K, type="put", name="american_put")
>>> print(american_put)
American option 'american_put':
t        0     1     2     3
omega
0      0.0   0.0   0.0   0.0
1      0.0   0.0   0.0   0.0
2      0.0   0.0   0.0   0.0
3      0.0   0.0   0.0   0.0
4      0.0   0.0   0.0   0.0
5      0.0   0.0   0.0   1.0
6      0.0   0.0   1.0   0.0
7      0.0   0.0   1.0   1.0
8      0.0   0.0   1.0  10.9
9      0.0   0.0   0.0   0.0
10     0.0   0.0   0.0   0.0
11     0.0   0.0   0.0   1.0
12     0.0   0.0   0.0   0.0
13     0.0   0.0   0.0   0.0
14     0.0   0.0   0.0  10.0
15     0.0   0.0  10.0   1.0
16     0.0   0.0  10.0  10.0
17     0.0   0.0  10.0  19.0
18     0.0  10.0   1.0   0.0
19     0.0  10.0   1.0   1.0
20     0.0  10.0   1.0  10.9
21     0.0  10.0  10.0   1.0
22     0.0  10.0  10.0  10.0
23     0.0  10.0  10.0  19.0
24     0.0  10.0  19.0  10.9
25     0.0  10.0  19.0  19.0
26     0.0  10.0  19.0  27.1

Get the risk-neutral price process of the put option.

>>> print(S.price_process(claim=american_put, theta=0.2))
Stochastic process 'X':
t             0         1          2     3
omega
0      0.770651   0.06576   0.000000   0.0
1      0.770651   0.06576   0.000000   0.0
2      0.770651   0.06576   0.000000   0.0
3      0.770651   0.06576   0.047619   0.0
4      0.770651   0.06576   0.047619   0.0
5      0.770651   0.06576   0.047619   1.0
6      0.770651   0.06576   1.000000   0.0
7      0.770651   0.06576   1.000000   1.0
8      0.770651   0.06576   1.000000  10.9
9      0.770651   0.68254   0.047619   0.0
10     0.770651   0.68254   0.047619   0.0
11     0.770651   0.68254   0.047619   1.0
12     0.770651   0.68254   0.476190   0.0
13     0.770651   0.68254   0.476190   0.0
14     0.770651   0.68254   0.476190  10.0
15     0.770651   0.68254  10.000000   1.0
16     0.770651   0.68254  10.000000  10.0
17     0.770651   0.68254  10.000000  19.0
18     0.770651  10.00000   1.000000   0.0
19     0.770651  10.00000   1.000000   1.0
20     0.770651  10.00000   1.000000  10.9
21     0.770651  10.00000  10.000000   1.0
22     0.770651  10.00000  10.000000  10.0
23     0.770651  10.00000  10.000000  19.0
24     0.770651  10.00000  19.000000  10.9
25     0.770651  10.00000  19.000000  19.0
26     0.770651  10.00000  19.000000  27.1

replicating_portfolio

replicating_portfolio(*args, **kwargs)

Pass.

risk_neutral_probs

risk_neutral_probs(theta, **kwargs)

Get the risk-neutral probabilities of the model given a parameter.

Parameters:

Name Type Description Default
theta Real

A real number in the open interval (0, 1) parameterizing the risk-neutral probabilities.

required

Returns:

Name Type Description
risk_neutral_probs tuple[Real, Real, Real]

The risk neutral probabilities as a tuple (q_u, q_m, q_d), where q_u is the risk-neutral probability of an up move, q_m is the risk-neutral probability of a middle move, and q_d is the risk-neutral probability of a down move.

Examples:

>>> from sigalg.finance import TrinomialPricingModel

Define the parameters of a trinomial pricing model.

>>> S_0 = 4
>>> r = 0.01
>>> p_u = 0.6
>>> p_d = 0.1
>>> u = 1.2
>>> m = 1.1
>>> d = 0.9
>>> T = 2

Exhaustively generate all price trajectories and print them.

>>> S = TrinomialPricingModel.generate(
...     initial_price=S_0,
...     risk_free_rate=r,
...     up_prob=p_u,
...     down_prob=p_d,
...     up_factor=u,
...     middle_factor=m,
...     down_factor=d,
...     mode="enum",
...     length=T,
... )
>>> print(S)
Trinomial price process 'S':
t        0    1     2
omega
0      4.0  4.8  5.76
1      4.0  4.8  5.28
2      4.0  4.8  4.32
3      4.0  4.4  5.28
4      4.0  4.4  4.84
5      4.0  4.4  3.96
6      4.0  3.6  4.32
7      4.0  3.6  3.96
8      4.0  3.6  3.24

The risk-neutral probabilities are a one-parameter family of probabilities. Get these probabilities for a specific parameter.

>>> S.risk_neutral_probs(theta=0.42)
(0.15400000000000003, 0.31899999999999973, 0.5270000000000001)