Options#
This page shows how individual options and volatility surfaces work on the platform.
Learn more: Example notebooks
Environment#
Setting up your environment takes three steps:
Import the relevant internal and external libraries
Configure the environment parameters
Initialize the environment
import sigtech.framework as sig
import datetime as dtm
import pandas as pd
import seaborn as sns
sns.set(rc={'figure.figsize': (18, 6)})
sig.config.init()
Learn more: Setting up the environment
Vanilla Options#
Overview#
To create a vanilla option on the SigTech platform, carry out the following steps:
1) Get option group#
The available option groups can be viewed in the Data Browser. To retrieve an option group, use the following syntax and insert the relevant option group name:
option_group = sig.obj.get('<Insert Relevant Option Group Name>')
2) Create option#
Retrieve the option by calling the .get_option()
method on the option group object. Below is an example:
option = option_group.get_option(
option_type='Call',
strike=1100,
start_date=dtm.date(2010, 4, 6),
maturity=dtm.date(2011, 4, 6)
)
If you’re getting an option for a futures group (such as CO COMDTY OTC OPTION GROUP
) the maturity date must match an expiration date of one of the futures in the group. To find a valid maturity date that is closest to a given a date, use the following method: option.available_maturity(dtm.date(2011,4,6))
.
Example: Index OTC option#
An index over-the-counter (OTC) option gives you the right to buy or sell the value of an index at a specified price.
On the SigTech platform, use sig.obj.get
to retrieve the option group. You can then create the option instrument.
Input:
# Get the option group
equity_option_group = sig.obj.get('SPX INDEX OTC OPTION GROUP')
# Create the option
spx_call_option = equity_option_group.get_option(
option_type='Call',
strike=1100,
start_date=dtm.date(2010, 4, 6),
maturity=dtm.date(2011, 4, 6)
)
spx_call_option
Output:
SPX 20110406 CALL 1100 604506EC INDEX <class 'sigtech.framework.instruments.options.EquityIndexOTCOption'>[4534898352]
You can also plot the valuation of each option. This is compared below to the underlying asset minus the strike.
pd.concat({
'Spot - strike (1100)': spx_call_option.underlying_object.history() - 1100,
'Option price': spx_call_option.history()
}, axis=1).dropna().plot();
Example: FX OTC option#
The FXOTCOptionsGroup
class represents FX OTC option groups.
Use the get_group
method to retrieve the option group, then create the FX OTC option:
eur_usd_group = sig.FXOTCOptionsGroup.get_group('USDEUR')
eurusd_call_option = eur_usd_group.get_option('Call', 1.3, dtm.date(2010, 4, 6),
dtm.date(2011, 4, 6))
Plot the valuation:
pd.concat({
'Spot - strike (1.3)': eurusd_call_option.underlying_object.history() - 1.3,
'Option price': eurusd_call_option.history()
}, axis=1).dropna().plot();
Other OTC option groups#
As well as FXOTCOptionsGroup
above, other OTC option group classes include:
OTCOptionGroup
EquityIndexOTCOptionsGroup
CommodityOTCOptionsGroup
ETFOTCOptionsGroup
FXOTCOptionsGroup
VolatilityIndexOTCOptionsGroup
You can use these option group classes to create the corresponding option. To view a list of available options, use the get_names
method—the example below retrieves a list of ETF OTC options:
sig.instruments.option_groups.ETFOTCOptionsGroup.get_names(include_children=True)
Alternative way of creating options#
Options can also be created explicitly from an option class without using the option group. Some of the option classes available include:
EquityIndexOTCOption
#
This class implements OTC equity index option instruments.
Input:
equity_option = sig.EquityIndexOTCOption(
currency='USD',
maturity_date=dtm.date(2011, 4, 6),
option_type='Call',
start_date=dtm.date(2010, 4, 6),
strike=1100,
underlying='SPX INDEX',
)
equity_option
Output:
SPX 20110406 CALL 1100 A6D17D99 INDEX <class 'sigtech.framework.instruments.options.EquityIndexOTCOption'>[5966872832]
FXOTCOption
#
This class implements FX OTC option instruments. Parameters include:
over
: The over currency of the underlying pair (e.g.USD
forEURUSD
)under
: The under currency of the underlying pair (e.g.EUR
forEURUSD
)
Use FXOTCOption
to create the instrument:
instr = sig.FXOTCOption(
over='USD',
under='EUR',
strike=1.0635,
start_date=dtm.date(2017, 1, 6),
maturity_date=dtm.date(2017, 4, 6),
option_type='Call'
)
CommodityFutureOTCOption
#
This class implements OTC commodity future options:
instr = sig.CommodityFutureOTCOption(
currency='USD',
start_date=dtm.date(2018, 8, 22),
strike=80,
maturity_date=dtm.date(2019, 1, 28),
option_type='Put',
underlying='COH19 COMDTY',
exercise_type='American'
)
CommodityFutureOTCDigitalOption
#
This class implements OTC commodity future digital options. A digital option is a type of option that lets you manually set a strike price. You receive a fixed payout when the market price of the underlying asset exceeds the strike price.
Create the instrument:
instr = sig.CommodityFutureOTCDigitalOption(
currency='USD',
start_date=dtm.date(2018, 7, 22),
strike=75,
maturity_date=dtm.date(2019, 1, 28),
underlying='COH19 COMDTY'
)
Exotic options#
Overview#
When dealing with other options apart from vanilla options, it’s easy to modify the .get_options()
method depending on use case. The available exotic options are:
Digital
Barriers (KO & KI)
One-touch & no-touch
Digital #
digital = eur_usd_group.get_option('Call', 1.3, dtm.date(2010, 4, 6),
dtm.date(2011, 4, 6), digital=True)
pd.concat({
'Spot - strike (1.3)': digital.underlying_object.history() - 1.3,
'Option price': digital.history()
}, axis=1).dropna().plot(subplots=True);
Barriers: KO & KI #
ki_barrier_1 = eur_usd_group.get_option('Call', 1.3,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='KI', barrier=1.5)
ki_barrier_2 = eur_usd_group.get_option('Call', 1.3,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='KI', barrier=1.4)
pd.concat({
'Spot - strike (1.3)': ki_barrier_1.underlying_object.history() - 1.3,
'Option price (1.4 barr.)': ki_barrier_2.history(),
'Option price (1.5 barr.)': ki_barrier_1.history()
}, axis=1).dropna().plot(subplots=True);
ko_barrier_1 = eur_usd_group.get_option('Call', 1.3,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='KO', barrier=1.5)
ko_barrier_2 = eur_usd_group.get_option('Call', 1.3,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='KO', barrier=1.4)
pd.concat({
'Spot - strike (1.3)': ko_barrier_1.underlying_object.history() - 1.3,
'Option price (1.4 barr.)': ko_barrier_2.history(),
'Option price (1.5 barr.)': ko_barrier_1.history()
}, axis=1).dropna().plot(subplots=True);
One-touch & no-touch #
ot_barrier = eur_usd_group.get_option('Call', 1.4,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='OT', digital=True)
nt_barrier = eur_usd_group.get_option('Call', 1.4,
dtm.date(2010, 4, 6), dtm.date(2011, 4, 6),
barrier_type='NT', digital=True)
pd.concat({
'Spot - strike (1.3)': ot_barrier.underlying_object.history() - 1.3,
'Option price (One-touch 1.4)': ot_barrier.history(),
'Option price (No-touch 1.4)': nt_barrier.history()
}, axis=1).dropna().plot(subplots=True);
Greeks#
The Greeks for each option can be queried in the following way:
equity_option.option_metrics().head()
The volatility can be overwritten in the Greeks calculation. This override can be specified as a float or time series of vols.
equity_option.option_metrics(
fields=['Delta', 'ImpliedVolatility'], vol_override=0.12).head()
Vol surface #
Retrieve vol surface object #
Input:
vs = sig.obj.get('EURUSD VOLSURFACE')
vs
Output:
EURUSD VOLSURFACE <class 'sigtech.framework.infra.vol_surfaces.vol_surface.FXVolSurface'>[5572896224]
vs.plot_surface(d=vs.history_dates_actual()[-1], z_name='Vol')
get_vol
based on the effective date, expiry date and strike.
Input:
vs.get_vol(dtm.date(2019, 3, 29), dtm.date(2019, 4, 28), 1.34)
Output:
0.05693914182317497
Vol surface iterator#
The FXVolSurfaceIterator
class simplifies the retrieval of a set of volatility surfaces for a selection of currencies and associated data.
Input:
vol_iterator = sig.FXVolSurfaceIterator(['USD', 'EUR', 'GBP'])
list(vol_iterator.iterate_surfaces())
Output:
[EURUSD VOLSURFACE <class 'sigtech.framework.infra.vol_surfaces.vol_surface.FXVolSurface'>[5572896224],
GBPUSD VOLSURFACE <class 'sigtech.framework.infra.vol_surfaces.vol_surface.FXVolSurface'>[5973002656],
EURGBP VOLSURFACE <class 'sigtech.framework.infra.vol_surfaces.vol_surface.FXVolSurface'>[5981535392]]
Use the iterator class to generate a list of all available surfaces:
Input:
sig.FXVolSurfaceIterator.get_all_available_surfaces_names()[:5]
Output:
['AUDBRL VOLSURFACE',
'AUDCAD VOLSURFACE',
'AUDCHF VOLSURFACE',
'AUDCNH VOLSURFACE',
'AUDHKF VOLSURFACE']
Using the FXVolSurfaceIterator
instance, you can obtain the historical implied ATM volatilities and risk reversals:
implied_1m_vol_history_df = vol_iterator.atm_vols_for_tenor('1M')
implied_1m_vol_history_df.plot(title='Historical Implied Volatilities');
rr_history_df = vol_iterator.risk_reversal('1M', 25)
rr_history_df.plot(title='Historical Risk Reversal (25 Delta)');
The available tenors can be listed with the get_all_available_tenors
method:
Input:
vol_iterator.get_all_available_tenors()[:10]
Output:
['-', 'O/N', 'ON', '1W', '1WK', '2WK', '2W', '3WK', '3W', '1M']