Full documentation is available at https://option-combos.readthedocs.io/

This package computes Black Scholes options values and Greeks for options and option combos with a number of valuable features:

  • The functions cover a comprehensive set of Greeks:

    • The first order Greeks include (a) several variants of delta including delta driftless, delta forward and delta dual, (b) rho’s with respect to domestic and foreign interest rates, (c) theta per day and vega per percentage point change in volatility.

    • Important second order Greeks including gamma, gamma dual, vanna, volga and charm

    • The most useful third order Greek, color

  • Since the asset is allowed to pay a continuous dividend yield, foreign currency options, options on futures and options on stock indices are covered.

  • Values and Greeks can be computed for an array of options (using a Pandas DataFrame).

  • The package handles a portfolio of options (option combinations) where different options are held long or short positions with different weights. The aggregate value and Greeks can be computed for the entire portfolio.

  • Option portfolios can contain forward contracts and zero coupon bonds. For example, a portfolio might include self financing strategies like buying a call option and investing the present value of the exercise price in a zero coupon bond.

  • It is very easy to create common option combinations. For example, a straddle can be created in a single line as straddle = combo.call(K=100) + combo.put(K=100) and a butterfly can be created as butterfly = combo.call(K=90) + combo.call(K=110) - 2 * combo.call(K=100). This illustrates the following features enabled by operator overloading:

    • Option combinations can be created by “adding” two options (combos)

    • Short options are created by using a negative sign

    • Weights can be assigned by simply multiplying an option (combo) by the weight.

  • Plotting functions are provided to plot payoffs, profits, values and Greeks of various options (combos).

    • Multiple Greeks of a single combo can be plotted on a single graph. For example, the gamma, vega and theta of a butterfly can be overlaid in a single plot.

    • Different things can be plotted in different plots in a grid in the same figure. For example, the payoff and profit of a strangle can be shown in one plot, and the delta in a separate plot by the side.

    • The same Greek can be plotted for different combos in a single plot. This allows, for example, the gamma of a straddle and a strangle to be compared in a single plot.

  • Interactive plot that includes sliders for changing the strikes of each option. For example, an interactive plot of a butterfly can help choose the high, mid and low strikes to achieve a desired option price or gamma/vega/theta profile.

Basic Black Scholes

option_combos.GBS.mywhere(condition, x, y)

same as numpy.where except it works with scalars as well

This function uses numpy.where if numpy array is received else it uses a simple if else

class option_combos.GBS.GBS(S=None, K=None, sigma=None, ttm=None, r=None, q=None, optType=None)

A Black Scholes Option class

Important methods include ‘value’ for option value as well as various Greeks like ‘delta’, ‘gamma’, ‘volga’, ‘vanna’

Parameters:
  • S (float or numpy array) – The current market price of the underlying This can be changed subsequently using the set_S method

  • K (float or numpy array) – The strike price of the option

  • sigma (float or numpy array) – The annualized volatility in decimal (0.25 for 25%)

  • ttm (float or numpy array) – Time to maturity in years

  • r (float or numpy array) – The (domestic) risk free rate This is continuously compounded annualized, and in decimal

  • q (float or numpy array, optional) – The dividend yield or foreign risk free rate This is continuously compounded annualized, and in decimal

  • optType (instrument.call [+1] or instrument.put [-1], optional) – Whether call or put option

Notes

If any of the parameters is a numpy array, the class instance behaves like an array of options and all its methods return a numpy array of values.

pre_compute()

Precompute elements of option pricing and greek formulas

Called from __init__, set_S and set_X. Should be called after changing any option parameter. The following are precomputed: d1, d2, N(+/-d1), N(+/-d2) DFr and DFq (the discount factors) Fwd (forward price)

set_S(S)

Change market price of underlying. Then call pre_compute

set_K(K)

Change strike price of option. Then call pre_compute

set_ttm(ttm)

Change maturity of option. Then call pre_compute

set_sigma(sigma)

Change volatility of option. Then call pre_compute

set_r(r)

Change risk free rate of option. Then call pre_compute

set_q(q)

Change dividend yield of option. Then call pre_compute

value()

Compute the option value (NPV is an alias for value)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().value().round(10)
2.423056836
>>> GBS(S=101, ttm=1).NPV().round(10)
9.823259516
>>> sigmas = numpy.array([15, 20, 25]) / 100
>>> GBS(S=101, sigma=sigmas, ttm=1).value().round(8)
... 
array([  7.94559796,   9.82325952,  11.71625574])
NPV()

Compute the option value (NPV is an alias for value)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().value().round(10)
2.423056836
>>> GBS(S=101, ttm=1).NPV().round(10)
9.823259516
>>> sigmas = numpy.array([15, 20, 25]) / 100
>>> GBS(S=101, sigma=sigmas, ttm=1).value().round(8)
... 
array([  7.94559796,   9.82325952,  11.71625574])
payoff(ST=None)

Compute the option payoff

Parameters:

