API Reference
finance
Module containing components for financial mathematics, including derivative pricing models.
AsianOption
Bases: Claim
Model an Asian option contingent claim.
The Asian option is a claim comes in two types: call and put. The payoff of an Asian call option is given by
while the payoff of an Asian put option is given by
where \(\bar{S}_T\) is the average underlying asset price over the option's life and \(K\) is the strike price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pricing_model
|
PricingModel
|
A pricing model representing the underlying asset price dynamics. |
required |
strike
|
Real
|
The strike price of the Asian option. |
required |
option_type
|
str
|
The type of the Asian option. It can be either "call" or "put". |
"call"
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the strike price is not a positive real number, or if the pricing model is not a PricingModel, or if the option type is not "call" or "put". |
payoff
property
payoff
Return the payoff of the Asian option.
Returns:
| Name | Type | Description |
|---|---|---|
option |
RandomVariable
|
A random variable representing the payoff of the Asian option. |
BinomialPricingModel
Bases: PricingModel
Binomial pricing model for a risky asset.
This class produces a binomial model for the price proccess \(S_t\) of a risky asset, often referred to generically as a stock. Beginning from its initial price \(S_0\), and given a time horizon \(T\), this model supposes that the price process evolves according to the following dynamics:
for each \(t=0,1,\ldots,T-1\), where \(Z_t\) is a random variable that takes the value \(u>1\) with some probability \(p\) and the value \(d = 1/u\) with probability \(1-p\). The factors \(u\) and \(d\) are called the up-factor and down-factor, respectively.
The risky asset is assumed to be traded in a market along with a non-risky asset with gross return \(R = 1 + r\) at each time step, where \(r\) is the risk-free rate. The non-risky asset is often conceptualized as a bank account with per-period interest rate \(r\).
The probability \(p\) is the real-world probability that drives the price process of the stock. However, under the no-arbitrage condition \(d < R< u\), a second probability \(q\), called the risk-neutral probability, may be defined via the equation
This risk-neutral probability is the key component in pricing various contingent claims using the binomial model.
As a subclass of StochasticProcess, an instance of BinomialPricingModel carries a probability_measure attribute, which corresponds to the real-world measure. The risk-neutral measure is accessible via the risk_neutral_measure property.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
initial_price
|
Real
|
The initial price of the risky asset. |
required |
up_factor
|
Real
|
The up-factor of the model, which must be greater than 1. |
required |
risk_free_rate
|
Real
|
The risk-free rate of the non-risky asset, which must be positive. |
required |
time
|
Time | None
|
The time index for the pricing model. |
None
|
name
|
Hashable | None
|
The name of the stochastic process. |
'S'
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If any of the parameters are of the wrong type or do not satisfy the required conditions. |
ValueError
|
If the no-arbitrage condition is violated. |
Examples:
>>> from sigalg.core import Time
>>> from sigalg.finance import BinomialPricingModel
>>> S_0 = 100
>>> u = 1.1
>>> p = 0.7
>>> r = 0.01
>>> T = 3
>>> time = Time.discrete(length=T)
>>> S = BinomialPricingModel(
... initial_price=S_0,
... up_factor=u,
... up_prob=p,
... risk_free_rate=r,
... time=time,
... ).from_enumeration()
>>> S
Stochastic process 'S':
time 0 1 2 3
trajectory
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
driving_process
property
driving_process
Return the driving process of the binomial pricing model.
The driving process is an IID process \(Z_t\) representing the up and down movements of the underlying asset in the binomial model. It takes the value \(u\) with probability \(p\) and the value \(d\) with probability \(1-p\), where \(u\) is the up-factor, \(d\) is the down-factor, and \(p\) is the real-world probability of an up move. The driving process is defined for times \(t=1,2,\ldots,T\), where \(T\) is the final time of the model.
This property should only be used for small values of \(T\), as the number of price trajectories is equal to \(2^T\).
Returns:
| Name | Type | Description |
|---|---|---|
driving_process |
StochasticProcess
|
The driving process of the binomial pricing model. |
risk_neutral_measure
property
risk_neutral_measure
Later.
from_enumeration
from_enumeration(length=None, enum_mode='sparse', **kwargs)
Generate price trajectories of the binomial pricing model via enumeration.
Suppose that \(S_t\) is the price process of the underlying asset, and that \(u\) and \(d\) are the up- and down-factors of the model, respectively. Then \(S_t\) is a random walk on the set of prices
At a fixed time horizon \(T\), the final price \(S_T\) takes one of the \(T+1\) values in the set
There are exactly \(\binom{T}{n}\) many random walks (i.e., price trajectories) that terminate at the final price \(S_T = S_0 u^{n} d^{T-n}\), and thus a total of \(2^T = \sum_{n=0}^T \binom{T}{n}\) many random walks that end at some final price.
This method enumerates these price trajectories in one of two modes: either dense mode or sparse mode. In dense mode, the method enumerates all \(2^T\) price trajectories of the model. In sparse mode, the method enumerates only \(T+1\) price trajectories of the model, which are of the special forms:
The dense mode of enumeration should only be used for small values of \(T\), as the number of price trajectories grows exponentially in \(T\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
length
|
int | None
|
The length of the enumeration, which must be a positive integer. If |
None
|
enum_mode
|
str
|
The mode of enumeration, which must be either "sparse" or "dense". See above for details. |
"sparse"
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
replicating_portfolio
replicating_portfolio(claim)
Compute the replicating portfolio for a given contingent claim.
The core idea of a replicating portfolio is this: Suppose that an individual sells a contingent claim on an underlying asset (generically called an underlying). The seller accepts a premium from the buyer for the claim at time \(t=0\), and then at some specified maturity time \(t=T\), the seller must pay the exercise value of the claim to the buyer. The claim is a derivative, in the sense that its value depends on (or derives from) the price of the underlying. The seller is thus interested in hedging their short position on the claim against an increase in the price of the underlying, which would increase the exercise value of the claim that the seller would owe the buyer.
The underlying asset is assumed to be traded in a market that includes a bank account with risk-free, per-period interest rate \(r\). The seller's hedging strategy is to trade in the underlying asset itself, as well as hold a cash position at the bank, so that when the contingent claim matures, the seller's portfolio will cover the exercise value owed to the buyer.
The replicating portfolio thus consists of a pair \((B_t,N_t)\) of processes, indexed \(t=0,1,\ldots,T-1\), where \(B_t\) represents the cash position at time \(t\), and \(N_t\) counts the number of units of the underlying held in the portfolio at time \(t\). A third process \(V_t\) represents the total value of the portfolio, given by
where \(S_t\) is the price of the underlying at time \(t\). A positive value of \(B_t\) represents money held in the bank accruing interest for the seller at rate \(r\), while a negative value represents a loan on which the seller pays interest at rate \(r\). A positive value of \(N_t\) represents a long position on the underlying, while a negative value represents a short position.
The replicating portfolio is self-financing, in the sense that
for each \(t=1,2,\ldots,T\). The right-hand side of this equation represents the evolution of the value of the portfolio over the time interval \([t-1,t]\), in which the amount \(B_{t-1}\) in the bank accrues interest at rate \(r\) and the price of the underlying changes from \(S_{t-1}\) to \(S_t\). This equation says that this evolved value of the old portfolio is equal to the value \(V_t\) of the new portfolio at time \(t\).
The existence of the replicating portfolio also allows us to determine a fair, "risk-neutral" premium for the contingent claim paid by the buyer. Under the no-arbitrage assumption, this premium should coincide with the initial price
of the replicating portfolio.
Recall that from_enumeration method generates price trajectories in one of two modes: either dense mode or sparse mode. In dense mode, the method enumerates all \(2^T\) price trajectories of the model. In sparse mode, the method enumerates only the following canonical \(T+1\) price trajectories:
where \(u\) and \(d\) are the up- and down-factors of the model. If the price trajectories have been enumerated in dense mode, then the replicating portfolio is computed via backward induction through the full binomial tree of price trajectories. If the price trajectories have been enumerated in sparse mode, and if the price process of the claim is path-independent, then the replicating portfolio is computed via backward induction through the reduced binomial tree of \(T+1\) price trajectories described above.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
claim
|
Claim
|
The contingent claim for which to compute the replicating portfolio. The payoff of the claim must be defined on the same domain as the price process of the underlying asset, and the price trajectories of the underlying asset must have been enumerated before calling this method. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the claim is not an instance of |
ValueError
|
If the price trajectories have not been enumerated. |
Returns:
| Type | Description |
|---|---|
bank_value, underlying_units, portfolio_value, risk_neutral_price : tuple[StochasticProcess, StochasticProcess, StochasticProcess, Real]
|
A tuple containing the bank account process, the underlying units process, the total portfolio value process, and the risk-neutral price of the claim. |
Examples:
>>> from sigalg.core import Time
>>> from sigalg.finance import AsianOption, BinomialPricingModel, EuropeanOption
>>> S_0 = 100
>>> u = 1.1
>>> p = 0.7
>>> r = 0.01
>>> T = Time.discrete(length=3)
>>> S = BinomialPricingModel(
... initial_price=S_0, up_factor=u, up_prob=p, risk_free_rate=r, time=T
... )
>>> S.from_enumeration(enum_mode="dense")
Stochastic process 'S':
time 0 1 2 3
trajectory
0 100 110.000000 121.000000 133.100000
1 100 110.000000 121.000000 110.000000
2 100 110.000000 100.000000 110.000000
3 100 110.000000 100.000000 90.909091
4 100 90.909091 100.000000 110.000000
5 100 90.909091 100.000000 90.909091
6 100 90.909091 82.644628 90.909091
7 100 90.909091 82.644628 75.131480
>>> K = 100
>>> asian_call = AsianOption(pricing_model=S, strike=K, option_type="call")
>>> B, N, V, price = S.replicating_portfolio(claim=asian_call)
>>> print(B)
Stochastic process 'bank_account_value':
time 0 1 2
trajectory
0 -38.134572 -46.564062 -17.079208
1 -38.134572 -46.564062 -17.079208
2 -38.134572 -46.564062 -22.277228
3 -38.134572 -46.564062 -22.277228
4 -38.134572 -0.560775 -1.071536
5 -38.134572 -0.560775 -1.071536
6 -38.134572 -0.560775 0.000000
7 -38.134572 -0.560775 0.000000
>>> print(N)
Stochastic process 'underlying_units':
time 0 1 2
trajectory
0 0.42436 0.497525 0.250000
1 0.42436 0.497525 0.250000
2 0.42436 0.497525 0.250000
3 0.42436 0.497525 0.250000
4 0.42436 0.006853 0.011905
5 0.42436 0.006853 0.011905
6 0.42436 0.006853 -0.000000
7 0.42436 0.006853 -0.000000
>>> print(V)
Stochastic process 'portfolio_value':
time 0 1 2 3
trajectory
0 4.301408 8.163660 13.170792 16.025000
1 4.301408 8.163660 13.170792 10.250000
2 4.301408 8.163660 2.722772 5.000000
3 4.301408 8.163660 2.722772 0.227273
4 4.301408 0.062246 0.118940 0.227273
5 4.301408 0.062246 0.118940 -0.000000
6 4.301408 0.062246 -0.000000 -0.000000
7 4.301408 0.062246 -0.000000 -0.000000
>>> print(price)
4.301408148315952
>>> S.from_enumeration(enum_mode="sparse")
Stochastic process 'S':
time 0 1 2 3
trajectory
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
>>> K = 100
>>> euro_call = EuropeanOption(pricing_model=S, strike=K, option_type="call")
>>> B, N, V, price = S.replicating_portfolio(claim=euro_call)
>>> print(B)
Stochastic process 'bank_account_value':
time 0 1 2
trajectory
0 -50.150931 -73.822294 -99.009901
1 -50.150931 -24.674118 -47.147572
2 -50.150931 -24.674118 -0.000000
3 -50.150931 -24.674118 -0.000000
>>> print(N)
Stochastic process 'underlying_units':
time 0 1 2
trajectory
0 0.587304 0.797939 1.00000
1 0.587304 0.301542 0.52381
2 0.587304 0.301542 0.00000
3 0.587304 0.301542 0.00000
>>> print(V)
Stochastic process 'portfolio_value':
time 0 1 2 3
trajectory
0 8.579463 13.950993 21.990099 33.1
1 8.579463 2.738827 5.233380 10.0
2 8.579463 2.738827 -0.000000 -0.0
3 8.579463 2.738827 -0.000000 -0.0
>>> print(price)
8.57946313365138
Claim
Bases: ABC
Abstract base class for various types of contingent claims.
payoff
abstractmethod
property
payoff
Return the payoff of the claim as a random variable.
EuropeanOption
Bases: Claim
Model a European option contingent claim.
The European option is a claim comes in two types: call and put. The payoff of a European call option is given by
while the payoff of a European put option is given by
where \(S_T\) is the underlying asset price at maturity and \(K\) is the strike price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pricing_model
|
PricingModel
|
A pricing model representing the underlying asset price dynamics. |
required |
strike
|
Real
|
The strike price of the European option. |
required |
option_type
|
str
|
The type of the European option. It can be either "call" or "put". |
"call"
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the strike price is not a positive real number, or if the pricing model is not a PricingModel, or if the option type is not "call" or "put". |
payoff
property
payoff
Return the payoff of the European option.
Returns:
| Name | Type | Description |
|---|---|---|
option |
RandomVariable
|
A random variable representing the payoff of the European option. |