Latest release notes#
For information about platform versions, please see:
For information on previous framework versions, please see:
v9.5#
New to v9?
See Introduction to v9.0 for help updating your code.
Improvements#
Rolling strategies: Improved consistency across rolling strategy classes with RollingStrategyBase
class#
Previously, certain methods were only available for RollingFuturesStrategy
, but not for other rolling strategy classes.
To improve consistency between rolling strategy classes, RollingStrategyBase
base class has been created. It contains the same attributes and methods that are shared between all its subclasses.
The rolling_schedule
method and specialized rolling_table
property have now been implemented in all rolling strategy classes, including:
RollingSwapStrategy
RollingOptionStrategy
RollingBondStrategy
RollingCreditIndexStrategy
RollingStructureBasketStrategy
RollingFXForwardStrategy
RollingOptionsStrategyBase
RFPriceIndex
rolling_schedule
returns the roll schedule, while rolling_table
returns the strategy’s rolling table as a pandas DataFrame.
Code example:
import datetime as dtm
import sigtech.framework as sig
sig.init()
rc = sig.RollingOptionStrategy(
currency="USD",
start_date=dtm.date(2018, 1, 4),
end_date=dtm.date(2019, 1, 4),
group_name="USDJPY OTC OPTION GROUP",
option_type="Call",
maturity="3M",
rolling_frequencies=["1M"],
strike_type="SPOT",
strike="ATM+10%",
)
_rolling_schedule = rc.rolling_schedule())
_rolling_table = rc.rolling_table
Rolling options strategy: Added scaling to strategy cash#
Previously, RollingOptionStrategy
would trade one option or one option strategy by default, regardless of how much initial_cash
was held.
To improve the behavior of the RollingOptionStrategy
class, cash needs to be taken into consideration to size the number of options. To enable this, two new additions have been introduced:
New
target_type
("PVAsProportionOfNAV"
) enables the sizing of the number of options depending on the net asset value (NAV), rather than a fixed amount of present value (PV).New parameter
greek_neutral_nav_scale
enables the sizing of the number of delta-neutral structures that the strategy would hold. This also fixes the issue of when the target_type is a Greek (e.g. `target_type=’Delta’).
As a result, RollingOptionStrategy
now sizes the number of options using the cash.
Code example to test PVAsProportionOfNAV
:
rc = sig.RollingOptionStrategy(
currency='USD',
start_date=dtm.date(2018, 1, 4),
end_date=dtm.date(2018, 6, 4),
group_name=g,
option_type='Call',
maturity='3M',
rolling_frequencies=['1M'],
strike_type='SPOT',
strike='ATM',
target_type='PVAsProportionOfNAV',
target_quantity=1,
)
rc.history()
Code example to test greek_neutral_nav_scale
:
butterfly = sig.RollingButterflyOptionsStrategy(
start_date=dtm.date(2018, 1, 4),
end_date=dtm.date(2019, 7, 4),
initial_cash=1000,
group_name=group.name,
rolling_frequencies=['3M'],
maturity='12M',
option_type='Call',
butterfly_direction='long',
strike_type='SPOT',
strike_1='ATM',
strike_2='ATM+3%',
strike_3='ATM+5%',
target_type='Delta',
target_quantity=0,
greek_neutral_nav_scale=1
)
butterfly.history()
Options: metrics
method returns vega weighted implied volatility#
Previously when calling the metrics
method on an options strategy, it would return the sum of all Greeks, as well as the average implied volatility of the options held.
To improve the output, a ‘Vega Weighted Implied Volatility’ column is now added to any metrics
method output. This is particularly useful for portfolios holding options with different expiries.
Code example:
import datetime as dtm
import sigtech.framework as sig
import datetime as dtm
sig.init()
d = dtm.date(2020, 2, 24)
group = sig.obj.get('EURUSD OTC OPTION GROUP')
def basket(strategy, dt, positions, **additional_parameters):
size_date = strategy.size_date_from_decision_dt(dt)
call = group.get_option(start_date=size_date, option_type='Call', strike=0.25, strike_type='Delta', maturity='3M')
put = group.get_option(start_date=size_date, option_type='Put', strike=-0.25, strike_type='Delta', maturity='3M')
return {call:1, put:-100}
strat = sig.DynamicOptionsStrategy(
currency='GBP',
start_date=d,
rolling_frequencies=['1M'],
group_name=group.name,
basket_creation_method=basket,
initial_cash=0,
total_return=False,
t0_option_selection=True,
close_out_at_roll=True,
target_quantity=100,
target_type='Vega',
net_target_quantity=False,
data_points=['NEW_YORK_1700']
)
strat.metrics()
Options: Improved calculations by adding net_target_quantity
flag variable to get net Greeks in option strategies#
Previously, the greeks
and metrics
methods for option strategies would only take the sum of all Greeks in an options strategy.
greeks
and metrics
methods for option strategies now match the net_target_quantity
flag. You can choose whether to net Greeks or not by setting the net_target_quantity
variable:
If set to
True
, the sum of values is calculatedIf set to
False
, the sum of absolute values is calculated
Code example:
import datetime as dtm
import sigtech.framework as sig
import datetime as dtm
sig.init()
d = dtm.date(2020, 2, 24)
group = sig.obj.get('EURUSD OTC OPTION GROUP')
def basket(strategy, dt, positions, **additional_parameters):
size_date = strategy.size_date_from_decision_dt(dt)
call = group.get_option(start_date=size_date, option_type='Call', strike=0.25, strike_type='Delta', maturity='3M')
put = group.get_option(start_date=size_date, option_type='Put', strike=-0.25, strike_type='Delta', maturity='3M')
return {call:1, put:-1}
strat = sig.DynamicOptionsStrategy(
currency='USD',
start_date=d,
end_date=dtm.date(2020, 3, 30),
rolling_frequencies=['1BD'],
group_name=group.name,
basket_creation_method=basket,
initial_cash=0,
total_return=False,
t0_option_selection=True,
close_out_at_roll=True,
target_quantity=100,
target_type='Vega',
net_target_quantity=False
)
strat.greeks(dollar_greeks=True, net_greeks=False)
New features#
New methods available for obtaining volatility series#
Added new methods to get historical butterfly volatility, at-the-money volatility, and volatility for a given tenor and delta for equity. You can use these to get a volatility series for certain delta on the volatility surface.
The following code blocks demonstrate the different methods for getting volatility series:
import sigtech.framework as sig
sig.init()
vs = sig.obj.get('SPX INDEX VOLSURFACE')
Get 1Y tenor 50 delta risk reversal:
vs.risk_reversal(tenor='1Y', delta=50).plot()
Get 1Y tenor 50 delta butterfly:
vs.butterfly(tenor='1Y', delta=50).plot()
Get 1Y tenor at-the-money volatility:
vs.atm_vols_for_tenor('1Y').plot()
Get 1Y tenor 25 delta call volatility:
vs.vols_for_tenor(delta=25, tenor='1Y')
Get 1Y tenor 25 delta put volatility:
vs.vols_for_tenor(delta=-25, tenor='1Y')
FX: Implemented volatility and forward curve shifts for FX#
When implementing volatility or forward curve shifts for FX, the change_type
parameter can now be set to either of the following arguments:
'RETURN'
: Percentage change'DIFF'
: Absolute value change
The following code blocks demonstrate a volatility curve shift:
import sigtech.framework as sig
from sigtech.framework.infra.data_adapter.simulations.simulation_adapter import SimAdapter
import datetime as dtm
sig.init()
### VOL CURVE SHIFT ###
vol_curve_ticker = 'EURUSD VOLSURFACE'
Shift volatility curve to at-the-money (ATM) strike of 1.25:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_vol_curve_modifier(
instruments=[vol_curve_ticker],
overwrites={dtm.date(2009, 3, 2): 1.25},
change_type='PRICE',
)
sig.obj.get(vol_curve_ticker).history()
Shift volatility curve horizontally by 0.1 to the right, so new_ATM_strike = old_ATM_strike + 0.1:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_vol_curve_modifier(
instruments=[vol_curve_ticker],
overwrites={dtm.date(2009, 3, 2): 0.1},
change_type='DIFF',
)
sig.obj.get(vol_curve_ticker).history()
Shift volatility curve horizontally by 2% of spot price to the left, so new_ATM_strike = old_ATM_strike - (2% * spot)
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_vol_curve_modifier(
instruments=[vol_curve_ticker],
overwrites={dtm.date(2009, 3, 2): -0.02},
change_type='RETURN',
)
sig.obj.get(vol_curve_ticker).history()
Forward curve shifts also take an additional overwrite_type
parameter:
'POINT'
: Single value overwrite'FLAT'
: Overwrite all tenor values'PARALLEL'
: Overwrite all tenors and keep absolute difference between them'RATIO'
: Overwrite all tenors and keep relative difference between tenors
The following code blocks demonstrate a forward curve shift:
### FWD CURVE SHIFT ###
fwd_curve_ticker = 'EURUSD FORWARD RATE CURVE'
Overwrite only 3 Feb 2009 tenor to 1.0:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_curve_modifier(
instruments=[fwd_curve_ticker],
overwrites={dtm.date(2009, 2, 3): 1.0},
change_type='PRICE',
overwrite_type='POINT'
)
sig.obj.get(fwd_curve_ticker).history()
Shift all tenor values by 0.098 upwards from 3 Feb 2009 onwards:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_curve_modifier(
instruments=[fwd_curve_ticker],
overwrites={dtm.date(2009, 2, 3): 0.098},
change_type='DIFF',
overwrite_type='PARALLEL'
)
sig.obj.get(fwd_curve_ticker).history()
Overwrite all tenor values on 3 Feb 2009 to 4 Jan 2005 original value +9%:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_curve_modifier(
instruments=[fwd_curve_ticker],
overwrites={dtm.date(2009, 2, 3): 0.09},
change_type='RETURN',
overwrite_type='FLAT'
)
sig.obj.get(fwd_curve_ticker).history()
Overwrite 3 Feb 2009 to 0.97 and adjust all other tenors on 3 Feb 2009 to keep the relative difference between tenors:
sim_adapter = SimAdapter()
sim_adapter.push_to_data_service()
sim_adapter.add_overwrite_curve_modifier(
instruments=[fwd_curve_ticker],
overwrites={dtm.date(2009, 2, 3): 0.97},
change_type='PRICE',
overwrite_type='RATIO'
)
sig.obj.get(fwd_curve_ticker).history()