ST (float or numpy array or None (for self.S)) – The market price of the underlying at maturity

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> prices = numpy.array([99, 100, 101])
>>> GBS(S=101, ttm=1).payoff(prices)
array([0, 0, 1])
>>> GBS(S=101, ttm=1, optType=instrument.put).payoff(prices)
array([1, 0, 0])
profit(ST=None)

Compute the option profit

Parameters:

ST (float or numpy array) – The market price of the underlying at maturity

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> prices = numpy.array([99, 100, 101])
>>> GBS(S=101, ttm=1).profit(prices).round(6)
array([-9.82326, -9.82326, -8.82326])
>>> GBS(S=101, ttm=1, optType=instrument.put).profit(prices).round(6)
array([-4.946136, -5.946136, -5.946136])
Delta()

Compute the option delta (dV/dS)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Delta().round(8)
0.60558311
DeltaFwd()

Compute the option delta dV/dF where F is the forward price

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).DeltaFwd().round(8)
0.58768543
DeltaDriftless()

Compute the option delta (dV/dS) without drift

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).DeltaDriftless().round(8)
0.6178167
DeltaDual()

Compute the option dual delta (dV/dK)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).DeltaDual().round(8)
-0.51340635
Theta()

Compute the option theta (dV/dt). Divide by 365 to get daily theta. Note t = -ttm

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Theta().round(8)
-5.11977695
Theta_daily()

Compute the option theta (dV/dt) with t in days not years. Note t = -ttm

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Theta_daily().round(8)
-0.01402679
Vega()

Compute the option vega (dV/dsigma). Divide by 100 to get vega per 1% change in sigma

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().Vega().round(8)
11.4673916
Vega_percent()

Compute the option vega (dV/dsigma) per 1% change in sigma

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().Vega_percent().round(8)
0.11467392
RhoD()

Compute the option rho (dV/dr). Divide by 100 to get RhoD per 1% change in r

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().RhoD().round(8)
4.19712579
RhoF()

Compute the option foreign rho or psi (dV/dq). Divide by 100 to get RhoF per 1% change in q.

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().RhoF().round(8)
-4.39904719
Gamma()

Compute the option gamma (d^2V/dS^2)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Gamma().round(8)
0.0185081
GammaDual()

Compute the option dual gamma (d^2V/dK^2)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).GammaDual().round(8)
0.01888012
Charm()

Compute the option charm (d^2V / dS dt) or (d delta / dt) or (d theta / dS). Note t = -ttm

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Charm().round(8)
-0.02532113
Vanna()

Compute the option vanna (d^2V / dsigma dS) or (d vega / d dS) or (d delta / d sigma)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Vanna().round(8)
-0.1864676
Volga()

Compute the option volga (d^2V/dsigma^2)

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS(S=101, ttm=1).Volga().round(8)
5.6452911
Color()

Compute the option color (d^3V / dttm dS^2) or (d gamma / d ttm). Note this is ttm not t.

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().Color().round(8)
-0.41635232
option_combos.GBS.GBSImplied(price, S=None, K=None, ttm=None, r=None, q=None, optType=None)

Compute Black Scholes implied volatility

Parameters:
  • P (option price (premium)) –

  • S (float or numpy array) – The current market price of the underlying This can be changed subsequently using the set_S method

  • K (float or numpy array) – The strike price of the option

  • ttm (float or numpy array) – Time to maturity in years

  • r (float or numpy array) – The (domestic) risk free rate This is continuously compounded annualized, and in decimal

  • q (float or numpy array, optional) – The dividend yield or foreign risk free rate This is continuously compounded annualized, and in decimal

  • optType (instrument.call [+1] or instrument.put [-1], optional) – Whether call or put option

Return type:

float

Examples

>>> 100 * round(GBSImplied(price=3), 6)
25.0308

Extended Black Scholes with bonds and forwards

class option_combos.GBSx.GBSx(S=None, K=None, sigma=None, ttm=None, r=None, q=None, instrumentType=None)

An extended Black Scholes class that includes bond and forward/futures

Modifies methods like ‘NPV’, ‘delta’, ‘gamma’, ‘volga’, ‘vanna’ inherited from GBS to handle bond and forward/futures

Parameters:
  • S (float or numpy array) – The current market price of the underlying

  • K (float or numpy array) – The strike price of the option

  • sigma (float or numpy array) – The annualized volatility in decimal (0.25 for 25%)

  • ttm (float or numpy array) – Time to maturity in years

  • r (float or numpy array) – The (domestic) risk free rate This is continuously compounded annualized, and in decimal

  • q (float or numpy array, optional) – The dividend yield or foreign risk free rate This is continuously compounded annualized, and in decimal

  • instrumentType (int) –

    • instrument.call: call option

    • instrument.put: put option

    • instrument.bond: zero coupon face value=K, maturity=ttm

    • instrument.forward: forward contract to buy at K

    • instrument.exposure: an unhedged exposure

      (for example input purchase) this is a long or short zero strike call except that no premium has been received only profit() method is modified for this

