FX Option Strangle Strategies using Dynamic Options
Contents
FX Option Strangle Strategies using Dynamic Options#
New user? The best way to learn SigTech is to follow the steps in our user guide.
Restricted data: You will only have access to the data used in this notebook if your organisation has specifically purchased it. To check your current data access, view Data. If you would like to access more data, please contact sales@sigtech.com.
Changes will not be saved: Edits made to SigTech’s example notebooks like this will only persist for the duration of your session. When you restart the research environment, this notebook will have been restored to its original state, and any changes you have made will have been lost. To make permanent changes, copy and paste the content to a new notebook in one of your workspaces.
Introduction#
The purpose of this notebook is to create a systematic strategy involving multiple straddle strategies using the DynamicOptionsStrategy
building block. This notebook contains three examples:
1M-3M strangle with a delta strike signal
Delta Hedged strangle
Date specific strangle roll
Environment#
This section imports the relevant internal and external libraries, and sets up the platform environment.
[ ]:
import datetime as dtm
import seaborn as sns
import pandas as pd
import numpy as np
import sigtech.framework as sig
sns.set(rc={'figure.figsize':(18, 6)})
env = sig.init(env_date=dtm.date(2024, 2, 22))
Variables#
[ ]:
ccy = "USD"
fx_group = "EURUSD OTC OPTION GROUP"
start_date = dtm.date(2020, 1, 1)
Delta Signal#
Signal defining where to place the near and far strangles.
[ ]:
delta_signal = pd.DataFrame(
np.random.uniform(0.1, 0.5, size=(50, 2)),
index=pd.bdate_range(start_date - pd.Timedelta(days=365), periods=50, freq="M"),
columns=["1M_delta", "3M_delta"]
)
delta_signal.head()
Baseline strangles with 1M
and 3M
delta strikes#
[ ]:
def strangle_creation_method(strategy,dt, positions) -> dict:
"""
Creates the strangles needed by looking at the delta signal.
"""
size_date = strategy.size_date_from_decision_dt(dt)
# Look up near and far delta strikes from signal
signal_column = "1M_delta" if strategy.maturity == "1M" else "3M_delta"
latest_delta = delta_signal.loc[:size_date, signal_column][-1]
# Generate the strangle
call = strategy.group.get_option(
option_type="Call",
strike=latest_delta,
strike_type="Delta",
start_date=size_date,
maturity=strategy.maturity,
)
put = strategy.group.get_option(
option_type="Put",
strike=-latest_delta,
strike_type="Delta",
start_date=size_date,
maturity=strategy.maturity,
)
# Return weights
return {
call: 1,
put: 1,
}
Create a DynamicOptionsStrategy
of strangles based on the method defined above
[ ]:
near_strangle = sig.DynamicOptionsStrategy(
maturity="1M",
basket_creation_method=strangle_creation_method,
currency=ccy,
group_name=fx_group,
start_date=start_date,
rolling_frequencies=["1M"],
close_out_at_roll=True,
target_quantity=1,
target_type="SpotNotional",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
far_strangle = sig.DynamicOptionsStrategy(
maturity="3M",
basket_creation_method=strangle_creation_method,
currency=ccy,
group_name=fx_group,
start_date=start_date,
rolling_frequencies=["1M"],
close_out_at_roll=True,
target_quantity=1,
target_type="SpotNotional",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
near_strangle.build()
far_strangle.build()
[ ]:
near_strangle.history().plot.line(legend=True, label="1M strangle")
far_strangle.history().plot.line(legend=True, label="3M strangle")
Analysing historical strikes#
[ ]:
near_strangle.plot.portfolio_table(near_strangle.action_datetimes()[0:10])
Delta hedged baseline strangles#
[ ]:
dh_near_strangle = sig.DeltaHedgingStrategy(
currency=near_strangle.currency,
start_date=near_strangle.start_date,
option_strategy_name=near_strangle.name,
include_option_strategy=True,
hedging_instrument_type="FXSPOT",
hedging_frequency="1BD",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
dh_far_strangle = sig.DeltaHedgingStrategy(
currency=far_strangle.currency,
start_date=far_strangle.start_date,
option_strategy_name=far_strangle.name,
include_option_strategy=True,
hedging_instrument_type="FXSPOT",
hedging_frequency="1BD",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
[ ]:
dh_near_strangle.history().plot.line(legend=True, label="Delta-hedged 1M strangle")
dh_far_strangle.history().plot.line(legend=True, label="Delta-hedged 3M strangle");
Date specific roll#
Rolling strangles based on signal dates
[ ]:
def strangle_creation_method_date_dependent(strategy, dt, positions) -> dict:
"""
Creates the strangles needed by looking at the delta signal.
"""
size_date = strategy.size_date_from_decision_dt(dt)
# Date roll logic
if dt.date() not in delta_signal.index.date:
return {}
# Look up existing positions
strategy.close_out_options(dt)
# Look up near and far delta strikes from signal
signal_column = "1M_delta" if strategy.maturity == "1M" else "3M_delta"
# Get latest delta signal
latest_delta = delta_signal.loc[:size_date, signal_column][-1]
# Strangle
call = strategy.group.get_option(
option_type="Call",
strike=latest_delta,
strike_type="Delta",
start_date=size_date,
maturity=strategy.maturity,
)
put = strategy.group.get_option(
option_type="Put",
strike=-latest_delta,
strike_type="Delta",
start_date=size_date,
maturity=strategy.maturity,
)
# Return weights
return {
call: 1,
put: 1,
}
[ ]:
near_strangle_date_dependent = sig.DynamicOptionsStrategy(
maturity="1M",
basket_creation_method=strangle_creation_method_date_dependent,
currency=ccy,
group_name=fx_group,
start_date=start_date,
rolling_frequencies=["1BD"], # check delta daily
close_out_at_roll=False, # don't close out at roll anymore automatically
target_quantity=1,
target_type="SpotNotional",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
far_strangle_date_dependent = sig.DynamicOptionsStrategy(
maturity="3M",
basket_creation_method=strangle_creation_method_date_dependent,
currency=ccy,
group_name=fx_group,
start_date=start_date,
rolling_frequencies=["1BD"], # check delta daily
close_out_at_roll=False, # don't close out at roll anymore automatically
target_quantity=1,
target_type="SpotNotional",
initial_cash=0,
total_return=False,
include_trading_costs=False,
)
near_strangle_date_dependent.build()
far_strangle_date_dependent.build()
[ ]:
near_strangle_date_dependent.history().plot.line(legend=True, label="1M strangle")
far_strangle_date_dependent.history().plot.line(legend=True, label="3M strangle");