Rolling Option Strategies#

This page shows the building blocks within the option space that are available on the SigTech platform. All of the building blocks in this notebook are strategies. For more information on how to construct individual options, see Options.

A notebook containing all the code used in this page can be accessed in the research environment: 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
from sigtech.framework.utils.numeric_utils import date_to_datetime
from sigtech.framework.strategies.rolling_options_baskets import RollingOption

from typing import Dict
from uuid import uuid4
import datetime as dtm
import seaborn as sns

sns.set(rc={'figure.figsize': (18, 6)})
sig.config.init()

Learn more: Setting up your environment.

Option Strategy Building Blocks#

The following strategy building blocks for options are available on the SigTech platform:

  • Straddle

  • Strangle

  • RollingOption

  • DynamicOptionsStrategy

  • DynamicMultiOptionsStrategy

Each building block inherits from the RollingOptionsStrategyBase class, which allows for maintaining exposure via options contracts over time. You can implement rolling options strategies by using the abstract roll_options method. Use the parameter dt (decision datetime) to set your preferred option positions.

Straddle#

A Straddle is a rolling option strategy that takes the same position in both a call option and a put option with the same expiration and strike price.

  • A long straddle strategy buys both a call option and a put option. This generally profits if the stock price increases or decreases, or if volatility increases.

  • A short straddle strategy sells both a call option and a put option. This generally profits if the stock price and volatility remain steady.

Input:

start_date = dtm.date(2018, 10, 1)
end_date = dtm.date(2020, 1, 4)

# Create option group
equity_option_group = sig.obj.get('SPX INDEX OTC OPTION GROUP')

# Create strategy
straddle = sig.Straddle(
    currency=sig.obj.get(equity_option_group.underlying).currency,
    start_date=start_date,
    end_date=end_date,
    group_name=equity_option_group.name,
    strike_type='Delta',
    strike=0.5,
    maturity='3M',
    rolling_frequencies=['1M'],
    target_quantity=1.0,
    target_type = 'StrikeNotionalAsProportionOfNAV', # 'SpotNotionalAsProportionOfNAV' and other options also available
    close_out_at_roll=True,
)

# Query and plot performance
straddle.history().plot();

Output:

Strangle#

A Strangle takes the same position in both a call option and a put option with the same expiration but different strike price.

  • A long strangle strategy buys both a call option and a put option. This strategy generally profits if the stock price increases or decreases, or if volatility increases.

  • A short strangle strategy sells both a call option and a put option. This generally profits if the stock price and volatility remain steady during the life of the options.

Input:

# Create option group
nky_option_group = sig.obj.get('NKY INDEX OTC OPTION GROUP')

# Create strategy
strangle = sig.Strangle(
    currency='USD',
    start_date=start_date,
    end_date=end_date,
    group_name=nky_option_group.name,
    strike_type='SPOT',
    put_strike=-0.05,
    call_strike=0.25,
    maturity='3M',
    rolling_frequencies=['1M']
)

# Query and plot performance
strangle.history().plot();

Output:

Rolling Option#

A RollingOption strategy takes the same position in either a call or put option with the same expiration and strike price and holds it from the start date to the end date defined in the strategy object.

Input:

# Create option group
gbpusd_group = sig.FXOTCOptionsGroup.get_group('GBPUSD')

# Create strategy
rolling_put = RollingOption(
    currency='USD',
    start_date=start_date,
    end_date=end_date,
    group_name=gbpusd_group.name,
    option_type='Put',
    strike_type='SPOT',
    maturity='3M',
    rolling_frequencies=['1M'],
    initial_cash=0
)

# Query and plot performance
rolling_put.history().plot();

Output:

Dynamic Options Strategy#

The DynamicOptionsStrategy class trades an arbitrary selection of options in the same group. This can take a callback method, which gets called for each rebalance date to determine the options to trade, or a dictionary of trades for each date can be provided.

The example below uses this strategy with a method to trade 10 put options each month. The basket_creation_method function gets passed in to the DynamicOptionsStrategy class, then gets called on each roll date and provides a dictionary or tuple of options to trade. The method should take the strategy, decision time and positions as input and provide a dictionary of options.

def basket_creation_method(strategy, dt, positions):
    size_date = strategy.size_date_from_decision_dt(dt)
    return {
        eur_usd_group.get_option(
            option_type='Put',
            strike=sig.obj.get(eur_usd_group.underlying).history().asof(
                date_to_datetime(size_date)),
            start_date=size_date,
            maturity='1M'
        ): 10
    }

Input:

# Create option group
eur_usd_group = sig.FXOTCOptionsGroup.get_group('EURUSD')

# Create strategy
method_strategy = sig.DynamicOptionsStrategy(
    currency=eur_usd_group.over,
    start_date=dtm.date(2010, 1, 6),
    end_date=dtm.date(2012, 1, 20),
    group_name=eur_usd_group.name,
    basket_creation_method=basket_creation_method,
    rolling_frequencies=['1M'],
    ticker=f'ROLLING PUT {str(uuid4())[:4]}',
    initial_cash=0,
)

# Query and plot performance
method_strategy.history().plot();

Output:

Dynamic Multi Options Strategy#

Similar to the Dynamic Options Strategy, the DynamicMultiOptionsStrategy class trades a basket of options. However, this building block allows you to trade options from multiple groups, whereas DynamicOptionsStrategy only trades options from within the same group.

When using the DynamicMultiOptionsStrategy building block, you need to define your own roll_options method to create the desired behavior. This is best achieved using a custom function—see the code example below:

class ExampleDynamicMultiOptionsStrategy(sig.DynamicMultiOptionsStrategy):
    def roll_options(self, dt):
        size_date = self.size_date_from_decision_dt(dt)

        usdeur = sig.FXOTCOptionsGroup.get_group('USDEUR')
        usdeur_maturity_date = usdeur.convert_maturity_tenor_to_date(size_date, '1M')
        usdeur_atm = usdeur.atm_from_type('Call', size_date,
                                          usdeur_maturity_date, 'DN')
        usdeur_call = usdeur.get_option('Call', usdeur_atm,
                                        size_date, usdeur_maturity_date)

        usdgbp = sig.FXOTCOptionsGroup.get_group('USDGBP')
        usdgbp_maturity_date = usdgbp.convert_maturity_tenor_to_date(size_date, '1M')
        usdgbp_atm = usdgbp.atm_from_type('Call',
                                          size_date, usdgbp_maturity_date, 'DN')
        usdgbp_call = usdgbp.get_option('Call', usdgbp_atm,
                                        size_date, usdgbp_maturity_date)

        self.set_option_positions(dt, ((usdeur_call, 1), (usdgbp_call, 1)))

Use the custom function to build your Dynamic Multi Options Strategy:

rs = ExampleDynamicMultiOptionsStrategy(currency='USD',
        start_date=dtm.date(2012, 1, 3),
        end_date=dtm.date(2013, 9, 24),
        group_names=[sig.FXOTCOptionsGroup.get_group('USDEUR').name,
                     sig.FXOTCOptionsGroup.get_group('USDGBP').name],
        target_type='Fixed',
        roll_dates=[dtm.date(2012, 2, 16),
                    dtm.date(2012, 3, 20),
                    dtm.date(2012, 4, 18)],)

# Print the strategy progress
rs.history()

API Documentation#

For more information on the RollingOptionsStrategyBase class, see the corresponding API reference.