value()

Compute the instrument value (NPV is an alias for value)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(K=100, ttm=1, r=numpy.array([0, 0.05, 0.20]),
...      instrumentType=instrument.bond
...      ).value().round(6) 
array([100.      ,  95.122942,  81.873075])
>>> GBSx(K=numpy.array([90, 100, 110]), ttm=1,
...      instrumentType=instrument.forward
...      ).value().round(6) 
array([12.409219,  2.896925, -6.615369])
>>> GBSx(K=numpy.array([90, 100, 110]), ttm=1,
...      instrumentType=instrument.exposure
...      ).value().round(6) 
array([0,  0, 0])
NPV()

Compute the instrument value (NPV is an alias for value)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(K=100, ttm=1, r=numpy.array([0, 0.05, 0.20]),
...      instrumentType=instrument.bond
...      ).value().round(6) 
array([100.      ,  95.122942,  81.873075])
>>> GBSx(K=numpy.array([90, 100, 110]), ttm=1,
...      instrumentType=instrument.forward
...      ).value().round(6) 
array([12.409219,  2.896925, -6.615369])
>>> GBSx(K=numpy.array([90, 100, 110]), ttm=1,
...      instrumentType=instrument.exposure
...      ).value().round(6) 
array([0,  0, 0])
payoff(ST=None)

Compute the portfolio payoff

Parameters:

ST (float or numpy array or None (for self.S)) – The market price of the underlying at maturity

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> prices = numpy.array([99, 100, 101])
>>> GBSx(S=101, ttm=1).payoff(prices)
array([0, 0, 1])
>>> GBSx(instrumentType=instrument.bond).payoff()
100
>>> GBSx(instrumentType=instrument.forward).payoff(110)
10
profit(ST=None)

Compute the portfolio profit

Parameters:

ST (float or numpy array or None (for self.S)) – The market price of the underlying at maturity

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> prices = numpy.array([99, 100, 101])
>>> GBSx(S=101, ttm=1).profit(prices).round(6)
array([-9.82326, -9.82326, -8.82326])
>>> GBSx(S=101, ttm=1, instrumentType=instrument.put).profit(
...      prices).round(6)
array([-4.946136, -5.946136, -5.946136])
Delta()

Compute the portfolio delta (dV/dS)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Delta().round(8)
0.60558311
>>> GBSx(instrumentType=instrument.forward).Delta().round(6)
0.998335

Bond has zero delta >>> GBSx(instrumentType=instrument.bond).Delta() 0

DeltaFwd()

Compute the portfolio delta dV/dF where F is the forward price

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(instrumentType=instrument.forward).DeltaFwd().round(6)
0.995842
>>> GBSx(S=101, ttm=1).DeltaFwd().round(8)
0.58768543
DeltaDriftless()

Compute the portfolio delta (dV/dS) without drift

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).DeltaDriftless().round(8)
0.6178167

Driftless delta of forward is exactly 1

>>> GBSx(instrumentType=instrument.forward).DeltaDriftless()
1
DeltaDual()

Compute the portfolio dual delta (dV/dK)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).DeltaDual().round(8)
-0.51340635
Theta()

Compute the portfolio theta (dV/dt).

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Theta().round(8)
-5.11977695

Most Greeks of a bond are zero, but theta is non zero

>>> GBSx(instrumentType=instrument.bond).Theta().round(6)
4.97921
Theta_daily()

Compute the option theta (dV/dt) with t in days not years. Note t = -ttm

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Theta_daily().round(8)
-0.01402679
Vega()

Compute the option vega (dV/dsigma). Divide by 100 to get vega per 1% change in sigma

Return type:

float or numpy array (depending on the GBS inputs)

Examples

>>> GBS().Vega().round(8)
11.4673916

Forward has zero vega

>>> GBSx(instrumentType=instrument.forward).Vega()
0
Vega_percent()

Compute the option vega (dV/dsigma) per 1% change in sigma

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBS().Vega_percent().round(8)
0.11467392
RhoD()

Compute the option rho (dV/dr). Divide by 100 to get RhoD per 1% change in r

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx().RhoD().round(8)
4.19712579
RhoF()

Compute the option foreign rho or psi (dV/dq). Divide by 100 to get RhoF per 1% change in q.

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx().RhoF().round(8)
-4.39904719
Gamma()

Compute the portfolio gamma (d^2V/dS^2)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Gamma().round(8)
0.0185081

Forward has zero gamma

>>> GBSx(instrumentType=instrument.forward).Gamma()
0
GammaDual()

Compute the portfolio dual gamma (d^2V/dK^2)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).GammaDual().round(8)
0.01888012
Charm()

Compute the portfolio charm (d^2V / dS dt) or (d delta / dt) or (d theta / dS). Note t = -ttm

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Charm().round(8)
-0.02532113
Vanna()

Compute the portfolio vanna (d^2V / dsigma dS) or (d vega / d dS) or (d delta / d sigma)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Vanna().round(8)
-0.1864676
Volga()

Compute the portfolio volga (d^2V/dsigma^2)

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx(S=101, ttm=1).Volga().round(8)
5.6452911
Color()

Compute the portfolio color (d^3V / dttm dS^2) or (d gamma / d ttm). Note this is ttm not t.

Return type:

float or numpy array (depending on the GBSx inputs)

Examples

>>> GBSx().Color().round(8)
-0.41635232
>>> GBSx(instrumentType=instrument.forward).Color()
0

Option Portfolios

class option_combos.portfolio.option_portfolio(S, K, sigma, ttm, r, q=0, instrumentType=1, weight=1)

A Black Scholes Option Portfolio class

Modifies methods like ‘NPV’, ‘delta’, ‘gamma’, ‘volga’, ‘vanna’ inherited from GBSx to compute the value for the portfolio

Parameters:
  • S (float or numpy array) – The current market price of the underlying

  • K (float or numpy array) – The strike price of the option

  • sigma (float or numpy array) – The annualized volatility in decimal (0.25 for 25%)

  • ttm (float or numpy array) – Time to maturity in years

  • r (float or numpy array) – The (domestic) risk free rate This is continuously compounded annualized, and in decimal

  • q (float or numpy array, optional) – The dividend yield or foreign risk free rate This is continuously compounded annualized, and in decimal

  • instrumentType (instrument.call, instrument.put etc.) – Whether call or put option or other instrument

  • weight (float or numpy array) – Number of options in the portfolio (long if positive, short if negative)

Notes

It is intended that one or all of the parameters is a numpy array. Otherwise, the base class GBSx should be adequate

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])

This portfolio is used in all the examples below for this class

value()

Compute the portfolio value (NPV is an alias for value)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.value().round(6)
25.804862

Verify by taking each option separately

>>> p.weight
[2, 1]
>>> GBSx.value(p).round(6)
array([8.918504, 7.967853])
NPV()

Compute the portfolio value (NPV is an alias for value)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.value().round(6)
25.804862

Verify by taking each option separately

>>> p.weight
[2, 1]
>>> GBSx.value(p).round(6)
array([8.918504, 7.967853])
payoff(ST=None)

Compute the portfolio payoff

Parameters:

ST (float or numpy array or None (for self.S)) – The market price of the underlying at maturity

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.payoff()
2

Verify by taking each option separately

>>> p.weight
[2, 1]
>>> GBSx.payoff(p)
array([1, 0])
profit(ST=None)

Compute the portfolio profit

Parameters:

ST (float or numpy array or None (for self.S)) – The market price of the underlying at maturity

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.profit(ST=110).round(6)
5.195138

Verify by taking each option separately

>>> p.weight
[2, 1]
>>> (GBSx.payoff(p, ST=110) - GBSx.value(p)).round(6)
array([2.081496, 1.032147])
Delta()

Compute the portfolio delta (dV/dS)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Delta().round(6)
1.698643

Verify by taking each option separately

>>> p.weight
[2, 1]
>>> GBSx.Delta(p).round(6)
array([0.579358, 0.539926])
DeltaFwd()

Compute the portfolio delta dV/dF where F is the forward price

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.DeltaFwd().round(6)
1.681741
DeltaDriftless()

Compute the portfolio delta (dV/dS) without drift

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.DeltaDriftless().round(6)
1.698643
DeltaDual()

Compute the portfolio dual delta (dV/dK)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.DeltaDual().round(6)
-1.44594
Theta()

Compute the portfolio theta (dV/dt).

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Theta().round(6)
-13.230481
Theta_daily()

Compute the portfolio theta (dV/dt). t is in days not years

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Theta_daily().round(6)
-0.036248
Vega()

Compute the option vega (dV/dsigma). Divide by 100 to get vega per 1% change in sigma

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Vega().round(6)
117.898867
Vega_percent()

Compute the option vega (dV/dsigma) per 1% change in sigma

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Vega_percent().round(6)
1.178989
RhoD()

Compute the option rho (dV/dr). Divide by 100 to get RhoD per 1% change in r

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.RhoD().round(6)
144.059404
RhoF()

Compute the portfolio foreign rho or psi (dV/dq).

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.RhoF().round(6)
-169.864267
Gamma()

Compute the portfolio gamma (d^2V/dS^2)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Gamma().round(6)
0.058949
GammaDual()

Compute the portfolio dual gamma (d^2V/dK^2)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.GammaDual().round(6)
0.059352
Charm()

Compute the portfolio charm (d^2V / dS dt) or (d delta / dt) or (d theta / dS). Note t = -ttm

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Charm().round(6)
-0.078649
Vanna()

Compute the portfolio vanna (d^2V / dsigma dS) or (d vega / d dS) or (d delta / d sigma)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Vanna().round(6)
0.196994
Volga()

Compute the portfolio volga (d^2V/dsigma^2)

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Volga().round(6)
-5.835487
Color()

Compute the portfolio color (d^3V / dttm dS^2) or (d gamma / d ttm). Note this is ttm not t.

Examples

>>> p = option_portfolio(S=100, K=array([99, 101]), sigma=0.2,
...     ttm=1, r=0.01, q=0, weight=[2, 1])
>>> p.Color().round(6)
-0.030064

Option Combos

class option_combos.combos.combo(df, name='', ksigmas=None, S0=None, sigma0=None)

A Black Scholes Option Combo class

Inherits methods like ‘NPV’, ‘delta’, ‘gamma’, ‘volga’, ‘vanna’ from option_portfolio (ultimately from GBS)

Instance Variables

dfPandas DataFrame containing combo data

(see documentation of __init__)

namestring

Combo name used in __repr__ and in the plots

ksigmasfloat

Width of x-axis (in standard deviations) in plots

Constructors

  • The __init__ constructor is not intended to be used directly. The following static methods are easier to use:

  • general constructor
    • combo.combo(K, [instrumentType], [weight], [ttm], [name])

  • specific constructors
    • combo.call(K, [ttm], [name]): call option

    • combo.put(K, [ttm], [name]): put option

    • combo.forward(K, [ttm], [name]): forward contract

    • combo.underlying(): call option with zero strike

    • combo.exposure(): same as underlying but with value set to 0

    • ZC_Bond(FV, [ttm], [name]): zero coupon bond

Overloaded Operators

  • ‘+’ create new combo containing the positions of two combos

  • ‘-’ (unary minus) new combo is short the first combo

  • ‘-’ (subtraction) new combo is long first combo and short second combo

  • ‘*’ (scalar multiply) left term is a float and second term is a combo

    creates new combo with positions multiplied by the number

New Methods

The new methods (not inherited from option_portfolio) are:
  • set_name: set (change) the name of the combo

  • set_one_strike: change one of the strikes used to change striked interactively

  • plot_payoff: plots payoff and optionally profit and value This is a wrapper around plot_any

  • plot_any: plots any set of quantities (value, greeks)

  • plot_interactive: plots_any with sliders

set_name(newname)

Change name of combo

Parameters:

newname (string) – new name of combo

Return type:

combo

Examples

set_one_strike(i, newk)

Change strike of one instrument in the combo

Parameters:
  • i (int) – row number of instrument to change

  • newk (float) – new strike

Return type:

combo

Examples

static combo(K, instrumentType=1, weight=1, ttm=None, name='', component_names=None)

Convenience constructor without DataFrame as argument

Parameters:
  • K (float or array of floats) – strike price

  • instrumentType (int) – type of instrument (e.g. instrument.put)

  • weight (float) – number of options (negative number for ttm)

  • ttm (float) – time to maturity in years

  • name (string) – name of the combo

  • component_names (string) – name of the component

Return type:

combo

Examples

static call(K=None, ttm=None, name=None, instrumentType=1)

Construct combo with only one call option

Parameters:
  • K (float) – strike price

  • ttm (float) – time to maturity in years

  • name (string or None) – name of combo

  • instrumentType (int) – type of instrument (e.g. instrument.call or instrument.exposure)

Return type:

combo

Examples

>>> combo.call(120)
combo: Call@120
static put(K=None, ttm=None, name=None)

Construct combo with only one put option

Parameters:
  • K (float) – strike price

  • ttm (float) – time to maturity in years

  • name (string or None) – name of combo

Return type:

combo

Examples

>>> combo.put(90)
combo: Put@90
static underlying(name=None)

Construct combo of only one zero strike forward (underlying)

Parameters:

name (string or None) – name of combo

Return type:

combo

Examples

>>> combo.underlying()
combo: Underlying
static exposure(name=None)

Construct combo of only one exposure to underlying

Parameters:

name (string or None) –

Return type:

combo

Examples

>>> combo.exposure()
combo: Exposure
static ZC_Bond(FV=None, ttm=None, name=None)

Construct combo of only one zero coupon bond

Parameters:
  • FV (float) – face value of bond

  • ttm (float) – maturity in years

  • name (string) – name of combo

Return type:

combo

Examples

>>> combo.ZC_Bond(FV=100,ttm=3)
combo: 3Y Bond (100)
static forward(K=None, ttm=None, name=None)

Construct combo with only one forward contract

Parameters:
  • K (float) – strike price of forward

  • ttm (float) – time to maturity in years

  • name (string or None) – name of combo

Return type:

combo

Examples

>>> combo.forward(105)
combo: Forward@105
decomposition()

Return list of combos consisting of this combo and its components

Return type:

list of combos

Examples

>>> (combo.call(100) - combo.put(100)).decomposition()
[combo: Call@100, combo: -Put@100, combo: Call@100-Put@100]
compute(flist, extra_strikes=[])
Parameters:
  • flist (list of strings) – each string is the name of a combo method For example, [‘combo.NPV’, ‘comb.payoff’, ‘combo.Delta’] Values returned by this method are plotted

  • extra_strikes (list of float) – additional dummy strikes to include while setting x axis limits These are passed on to the _make_S_array method

Returns:

This DataFrame has one column for each string in flist Each column contains the payoff, profit, value or greek of combo for the set of set of underlying prices returned by _make_S_array

Return type:

Pandas DataFrame

Examples

>>> combo.call(100).compute(['payoff']).round(2)
... 
            payoff
82.679492     0.00
99.000000     0.00
100.000000    0.00
101.000000    1.00
117.320508   17.32
plot_any(flist, axis=None, title=None, xlabel='Asset Price', ylabel=None, legend=True, strikes=True, spot=True, name_mapping=None, extra_strikes=[], ylim=None)

Plot one graph (payoff, premium or greek) for one combo

Parameters:
  • flist (list of strings) – each string is the name of a combo method For example, [‘combo.NPV’, ‘comb.payoff’, ‘combo.Delta’] Values returned by this method are plotted

  • axis (matplotlib Axis object or None) – matplotlib Axis object to be used for plotting. If None, plt.gca() is used

  • title (string or None) – If not None, this is used as the title for plot

  • xlabel (string) – X axis label

  • ylabel (string) – Y axis label

  • legend (boolean) – If True, plot includes legend

  • strikes (boolean) – whether to draw vertical lines at the strikes

  • spot (boolean) – whether to draw vertical lines at the current spot

  • name_mapping (Dictionary) – maps method names of this class to label in plots

  • extra_strikes (list of float) – additional dummy strikes to include while setting x axis limits These are passed on to the compute method

  • ylim (tuple of two floats) – lower and upper bounds on the y-axis to override defaults useful to force same axes in different plots

Returns:

This DataFrame has one column for each string in flist Each column contains the payoff, profit, value or greek of combo for the set of set of underlying prices returned by _make_S_array

Return type:

Pandas DataFrame

plot_payoff(profit=True, value=False, axis=None, title=None, xlabel='Asset Price', ylabel=None, legend=True, strikes=True, spot=True, name_mapping=None, extra_strikes=[], ylim=None)

Plot payoff (and optionally profit and value) of combo

Parameters:
  • profit (boolean) – if True, profit is also plotted

  • value (boolean) – if True, value is also plotted

  • axis (matplotlib Axis object or None) – matplotlib Axis object to be used for plotting. If None, plt.gca() is used

  • title (string or None) – If not None, this is used as the title for plot

  • xlabel (string) – X axis label

  • ylabel (string) – Y axis label

  • strikes (boolean) – whether to draw vertical lines at the strikes

  • spot (boolean) – whether to draw vertical lines at the current spot

  • legend (boolean) – If True, plot includes legend

  • name_mapping (Dictionary) – maps method names of this class to label in plots

  • extra_strikes (list of float) – additional dummy strikes to include while setting x axis limits These are passed on to the compute method

  • ylim (tuple of two floats) – lower and upper bounds on the y-axis to override defaults useful to force same axes in different plots

Returns:

This DataFrame has one column for each string in flist Each column of this DataFrame contains payoff/profit/value for the set of underlying prices returned by _make_S_array

Return type:

Pandas DataFrame

plot_many(fl_list=None, layout=None, title=None, xlabel='Asset Price', ylabel=None, legend=True, strikes=True, spot=True, name_mapping=None, extra_strikes=[], ylim=None)
Plot many graphs for same combo

for different variables (payoff, premium, greeks)

Parameters:
  • Combo (instrument or bundle) –

  • fl_list (list) – This is a list of sublists of function names. Each sublist is plotted in a separate subplot by calling plot_any method. Each function is a combo method.

  • layout (tuple of two ints or None) – nr and nc arguments to the matplotlib add_subplot command If None, an automatic choice is made

  • title (string or None) – If not None, this is used as the title for plot

  • xlabel (string) – X axis label

  • ylabel (string) – Y axis label

  • strikes (boolean) – whether to draw vertical lines at the strikes

  • spot (boolean) – whether to draw vertical lines at the current spot

  • legend (boolean) – If True, plot includes legend

  • name_mapping (Dictionary) – maps method names of this class to label in plots

interactive_plot(flist, title=None, xlabel='Asset Price', ylabel=None, inplace=False, legend=True, strikes=True, spot=True, name_mapping=None, extra_strikes=[], ylim=None)

Interactive plot with sliders to change strikes

Parameters:
  • flist (list of strings) – each string is the name of a combo method For example, [‘NPV’, ‘payoff’, ‘Delta’] Values returned by this method are plotted

  • title (string or None) – If not None, this is used as the title for plot

  • xlabel (string) – X axis label

  • ylabel (string) – Y axis label

  • inplace (boolean) – if False, a copy of the combo is used so that the interactive sliders do not alter the original combo

  • legend (boolean) – If True, plot includes legend

  • strikes (boolean) – whether to draw vertical lines at the strikes

  • spot (boolean) – whether to draw vertical lines at the current spot

  • name_mapping (Dictionary) – maps method names of this class to label in plots

  • extra_strikes (list of float) – additional dummy strikes to include while setting x axis limits These are passed on to the compute method

  • ylim (tuple of two floats) – lower and upper bounds on the y-axis to override defaults useful to force same axes in different plots

  • inplace – if False, a copy of the combo is used so that the interactive sliders do not alter the original combo

Returns:

This is original combo if inplace is False Else it is the interactively altered combo

Return type:

combo

plot_decomposition(flist=None, layout=None, name_mapping=None)
Plot graphs of same variables (payoff, premium, greeks)

for combo and its components

Parameters:
  • flist (list of string) – Each string is name of a GBSx method whose result is plotted.

  • layout (tuple of two ints or None) – nr and nc arguments to the matplotlib add_subplot command If None, an automatic choice is made

  • name_mapping (Dictionary) – maps method names of this class to label in plots

option_combos.combos.plot_many_combos(combos, flist=None, layout=None, decompose=True, title=None, xlabel='Asset Price', ylabel=None, legend=True, strikes=True, spot=True, name_mapping=None)
Plot graphs of same variables (payoff, premium, greeks)

for different combos

Parameters:
  • combos (combo or list of combos) –

  • flist (list of string) – Each string is name of a GBSx method whose result is plotted.

  • layout (tuple of two ints or None) – nr and nc arguments to the matplotlib add_subplot command If None, an automatic choice is made

  • decompose (boolean) – If True and combos is a single combo (not a list), the combo is decomposed into components and each component is plotted

  • title (string or None) – If not None, this is used as the title for plot

  • xlabel (string) – X axis label

  • ylabel (string) – Y axis label

  • strikes (boolean) – whether to draw vertical lines at the strikes

  • spot (boolean) – whether to draw vertical lines at the current spot

  • legend (boolean) – If True, plot includes legend

  • name_mapping (Dictionary) – maps method names of this class to label in plots

Default values

class option_combos.defaults.defaults

Default values for GBS/GBSx constructors and combo plots

  • The first set of defaults allow a GBS or GBSx class to be instantiated without giving values for any arguments.

  • The second set of defaults provide default settings for plotting a combo

S = 100

default value for current market price of the underlying

K = 100

default value for Strike price

sigma = 0.2

Annualized volatility in decimal (0.25 for 25%)

months = 0.08333333333333333

convert months into years in option maturity

days = 0.0027397260273972603

convert days into years in option maturity

ttm = 0.08333333333333333

Default time to maturity in years

r = 0.05

(Domestic) risk free rate, decimal annlzd cont. compounded

q = 0.02

Dividend yield or foreign risk free rate dec annlzd cont comp

instrumentType = 1

default instrument type

instrumentType_name = 'call'

default instrument type by name

ksigmas = 3

default Width of x-axis (in standard deviations) in plots

nlinspace = 20

by default x-axis includes 2*nlinspace+1 points between end points

name_mapping = {}

Dictionary to rename method names to label in plots

payoff_only = ['payoff']

fl_list argument for plot_many to plot only payoff

payoff = ['payoff', 'profit']

fl_list argument for plot_many to plot payoff and profit

value = ['value', 'payoff']

fl_list argument for plot_many to plot payoff and value

profit_value = ['payoff', 'profit', 'value']

fl_list argument for plot_many to plot payoff profit and value

greeks = [['Delta'], ['Gamma'], ['Vega'], ['Theta']]

fl_list argument for plot_many to plot greeks

all_list = [['payoff', 'profit'], ['value', 'payoff'], ['Delta'], ['Gamma'], ['Vega'], ['Theta']]

fl_list argument for plot_many to plot payoff value and greeks

all_list2 = [['payoff'], ['value', 'payoff'], ['Delta'], ['Gamma'], ['Vega'], ['Theta']]

fl_list argument for plot_many to plot payoff and greeks

Merton Model for Credit Risk

option_combos.merton_model.merton(DebtBV, maturity, r, DivYld=0, frequency=inf, Assets=nan, sigmaA=nan, EquityMV=nan, DebtMV=nan, DebtYTM=nan, CreditSpread=nan, coupon=nan, index_from_Series=False)

Merton (structural) credit model.

Given data on two of the following variables, compute the third
  1. debt market value, YTM and credit spread, or

  2. equity market value, or

  3. asset volatility

Parameters:
  • DebtBV (None or float or sequence) – The book value of the Debt

  • maturity (float or sequence) – Maturity of zero coupon debt in years

  • r (float or sequence) – The risk free rate This is annualized, and in percent

  • DivYld (float or sequence) – The dividend yield This is annualized, and in percent

  • frequency (integer or np.Inf or sequence) – The frequency of compounding of interest rates and spreads

  • Assets (None or float or sequence) – The current market price of the assets of the firm

  • sigmaA (None or float or sequence) – The annualized asset volatility in percent

  • EquityMV (None or float or sequence) – The market value of the equity

  • DebtMV (None or float or sequence) – The market value of the debt

  • DebtYTM (None or float or sequence) – The yield to maturity of the debt

  • CreditSpread (None or float or sequence) – The credit spread of the debt in basis points

  • coupon (None or float or sequence) – The coupon rate on the debt annualized, and in percent. If None, the risk free rate is assumed. Face value of zero coupon debt is computed by assuming that the coupon is compounded and paid at maturity. If DebtBV is already the face value of zero coupon debt, provide an explicit coupon rate if 0.

  • index_from_Series (boolean) – if true the returned DataFrame is indexed with the index of the first Pandas Series among the input arguments

Returns:

Input variables and model values of other variables

Return type:

Pandas DataFrame

Notes

If both debt market and equity market information are given, sigmaA is calibrated from the given data. If sigmaA and information from either debt or equity market is given, the asset value is calibrated from the given information and then data for the missing market is computed. Equity market information is given as EquityMV Debt market information can be given as DebtMV, DebtYTM or CreditSpread

EWMA Volatility Estimation

option_combos.EWMA.EWMA(df, input_name='Price', vol_name='Sigma', ret_name='lnret', input_is_price=True, Lambda=0.94, burn_in=20, sigma_init=None, sigma_init_sample=20, inplace=True)

Compute time varying historical volatility using EWMA method.

EWMA (Exponentially Weighted Moving Average) is also sometimes called the RiskMetrics method (because it was first popularized by Riskmetrics) or the IGarch (Integrated Garch) method (because it is similar to the Garch method except that the volatility is assumed to follow a unit root process instead of being a stationary process).

Parameters:
  • df (Pandas DataFrame) – One column must contain prices/returns and the index must be the date

  • input_name (string) – Column name of df that contains price/return

  • vol_name (string) – Column name of df in which to store estimated volatitlity

  • ret_name (string) – Column name of df in which to store returns (if input is price)

  • input_is_price (boolean) – Whether the input column is price (True) or return (False)

  • Lambda (float) – Smoothing parameter of exponential moving average

  • burn_in (int) – Number of initial values of volatility to be set to nan

  • sigma_init (float or None) – Initial volatility (if None sample volatility is used)

  • sigma_init_sample (int) – Length of initial sample to compute initial volatility (used only if sigma_init is None)

  • inplace (boolean) – If true df is modified in place and returned. Else copy is made

Returns:

Input DataFrame with added column(s) containing the estimated volatility and if necessary the log return

Return type:

Pandas DataFrame

Check analytical Greeks numerically

option_combos.GBS_greek_test.check(S, K, sigma, ttm, r, q, optType, delta=1e-06, tolerance=5e-05, verbose=True)

Check analytic greeks of a specific option by numerical differentiation

Parameters:
  • S (float) – The current market price of the underlying

  • K (float) – The strike price of the option

  • sigma (float) – The annualized volatility in decimal (0.25 for 25%)

  • ttm (float) – Time to maturity in years

  • r (float) – The (domestic) risk free rate This is continuously compounded annualized, and in decimal

  • q (float) – The dividend yield or foreign risk free rate This is continuously compounded annualized, and in decimal

  • optType – instrument.call, instrument.put, instrument.forward, instrument.bond

  • delta (float) – numerical differentiation uses values delta apart

  • tolerance (float) – tolerance for discrepancy between analytic and numerical derivative (discrepancy is regarded as significant only if both absolute and relative error must exceed this tolerance)

  • verbose (boolean) – if true error details are printed

Returns:

int

Return type:

error count (number of greeks with discrepancy > tolerance)

Examples

>>> check(S=93.112533, K=106.693664, sigma=0.260802,
...       ttm=108.625926, r=0.072272, q=0.073218, optType=instrument.put,
...       delta=1e-6, tolerance=5e-5, verbose=True)
... 
RhoD=-4.180261. Numl=-4.180501. abserr=0.000240. relerr=0.000057
1 errors in excess of 5e-05
1
option_combos.GBS_greek_test.test_GBS_greeks_by_numerical_differentiation(delta=1e-06, tolerance=5e-05, samplesize=50, verbose=True)

Check analytic Greeks of a random sample of options by numerical differentiation

Parameters:
  • delta (float) – numerical differentiation uses values delta apart

  • tolerance (float) – tolerance for discrepancy between analytic and numerical derivative

  • samplesize (int) – number of options (random sample) to be checked

  • verbose (boolean) – if true error details are printed

Returns:

first element is the number of options which had at least one greek with discrepancy exceeding tolerance, second element is the total number of greeks across all options that had discrepancy exceeding tolerance

Return type:

tuple of two ints

Notes

  • S and K are sampled from normal distribution with mean=100 and sd=10

  • r and q are sampled from normal distribution with mean=5% and sd=3%

  • ln(sigma) is sampled from normal distribution with mean=-1.5 and sd=0.5

  • ln(ttm) is sampled from normal distribution with mean=0 and sd=2

  • the instrument type is sampled from [call, put, forward, bond] with probabilities [35%, 35%, 15%, 15%].

Indices and tables