Framework v7

This page is about a previous version of the SigTech framework.

Please see Release notes | SigTech framework v8: Latest for information on the latest framework version.

Pages in this category

On this page

v7.40.0 - v7.48.0 (Dec 2021 - Apr 2022)

In this section

v7.48.0 (11 Apr 2022)

Custom trade sizing methods now available

You can now define your own custom sizing methods in terms of quantities. Previously, custom sizing was only available via the traded instrument. The below code block demonstrates how to define a custom sizing method.

import sigtech.framework as sig
import datetime as dtm

def percent_sizing(instrument_name, units, dt):
            return units / 100.0

sig.register_sizing_method('PERCENT', percent_sizing)

class MyStrategy(sig.DailyStrategy):
    def strategy_initialization(self, dt):
        # Order 200% of the stock
        self.add_position_target(dtm.date(2021,7,10),
                                 instrument_name='1003331.SINGLE_STOCK.TRADABLE',
                                 units=200.0,
                                 unit_type='PERCENT'
                                )


strat = MyStrategy(
    currency='USD',
    start_date=dtm.date(2021,7,1)
)

Default configuration now available for single stock strategy start date

Previously, retrieving single stock strategies via the sig.get_single_stock_strategy call would allow you to specify a minimum start date or revert to a default. You can now configure this default via the environment flag DEFAULT_RS_START_DATE. The following code block demonstrates this new functionality.

import sigtech.framework as sig
import datetime as dtm

# After intitializing your environment...
sig.env()[sig.config.DEFAULT_RS_START_DATE] = dtm.date(2009, 1, 2)

Rolling options strategies can now target notional values based on NAV

Previously, rolling option strategies would allow either a fixed target at each roll or a custom value. You can now set the target to scale with the size of the strategy via the target_type parameter. This parameter takes two values:

  • StrikeNotionalAsProportionOfNAV

  • SpotNotionalAsProportionOfNAV

The following code block demonstrates this added functionality using a rolling option straddle.

import sigtech.framework as sig
import datetime as dtm
import seaborn as sns

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

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

# Create strategy
straddle = sig.Straddle(
    currency = equity_option_group.underlying.currency,
    start_date = dtm.date(2018, 10, 1),
    group_name = equity_option_group.name,
    strike_type = 'Delta',
    strike = 0.5,
    maturity = '3M',
    rolling_frequencies = ['1M'],
    target_quantity = 1, # 100% of strategy value
    target_type = 'StrikeNotionalAsProportionOfNAV', # 'SpotNotionalAsProportionOfNAV' also available
    close_out_at_roll = True,
)

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

Drawdown plot added to the performance report

The performance report now includes a drawdown plot with additional enhancements.

v7.46.0 (07 Mar 2022)

Calculate the approximate return of a signal strategy

You can now calculate the approximate return of a signal strategy based on its weights, without having to construct the entire strategy. This allows you to perform multiple evaluations quickly and efficiently. The following code block demonstrates this new functionality.

import sigtech.framework as sig
import datetime as dtm
import numpy as np

from sigtech.framework.default_strategy_objects.rolling_futures import es_index_front

signal_ts = np.sign(es_index_front().history())
signal = sig.signal_library.from_ts(signal_ts.to_frame(es_index_front().name))

st=sig.SignalStrategy(
    currency="USD",
    start_date=dtm.date(2018, 3, 1),
    signal_name=signal.name,
    rebalance_frequency="1W",
    include_trading_costs=False,
    total_return=False,
    unit_type='WEIGHT'
)
st.approx_return().plot()

v7.45.0 (24 Feb 2022)

Add expected returns to portfolio optimisations

You can now add your own estimates of expected returns when using the PortfolioOptimizer. Previously, functionality had been limited to the historical mean returns. Whilst this is still the default behaviour, you now have the option of using proprietary models for stock predictions and inputting your expectations into the optimisation framework during portfolio construction.

The following code block compares the previous and new approaches.

import sigtech.framework as sig
import pandas as pd
import numpy as np

stocks = ['A', 'B']
dates = pd.date_range('2020-01-01', freq='b', periods=20)
returns = pd.DataFrame(np.random.normal(1, 1e-3, (len(dates), len(stocks))), index=dates, columns=stocks)
expected_returns = pd.Series([1,2], index=stocks)

po = sig.PortfolioOptimizer().require_weights_l2_penalty().require_maximum_return(expected_returns=expected_returns)

po.calculate_weights(returns)

New IntradaySignalStrategy building block added

The new IntradaySignalStrategy building block clones the functionality of the existing SignalStrategy class but sets the defaults of certain parameters to intraday-focused values. This offers a more efficient way of creating intraday strategies.

The default parameters are: use_signal_for_rebalance_dates=True, t0_execution=True, execution_delay='5 minutes'.

The following code block demonstrates the use of this new building block.

import sigtech.framework as sig
import datetime as dtm

intraday_signal = pd.DataFrame(
    {'ECZ22 CURNCY': [1, 0, 1]},
    index = [dtm.datetime(2021,1,5, 21, 0, 0),
             dtm.datetime(2021,1,5, 21, 0, 1),
             dtm.datetime(2021,1,5, 21, 0, 2)]
)

intraday_strategy = sig.IntradaySignalStrategy(
    currency='USD',
    signal_name=sig.signal_library.from_ts(intraday_signal).name,
    start_date=intraday_signal.first_valid_index()
)
intraday_strategy.build()

New SigMaster method creates customised universes on different dates

The new SIGMaster method get_universe_generator() returns an object offering the same filtering capabilities as SIGMaster but can also be applied to a customised universe across different dates.

Applying the filter using apply() returns a {date: universe} dictionary. The following code block demonstrates this added functionality.

import sigtech.framework as sig
import datetime as dtm

env = sig.init()
sm = env.sig_master()

# Get universe generator (same syntax as SIGMaster)
ug = sm.get_universe_generator()
ug = ug.filter(value='US', column='EXCHANGE_COUNTRY_ISO2', op='==')
ug = ug.filter(value='Technology', column='TRBC_ECONOMIC_SECTOR', op='==')

# Apply filters on specific dates
dates = [dtm.date(2022, 2, 2), dtm.date(2022, 3, 2)]
universes = ug.apply(dates)

This dictionary can be used as an input for the EquityUniverseFilter for more advanced filtering operations.

# Use as input for EquityUniverseFilter
euf = sig.EquityUniverseFilter(universes)

New methods for bulk data retrieval during strategy construction

You can now retrieve bulk data in advance when building strategies. This allows for the construction of a large number of strategies in one go, rather than building them individually.

The following code block demonstrates the use of these new methods in the specific case of reinvestment strategies.

import sigtech.framework as sig
env = sig.init()
env.set_shared_memory(False)

const = sig.obj.get('DAX INDEX').constituents_dict()

# Turn the list of tickers into a list of ready-built reinvestment strategies
sig.get_single_stock_strategy(list(const.values())[0])

A more general approach is offered by sig.calc_history(list_of_strategies). This retrieves all of the data used by the listed strategies and then runs those strategies.

This functionality replaces the existing DAGs methods.

Functions added to convert factor exposures to stock weights

More predefined functions have been added to convert factor exposures to stock weights when using the EquityFactorBasket.

Functions to weight stocks by their market cap or cumulative factor score are accessible through sig.EquityFactorBasket.AVAILABLE_FACTOR_TO_WEIGHT_FUNCTIONS.

You now have the option of combining factor scores after normalisation (z_score=True) and/or only take the long leg (rather than both long & short legs) when ranking stocks using the proportion keyword by passing long_only=True.

The following code block demonstrates these new functions.

import sigtech.framework as sig
import pandas as pd

dates = pd.bdate_range("2021-06-01", "2021-06-30", freq='b')

equity_filter = sig.EquityUniverseFilter('SX5E INDEX')
equity_filter.add('MARKETCAP', 'top', 20, 'Daily')
universe = equity_filter.apply_filter(dates)
all_tickers = list(set().union(*universe.to_dict().values()))
sig.get_single_stock_strategy(all_tickers)

factor_exposures = sig.FactorExposures()
factor_exposures.add_raw_factor_timeseries('Size', history_field='MARKETCAP')
factor_exposures.add_raw_factor_timeseries('Volume', history_field='Volume')

size_strategy_v1 = sig.EquityFactorBasket(
    universe_filter=universe,
    universe_mapping={s: f'{s} REINV STRATEGY' for s in all_tickers},
    factor_exposure_generator=factor_exposures,
    currency="USD",
    start_date=dates[0],
    end_date=dates[-1],
    rebalance_frequency="1BD",
    factors_to_weight_kwargs={'proportion': 0.1, 'factor_weights': {'Size': -1, 'Volume': -1}, 'long_only': False, "z_score": True},
    factors_to_weight_function=sig.EquityFactorBasket.AVAILABLE_FACTOR_TO_WEIGHT_FUNCTIONS.FACTOR_WEIGHTED
)

v7.44.0 (07 Feb 2022)

New argument added to the initialisation function

Previously, attempting to initialise your environment more than once - with init() - would terminate the notebook execution and generate a long error message. This error message has been simplified and an additional argument - repeat_mode - has been added to the init() function. Attempts to initialise an already initialised environment will produce different behaviours based on the value of repeat_mode:

  • 'reinit' - Destroys the current environment and creates a new one. A warning message explaining these actions is printed

  • 'error' - The execution terminates and a clearer error message is printed

  • 'warning' - A warning is printed and the init() has no effect (default)

These behaviours are described in the code block below:

import sigtech.framework as sig

sig.init()
# The environment is now initialised

sig.init()
# The call above has no effect (default is 'warning')

sig.init(repeat_mode='reinit')
# The call above destroys the current environment and creates a new one

sig.init(repeat_mode='error')
# The execution terminates with an error

Delta Hedging Rebalance Dates

When hedging an option using the DeltaHedgingStrategy, you can now choose for hedge adjustments to occur only on dates when the options are rolled. This can be achieved by setting the rebalance_hedge_on_roll parameter to True. This reduces turnover from the hedge rebalancing and concentrates trading on the same day for both the options strategy and hedge. However, the delta will not be exactly hedged between trades. The below code block demonstrates the use of this new functionality.

import sigtech.framework as sig
import datetime as dtm

underlying = sig.RollingOption(
    currency="USD",
    start_date=dtm.date(2017, 1, 1),
    end_date=dtm.date(2017,12,1),
    group_name="SPX INDEX OTC OPTION GROUP",
    option_type="Call",
    maturity="3M",
    rolling_frequencies=["1M"],
    strike_type="SPOT",
    strike="SPOT+10%",
    ticker='USD SPX TEST DHS CALL RO'
)

strat = sig.DeltaHedgingStrategy(
    currency="USD",
    start_date=underlying.start_date,
    end_date=underlying.end_date,
    option_strategy_name=underlying.name,
    hedging_instrument_type="ETF",
    rebalance_hedge_on_roll=True
)

You can also pass a list of dates to rebalance the hedge on, using the custom_hedge_dates parameter. The below code block demonstrates this new feature.

import sigtech.framework as sig
import pandas as pd
import datetime as dtm

underlying = sig.RollingOption(
    currency="USD",
    start_date=dtm.date(2017, 1, 1),
    end_date=dtm.date(2017,12,1),
    group_name="SPX INDEX OTC OPTION GROUP",
    option_type="Call",
    maturity="3M",
    rolling_frequencies=["1M"],
    strike_type="SPOT",
    strike="SPOT+10%",
    ticker='USD SPX TEST DHS CALL RO'
)

custom_dates = [
    underlying.start_date + pd.tseries.offsets.BDay(2),
    dtm.date(2017, 5, 10),
    dtm.date(2017, 10, 2)
]

strat = sig.DeltaHedgingStrategy(
    currency="USD",
    start_date=underlying.start_date,
    end_date=underlying.end_date,
    option_strategy_name=underlying.name,
    hedging_instrument_type="ETF",
    custom_hedge_dates=custom_dates
)

New threshold function added to SignalStrategy for rebalancing

The SIGNALCHANGE function has been added to the AVAILABLE_THRESHOLD_FUNCTIONS for the SignalStrategy. When applied, the function will trigger a rebalance if the signal value changes. This replaces the previous approach which would rebalance an instrument regardless of whether or not the signal value had changed.

The following code block demonstrates the use of this new function.

import sigtech.framework as sig
import numpy as np
import pandas as pd
import datetime as dtm
import sigtech.framework.signal.library as signal_lib

from sigtech.framework.signal.signal_strategy import SignalStrategy
from sigtech.framework.default_strategy_objects.rolling_futures import es_index_front

signal_ts = np.sign(es_index_front().history())
signal_obj = signal_lib.from_ts(signal_ts.to_frame(es_index_front().name))

strategy_w_threshold = sig.SignalStrategy(
currency='USD',
start_date=dtm.datetime(2010, 1, 4),
end_date=dtm.datetime(2012, 2, 6),
signal_name=signal_obj.name,
use_signal_for_rebalance_dates=True,
threshold_function=sig.SignalStrategy.AVAILABLE_THRESHOLD_FUNCTIONS.SIGNAL_CHANGE,
)

v7.43.0 (26 Jan 2022)

Back-adjusted futures prices now available

You now have the ability to work with back-adjusted futures series in order to avoid triggering spurious trading signals during the roll. The following code block demonstrates this functionality by setting the back_adjusted parameter to True.

import sigtech.framework as sig
import numpy as np
import pandas as pd

pi = sig.RFPriceIndex(
    currency='USD',
    start_date=dtm.date(2019, 1, 1),
    end_date=dtm.date(2020, 6, 4),
    contract_code='C ',
    contract_sector='Comdty',
    front_offset='-4:-1',
    back_adjusted=True
)

v7.42.0 (21 Jan 2022)

Custom aggregation metrics added to EquityUniverseFilter

You can now access the full set of methods and properties available for a single stock when implementing custom aggregation metrics via the EquityUniverseFilter. These new capabilities are accessible by passing an additional argument - stock_obj - to the aggregation function.

The code block below demonstrates the use of this new functionality.

import sigtech.framework as sig
import datetime as dtm

def compute_rolling_volatility(ts, stock_obj):
    # ts may not be used
    adjusted_prices = stock_obj.adjusted_price_history(True, True)
    return 1 / adjusted_prices.pct_change().dropna().rolling(window=21).std()

euf = sig.EquityUniverseFilter('SPX INDEX')
euf.add('Volume', 'top', 5, 'Daily', compute_rolling_volatility)

v7.41.0 (18 Jan 2022)

New functionality for hedging FX forwards

A new parameter has been added to the FXForwardHedgingStrategy class which allows you to hedge using multiple FX Forwards in different currencies. By setting the use_holdings_for_hedge_ccy parameter to True, the currencies of the bottom level assets in your strategy will be hedged in proportion to their respective weights.

This replaces the previous approach of hedging the total value of the strategy in its currency into the FXForwardHedgingStrategy currency. This change allows for a better hedge of complex, multi-currency strategies. The below code block demonstrates the construction of a strategy using the use_holdings_for_hedge_ccy parameter.

import sigtech.framework as sig
import datetime as dtm
import pandas as pd
import numpy as np

sp500_rfs = sig.default_strategy_objects.rolling_futures.es_index_front()
ftse_rfs = sig.default_strategy_objects.rolling_futures.z_index_front()

underlying_strat = sig.BasketStrategy(
    currency = 'EUR',
    constituent_names = [sp500_rfs.name, ftse_rfs.name],
    weights = [0.5, 0.5],
    start_date = dtm.date(2020,1,1),
    rebalance_frequency = '1W'
)

hedged_strat = sig.FXForwardHedgingStrategy(
    currency = 'AUD',
    strategy_name = underlying_strat.name,
    hedging_tenor = '1M',
    use_holdings_for_hedge_ccy = True,
    start_date = underlying_strat.start_date,
    hedge_rebalance_threshold = 0.1,
    exposure_rebalance_threshold = 0.1
)

As hedges are applied after orders are placed, this added functionality may not be suitable for high turnover strategies.

Execution points parameter added

A new option ('EXECUTION_PTS') has been added for the type of strategy time points. This gives the times where orders are executed on all levels in the strategy. This can be used as an input to interactive_portfolio_table, historic_positions and strategy_dt_list.

Example:

import sigtech.framework as sig
import datetime as dtm

# Use default strategy
es = sig.default_strategy_objects.rolling_futures.es_index_front()

# Example of retrieving execution times
execution_times = es.strategy_dt_list('EXECUTION_PTS')

# Example of obtaining positions at execution times
positions_df = es.inspect.historic_positions('EXECUTION_PTS')

# Example of using execution times in portfolio table
es.plot.portfolio_table('EXECUTION_PTS', start_dt=dtm.date(2019,1,1), end_dt=dtm.date(2020,1,1))

Custom roll schedule added to RollingFXForward

The RollingFXForwardStrategy now allows you to input a rolling frequency or a custom roll schedule . In particular it allows for the monthly or daily roll of longer term forwards. This replaces the previous approach which restricted you to a roll offset from the forward maturity.

The below code block demonstrates the use of the rolling_frequencies parameter - set to roll monthly - when trading a 3 month rolling EUR USD forward.

import sigtech.framework as sig
import datetime as dtm

rfxs1 = sig.RollingFXForwardStrategy(
    long_currency="EUR",
    currency="USD",
    forward_tenor="3M",
    start_date=dtm.date(2010, 9, 15),
    rolling_frequencies=['1M'],
)

This can be contrasted with the use of the custom_roll_datesparameter which allows you to specify a particular roll schedule. The following code block demonstrates the use of this parameter, setting a schedule containing only two dates.

import sigtech.framework as sig
import datetime as dtm

rfxs2 = sig.RollingFXForwardStrategy(
    long_currency="EUR",
    currency="USD",
    forward_tenor="3M",
    start_date=dtm.date(2010, 9, 15),
    custom_roll_dates=[dtm.date(2010, 10, 18), dtm.date(2011, 10, 25)],
)

New functionality added to the PerformanceReport

Two new views have been added to the PerformanceReport which allow for the inclusion of currency based metrics. The following code block demonstrates how to include these new views.

import sigtech.framework as sig
import datetime as dtm
import pandas as pd

rfs = sig.RollingFutureStrategy(
    currency='USD',
    start_date=dtm.date(2020,1,1),
    contract_code='ES',
    contract_sector='INDEX',
    rolling_rule='front',
    fixed_contracts=1
)
rfs.build()

dates = pd.date_range('2021-01-04', '2021-12-01', freq='1W-MON')

sig.PerformanceReport(rfs, views=[sig.View.SUMMARY_SINGLE_CCY, sig.View.SUMMARY_ROLLING_CCY_SERIES], dates=dates).report()

The new aum argument allows you to pass a representative AUM figure. This is useful in strategies where initial_cash=0 as it avoids dividing by zero. Following on from the above code block, the use of this new argument is demonstrated below.

sig.PerformanceReport(rfs, dates=dates, views=[sig.View.SUMMARY_SINGLE]).report()

first_contract = sig.obj.get(rfs.rolling_table.rolled_in_contract.iloc[0])
first_contract_value = first_contract.history().asof(rfs.start_date.strftime("%Y-%m-%d")) * first_contract.contract_size

sig.PerformanceReport(
    rfs,
    dates=dates,
    views=[sig.View.SUMMARY_SINGLE],
    aum=first_contract_value
).report()

In addition, you can now generate a PerformanceReport with compounded metrics by passing compound_metrics=True . The below code block demonstrates this feature by building on the examples provided above.

sig.PerformanceReport(
    rfs,
    dates=dates[-5:],
    views=[sig.View.SUMMARY_ROLLING_SERIES],
    aum=first_contract_value,
    compound_metrics=True
).report()

New technical indicators added to the platform

A new set of indicators (MACD, KDJ, RSI, BOLL, WR, ADX) for the technical analysis of price movements has been added to sigtech.framework.signal.library.technical_indictors.

v7.40.0 (20 Dec 2021)

New methods available for defining and applying custom risk measures when sizing a strategy

It is now possible to define a custom risk measure and use it to size positions in a strategy. The addition of a new parameter - sizing_method - and a new option - CUSTOM - for the existing unit_type parameter replaces the previously used PV01 mechanism for sizing swaps. The following code block describes this new functionality, where the ‘pv01_to_notional' method is defined on rates instruments - like swaps - to trade PV01.

self.add_position_target(dt, underlying, target_units,
                         unit_type='CUSTOM',
                         sizing_method='pv01_to_notional')

This method can be used as part of building a custom strategy. Please see our Custom strategies page to learn more.

Wider range of swap data now available via Default Universe datasets

The extension of the DefaultUniverses functionality allows for easy access and caching of returns series for single stocks, as well as returns, PV01, and rates for forward starting swaps.

The following code block demonstrates the retrieval of a single stock strategy returns series for specific stock tickers:

from sigtech.framework.experimental.default_universes import DefaultUniverses

du = DefaultUniverses(local_path='du_cache', force_local=True)
df_stocks = du.universe(
    'Specific Stocks',
    tickers=[
        '1000045.SINGLE_STOCK.TRADABLE',
        '1001962.SINGLE_STOCK.TRADABLE'
    ]
)

This can be contrasted with the code block below which demonstrates the retrieval of data for a USD 5Y swap starting in 3 months and a USD 3Y swap starting immediately:

df_swaps = du.universe(
    'Fair Swap Rates',
    tickers=['USD 3Mx5Y', 'USD 3Y']
)

Additional parameters added to the Basket Strategy

The BasketStrategy has been extended to include: 1) unit types used for weights, and 2) long-short constituent conversion.

The parameters added to the strategy are:

  • convert_long_short_weight: Determines if the strategy applies long-short conversion (default is False)

  • use_db_for_short_version: Determines if the long-short conversion examines the object cache for the same short strategy (default is False)

  • unit_type: Sets the units used for weighting (default is 'WEIGHT')

The below code block demonstrates the use of these new features.

import sigtech.framework as sig
import datetime as dtm
from sigtech.framework.default_strategy_objects.rolling_futures import cl_comdty_f_0, co_comdty_f_0

b = sig.BasketStrategy(
    currency='USD',
    start_date=dtm.datetime(2013, 12, 16),
    end_date=dtm.datetime(2014, 1, 15),
    constituent_names=[
        cl_comdty_f_0().name,
        co_comdty_f_0().name,
    ],
    weights=[0.5, -0.25],
    rebalance_frequency='EOM',
    convert_long_short_weight=True,
)

v7.30.0 - v7.38.0 (Oct 2021 - Dec 2021)

In this section

v7.38.0 (13 Dec 2021)

Greater Flexibility when Retrieving Futures Contracts

The new get_future_curve method allows users to retrieve all of the contracts within a FuturesContractGroup with a price on the requested date. This creates a more efficient process by removing the need to search for contracts expiring after the specified date.

import sigtech.framework as sig

g = sig.obj.get('CL COMDTY FUTURES GROUP')
g.get_future_curve(dtm.date(2020,1,1))

Once the required contracts have been retrieved, the plot_curve_on_dates __ and plot_end_on_curve_on_dates methods allow users to generate visualisations of all available contract prices.

import sigtech.framework as sig
import pandas as pd

g = sig.obj.get('CL COMDTY FUTURES GROUP')
g.curve_plots.plot_curve_on_dates(pd.date_range('2015-01-01', '2021-11-22', freq='Y'))

New Credit Index Trading Strategy Available

Users now have the ability to construct strategies that trade credit index instruments, with the introduction of the RollingCreditIndexStrategy. This added functionality also allows for the reinvestment of coupons. The following code block demonstrates how this strategy can be built:

from sigtech.framework.strategies.rolling_credit_index_strategy import RollingCreditIndexStrategy
import datetime as dtm

s = RollingCreditIndexStrategy(
    start_date=dtm.date(2013, 12, 1),
    end_date=dtm.date(2021, 2, 10),
    index='XOVER',
    tenor='5Y',
    currency='EUR',
    reinvestment_mode='Coupon',
    rebalance_frequency='3M',
    roll_offset_days=0
)
s.history().plot();

v7.37.0 (03 Dec 2021)

New Function for Swaption Volatility Data

Users can now retrieve daily, at-the-money swaption normal volatility data. This data is available for both rolling and fixed expiry swaptions.

If you would like to access SigTech's swaptions data, please contact sales@Sigtech.com.

Extra Features Added to the Rolling Swap Strategy

New functionality has been added which allows for the retrieval of:

  • The daily spot or forward swap fair rate

  • The swap's DV01

  • The daily P&L for entering a fair swap on the previous day and holding it for one day.

The below code block demonstrates the use of the fair_swap_rate:

import sigtech.framework as sig
import datetime as dtm

sig.InterestRateSwapGroup.fair_swap_rate(
    'USD',
    '5y',
    dtm.date(2017, 4, 1),
    dtm.date(2017, 4, 10)
)

Retrieve the Most Liquid Stock from a Given Ticker

The get_most_liquid_stock function has been added to the platform. The function returns the most liquid stock within a specified tradable ticker, exchange ticker, or list of tickers. The following code block demonstrates the use of the function.

import sigtech.framework as sig
from sigtech.framework.equities.liquidity_indicators import LiquidityIndicators

sig.get_most_liquid_stock(
    exchange_ticker='AAPL',
    rolling_window=30,
    liquidity_function=LiquidityIndicators.rolling_dollar_vol,
    filters={'EXCHANGE_COUNTRY_ISO2': ['US']}
)

Strike Optimisation now Available for Options

A new function has been added which allows users to search for the option strike at a given price level. This facilitates price-targeted investing. The code block below demonstrates the use of this new functionality.

import sigtech.framework as sig
import datetime as dtm

spx_g = sig.obj.get('SPX INDEX OTC OPTION GROUP')
# Find the strike of a 1-year call option that was worth $20.0 on 2021-10-15
spx_g.strike_from_price(20.0, dtm.date(2021, 10, 15), '1Y', 'Call')

Time and Timezone Optionality now Available for Instrument Time Series

Users now have the option of including the time and UTC timezone when calling the history() method on financial instruments. The below code block demonstrates this new functionality.

import sigtech.framework as sig
import datetime as dtm

sig.obj.get('EURUSD CURNCY').history(datetime_index=True)

Flow Decorators Renamed to Job

The Flow decorators previously used on the SigTech platform have been replaced by Job. Hence, FunctionFlow and StrategyFlow are now FunctionJob and StrategyJob. The below code block demonstrates these changes.

import sigtech.framework as sig
from sigtech.framework.default_strategy_objects.rolling_futures import nq_index_front, es_index_front

@sig.deployment.FunctionJob(cpu=1, memory=2048, enabled=True, schedule='0/50 * * * ? *')
def example_function(self):
    self.data = "Persist this string to the datastore"
    print("Hello world!")


@sig.deployment.StrategyJob(task_name='quick',
                            enabled=True,
                            schedule='0/50 * * * ? *',
                            collect=[nq_index_front, es_index_front],
                            outputs=[sig.deployment.HistoryOutput])
def example_basket_strategy():
    return sig.BasketStrategy(
        currency='USD',
        start_date=dtm.date(2010, 1, 4),
        ticker='BASKET',
        constituent_names=[es_index_front().name, nq_index_front().name],
        weights=[0.5, 0.5],
        rebalance_frequency='EOM'
    )

New Functions Available for Retrieval of Raw Market Data

Two new functions for the extraction of raw data have been added to the SigTech platform. These functions facilitate the retrieval of raw market data and allow for the viewing of market swap rates, deposit rates, FRAs, and futures. The below code block demonstrates how these functions can be used.

import sigtech.framework as sig
import datetime as dtm

# Retrieve the time series for the discounted swap rate for a given tenor.
sig.obj.get('USD.D CURVE').get_swap_rate('5Y')

# Different forecasting curves
sig.obj.get('USD.F3M CURVE').get_swap_rate('1Y')
sig.obj.get('USD.F3M CURVE').get_rate('2d','depo')

Add Custom Futures Data

Users wanting to supplement the futures data currently available on the SigTech platform can now upload and utilise their own custom data. This added functionality allows for the utilisation of both individual futures contracts and contract groups.

When extending a contract's history back to a date prior to the one provided by SigTech, it is necessary to alter theFuturesContractGroup.first_contract string to be the new first contract.

New Strategy for Rolling Asset Swaps now Available

For users interested in systematically rolling into OTR bonds, a new RollingAssetSwap strategy has been added to the SigTech platform. This added functionality also includes a method for calculating carry and roll down returns. The below code block provides an example of this new feature:

import sigtech.framework as sig
import datetime as dtm

strat = sig.RollingAssetSwap(
    country='US',
    tenor='10Y',
    currency='USD',
    run_type='ON_THE_RUN',
    start_date=dtm.date(2018, 1, 5),
    notional=100
)

Market Data Widget Available

Users can now view live market data within the SigTech Research Environment. The following code block demonstrates how to generate the market data widget:

import sigtech.framework as sig
import datetime as dtm
from sigtech.framework.experimental.ui.live_view_widget import LiveViewWidget

w = LiveViewWidget(['ESZ21 INDEX'], ['LastPrice'])
w.display()

v7.35.0 (15 Nov 2021)

RFPriceIndex now accepts customisable roll table

Users are now able to apply a custom_roll_table table within the RFPriceIndex class in order to hold any desired contracts. The following code block demonstrates this functionality.

import sigtech.framework as sig
import datetime as dtm

rfpi = sig.RFPriceIndex(
    currency='USD',
    contract_code='TM',
    contract_sector='COMDTY',
    front_offset='-2:-1',
    start_date=dtm.datetime(2009,10,1),
    rolling_rule='custom',
    custom_roll_table=["F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]", "F[1]"]
)

Swaps can now be created using custom roll tables

A list of tuples (swap trade date, swap strat date) can now be passed into the RollingSwapStrategy to allow for more flexibility when creating swap strategies. Please see below code block for an example:

import sigtech.framework as sig
import datetime as dtm

table = [(datetime.date(2010, 1, 5), datetime.date(2010, 6, 16)),
 (datetime.date(2010, 6, 9), datetime.date(2010, 12, 15)),
 (datetime.date(2010, 12, 8), datetime.date(2011, 6, 15)),
 (datetime.date(2011, 6, 8), datetime.date(2011, 12, 21)),
 (datetime.date(2011, 12, 14), datetime.date(2012, 6, 20))]

s = sig.RollingSwapStrategy(
   tenor='10Y',
   currency='USD',
   swap_currency='USD',
   start_date=dtm.date(2010, 1, 4),
   custom_roll_table=table,
)

OIS Swaps are now available

As per below example, OIS swaps are now available on the SigTech platform. You can use them by passing in the OIS as the swap_type argument when instantiating a RollingSwapStrategy object. In the below example a RollingSwapStrategy object is created which will trade 6M forward 10Y OIS swaps and roll them every 6 months.

import sigtech.framework as sig
import datetime as dtm

sig.RollingSwapStrategy(
    tenor='10Y',
    currency='USD',
    swap_currency='USD',
    rolling_frequency_months=6,
    forward_start_months=6,
    start_date=dtm.date(2010, 1, 4),
    swap_type='OIS',
    pv01_target=100,
)

Signal Report

SigTech has introduced an experimental feature called the Signal Report on the platform. This feature allows applying an extensive range of analytical tools on a given data set and strategy, below code block provides a simple example of how it can be used. We would appreciate any feedback on the usability of this feature.

from sigtech.framework.default_strategy_objects.rolling_futures import cl_comdty_f_0, gc_comdty_pre_roll
import sigtech.framework.experimental.analytics.signal_design as sig_sr
import sigtech.framework as sig

import datetime as dtm
import pandas as pd

ASSETS = {'CL': cl_comdty_f_0(), 'GC': gc_comdty_pre_roll()}

# Generate the signals - rolling mean on changes
signals = pd.DataFrame(
    {asset: obj.history().diff().ewm(alpha=1/10).mean() for asset, obj in ASSETS.items()},
    columns=ASSETS.keys()
)

# Delay the signal by one day
features = signals.shift()

# Align the RollingFutureStrategy returns
targets = pd.DataFrame(
    {asset+'_TGT': obj.history() for asset, obj in ASSETS.items()}
).pct_change().dropna()

features = sig_sr.align_a_to_b(a=features, b=targets, how='last')

# Generate the report
sr = sig_sr.SignalReport(X_df=features, Y_df=targets)
sr.interactive_report()

Additional optimizers

The method require_equal_risk_contribution has been added to the portfolio optimizers, a simple demonstration of its use can be viewed in below code block.

from sigtech.framework.analytics.optimization.portfolio_optimizer import PortfolioOptimizer

import pandas as pd

fake_returns_data = pd.DataFrame({
    'A': [-0.000872, -0.000643, 0.000079],
    'B': [-0.007121, -0.013479, -0.006149]
})

opt = (
    PortfolioOptimizer()
    .require_equal_risk_contribution()
    .require_fully_invested()
    .require_long_only()
)
opt.calculate_weights(fake_returns_data)

v7.33.0 (29 Oct 2021)

New operator added to SIGMaster filter

The SIGMaster filter method now accepts the operator 'not in'. This restricts the filter to only include records not contained in the list specified by the user. In the code block below, the filter will exclude all records where the EXCHANGE_COUNTRY_ISO2 is either US or JP.

import sigtech.framework as sig

sm = sig.env().sig_master()
sm.filter(['US', 'JP'], 'EXCHANGE_COUNTRY_ISO2', op='not in')

New custom_roll_table parameter added to RollingSwapStrategy

The RollingSwapStrategy now provides users with the option of specifying a custom_roll_table. The following code block demonstrates the creation of a RollingSwapStrategy which includes this parameter.

import sigtech.framework as sig
import datetime as dtm

roll_swap = sig.RollingSwapStrategy(
    currency='EUR',
    swap_currency='EUR',
    forward_start_months=12,
    rolling_frequency_months=6,
    start_date=dtm.date(2020, 1, 4),
    tenor='5Y',
    roll_offset='-2',
    custom_roll_table=[(dtm.date(2020, 6, 18), dtm.date(2020, 12, 5)),
                 (dtm.date(2020, 12, 1), dtm.date(2021, 6, 5)),
                 (dtm.date(2021, 6, 1), dtm.date(2021, 12, 5)),
                 (dtm.date(2021, 12, 1), dtm.date(2022, 6, 5)),
                 (dtm.date(2022, 6, 1), dtm.date(2022, 12, 5)),
                 (dtm.date(2022, 12, 1), dtm.date(2023, 6, 5))]
)

New parameter available when configuring your research environment

When configuring the research environment, the parameter HISTORY_DATA_CLEAN can be applied to determine whether to use clean or dirty data. When the parameter is set to True clean data is used, and when set to False, dirty data is used. The default value is None which has the effect that clean data will be used if available, otherwise it will use dirty data. The code block below demonstrates this call within the wider context of environment setup.

import sigtech.framework as sig

sig.init()
sig.config.set(sig.config.HISTORY_DATA_CLEAN, True)

Strike value class added for rolling option strategies

A range of strike values have been added for any rolling option strategy inheriting from the RollingOptionStrategyBase class. The below code block demonstrates how AVAILABLE_STRIKE_VALUES can retrieve the available alternatives for the strike_type argument, where the variable straddle is used in this example to represent an instantiated object of the Straddle class.

straddle.AVAILABLE_STRIKE_VALUES.atm_percentage_offset()
straddle.AVAILABLE_STRIKE_VALUES.fx_fwd_percentage_offset()
straddle.AVAILABLE_STRIKE_VALUES.fx_spot_percentage_offset()

Caching user-created strategies

A strategy service has been added to the platform allowing users to cache the results of strategies. To gain access to this feature, please contact John.McCann@Sigtech.com.

v7.32.0 (26 Oct 2021)

New Swaption building blocks now available

A range of swaption strategy classes have been added to therolling_swaption_basket module.These classes include: SwaptionStrangle, DynamicSwaptionsStrategy, and DynamicMultiSwaptionsStrategy.

v7.31.0 (21 Oct 2021)

The RollingFXForwardStrategy can now be used with a fixed notional

The RollingFXForwardStrategy class now includes a number of new parameters allowing the use of fixed notional in the FX forward strategy. By setting the optional parameter set_weight_from_initial_cash to True the initial FX forward and subsequent rolled forward will have the notional equal to initial_cash. The default value is False. The following code block demonstrates the use of this parameter.

import sigtech.framework as sig
import datetime as dtm

st_nominal = sig.RollingFXForwardStrategy(
    long_currency='EUR',
    currency='USD',
    forward_tenor='3M_IMM',
    start_date=dtm.date(2014, 12, 15),
    set_weight_from_initial_cash=True
)

v7.30.0 (20 Oct 2021)

Parameter changes for strategy methods

A number of changes have been made to the methods on the Strategy class. These changes are described in the following table.

New parameters added to RollingFutureStrategy class

The RollingFutureStrategy class now includes the parameter rolling_approach . Its default value is 'weight', which rolls the full value of the previous contract into the new contract, taking price differences into consideration. The alternative value for this parameter is contracts , which sets an initial investment value in one contract and rolls the same number of units into subsequent contracts. The following code block demonstrates this functionality.

import datetime as dtm
import sigtech.framework as sig

rfs = sig.RollingFutureStrategy(
    currency='USD',
    start_date=dtm.date(2001, 1, 2),
    end_date=dtm.date(2001, 5, 23),
    contract_code='US',
    contract_sector='COMDTY',
    rolling_rule='front',
    front_offset='-2:-1',
    rolling_approach='contracts'
)

An optional parameter, fixed_contracts, overwrites the default behaviour and trades a specified number of contracts throughout the strategy. When set, the strategy will subsequently roll into the same number of contracts. Its default value, None, rolls the initial investment into subsequent contracts as per the value assigned to rolling_approach. This functionality is demonstrated in the following code block.

import datetime as dtm
import sigtech.framework as sig

rfs = sig.RollingFutureStrategy(
    currency='USD',
    start_date=dtm.date(2001, 1, 2),
    end_date=dtm.date(2001, 5, 23),
    contract_code='CL',
    contract_sector='COMDTY',
    rolling_rule='front',
    front_offset='-2:-1',
    fixed_contracts=1
)

New generate_data_for_FX_curve_override method

The generate_data_for_FX_curve_override method on the FXCurveMarket class has been added to the platform. The method allows users to override existing or missing FX curves. The code block below includes the parameters for this method.

def generate_data_for_fx_curve_override(self, currency, quote_date,
                                            tenors=None, forward_dates=None,
                                            delivery_days=None, forward_points=None,
                                            forwards=None, data_point=None)

v7.28.0 & earlier (Jun 2021 - Sep 2021)

In this section

Sep 2021

Delta hedging now available on swaptions

The update allows the DeltaHedgingStrategy to hedge the delta for any swaptions trading strategy inheriting from the OptionStrategyBase class. The following code block demonstrates a call to the DeltaHedingStrategy where the variable st is an option strategy.

import sigtech.framework as sig
dhst = sig.DeltaHedgingStrategy(
    option_strategy_name=st.name,
    currency='USD',
    hedging_instrument_type='UNDERLYING',
    start_date=st.start_date,
    include_option_strategy=False
)

Intraday rebalancing now available with signal data

The platform now allows intraday rebalancing for strategies inheriting from the signal_strategy class. This can be achieved in two ways:

  • By specifying a signal with intraday values and setting the use_signal_for_rebalance_dates parameter to ‘True’

  • By specifying a rebalance_frequency parameter in an intraday format (e.g. '2h')

The below code block demonstrates intraday rebalancing at one hour intervals with the rebalance_frequency parameter, the variable signal_obj is a signal object converted from a pandas Dataframe.

import sigtech.framwork as sig
import datetime as dtm
strategy = sig.SignalStrategy(
    start_dt=dtm.datetime(2013, 12, 2, 6),
    end_dt=dtm.datetime(2013, 12, 5, 15),
    currency='USD',
    signal_name=signal_obj.name,
    allocation_function=sig.signal_library.allocation.identity,
    rebalance_frequency='1h'
)

Simplification of ticker command

When assigning a ticker to your strategy, the previous command db_ticker has been simplified to ticker. The code block below demonstrates its use.

import sigtech.framwork as sig
import datetime as dtm
rs = sig.ReinvestmentStrategy(
    currency = 'USD',
    underlyer = '1140587.SINGLE_STOCK.TRADABLE',
    start_date = dtm.datetime(2021, 1, 4),
    ticker = 'Reinvestment'
)

Cleanup of logging messages

The logging messages generated by the platform, as per the default or user-defined logging level, have been edited to remove any unnecessary information. This change should streamline the user experience.

Trading Economics calendar update

The Trading Economics calendars, which list specific events (e.g. bond auctions), have been updated to include the time of day when these events occur.

CBOE FX intraday data now available

The raw CBOE FX intraday dataset is now available. It can be accessed via the Market Data window via the FX > FX Spot Rates pathway. If you would like access to this or any other dataset, please contact John.McCann@Sigtech.com.

Intraday history retrieval

Querying intraday data for specific time periods is now possible. The code block below queries price data for the Crude Oil December 2019 contract between 12:00:00 on January 4th 2019 and 10:00:00 on October 4th 2020.

import sigtech.framework as sig
import datetime as dtm
instrument = sig.obj.get('CLZ19 COMDTY')
instrument.intraday_history(
    field='LastPrice',
    period=dtm.timedelta(minutes=1),
    start_dt=dtm.datetime(2019, 1, 4, 12, 0, 0),
    end_dt=dtm.datetime(2020, 10, 4, 10, 0, 0)
)

Easily access signal strategy methods

Access assorted allocation and threshold functions using the following code strings:

import sigtech.framework as sig
sig.SignalStrategy.AVAILABLE_ALLOCATION_FUNCTIONS.NORMALIZE
sig.SignalStrategy.AVAILABLE_THRESHOLD_FUNCTIONS.SPARSE_REBALANCING

These functions allow users to normalize or rebalance their strategy’s weights without accessing the specific area of the Framework Signal library. Additional functions are available within the allocation functions module.

Dividend reinvestment methodologies

An assortment of dividend reinvestment methodologies have been added to the EquityFactorBasket strategy. These are accessible through the reinvest_dividends input. The following parameters are available:

reinvest_dividends = StringEnumType(
    ['post_div', 'individual_stock'], default='individual_stock')

The post_div parameter reinvests dividends into a portfolio's constituents on a pro rata basis. The individual_stock parameter reinvests the dividend into the stock paying the dividend.

JupyterLab v3.1.4 update

The version of JupyterLab utilised within the SaaS production window has been updated. This update heralds several new and exciting changes to the functionality available to users of the platform.

Code-completion function added

In the interests of user efficiency the SigTech platform now includes a code-completion feature. The added functionality is made available via Jedi and the Jedi Language Server. This feature is automatically available within the platform and requires no action by the user to enable.

Save time with our code completion feature

Strategy templates now available within the SigTech research environment

A set of pre-made strategy templates have been added to the SigTech platform. These templates are easily accessible via the Template button in the initial Launcher notebook. From these templates, users can easily navigate to the relevant user guide tutorials.

Strategy templates are now available

Debugging feature now available

Identify, isolate and remedy bugs within your code with the aid of SigTech's new debugging feature. This feature can be enabled and disabled with the toggle button on the right of the notebook toolbar.

Drag and drop code snippets into your notebooks

The SigTech platform now allows users to save time by dragging and dropping pre-written snippets of code into their notebooks.

Memory monitoring facility added

Users can now track their memory usage with a green health bar located on the right hand side of the research environment menu.

Strategy widget now available

Visually interact with the performance of your strategy with the new SigTech strategy widget. The widget displays of a range of plots and numerical performance metrics. Once you have defined your strategy's name (e.g. my_strategy) the widget can be generated in one of two ways:

  • Within a notebook cell

my_strategy.interactive_performance(inline=true)
  • As a pop-up to allow for easy sharing

my_strategy.interactive_performance()

Aug 2021

🔎 Instantly search across all documentation, example strategies and the framework source code:

📚Instant access to all example strategies: You can now access our library of example notebooks from every instance of the research environment. See example notebooks.

👀 Frame source code revealed: Browse our entire framework source code and see what's going on under the hood. See framework source code.

📖 New User Guide content

pageAsset swapspageRolling swap strategypageLME FuturespageCustom sizing for rolling futures

Jul 2021

🔧 Data API

You can now make requests to the Data API via personal access tokens. To find out more, contact us at support@sigtech.com.

📈 Market Data UI improvements

The Market Data UI now shows timeseries visualisations when viewing an instrument – use the dropdown to switch between an instrument's various available timeseries.

We've also added a history of recent updates for each timeseries.

🐍 Python Framework updates

27 Jul

  • Addition of new Xccy swap instrument

  • Support for ON, TN and SN rolling FX forward strategies

19 Jul

  • Additional features added in portfolio optimization allocation function.

  • New building block for equity factor strategies.

7 Jul

  • Added asset swap structure.

  • Docs improved for quant-lib module.

6 Jul

  • Automatic data point filtering based on entitlements.

📖 User Guide – new content

pageStrategy deploymentpageDefault strategiespageFutures modellingpagePortfolio optimisation

Jun 2021

Market Data overhaul

Our Market Data interface has undergone a complete overhaul:‌

  • Search our entire database

  • Easier browsing through UI improvements, better organisation and clearer naming

  • Improved code samples

  • More information available for all data

Let us know your feedback at support@sigtech.com.‌

Python Framework updates

30 Jun

  • Constant dv01 rolling swap strategy.

  • Preferred data points can be provided.

  • StrategyService enhanced with get + put many capabilities.

23 Jun

  • Credit Index functionality added.

  • Support for IBES estimates.

21 Jun

  • Added flag to keep stocks with missing values when filtering.

  • Added new swap currency definitions.

  • Methods provided for sizing swap trades using pv01 quantities.

21 Jun

  • Methods provided for sizing swap trades using pv01 quantities.

  • Added optimised intraday history "intraday_history_df" method for retrieving multiple fields

  • Allowed RollingFutureStrategy front offset from expiry date rather than min(expiry date, first delivery notice date)

  • DAG implementation for EQ/CM/FX Options

  • Removed FxPricer class - move functionality to TradePricer.

  • Fixed bug with FxCross class to properly allow for non-USD currency pairs

  • Added doc strings to utils modules

  • Added TRBC sector filters to EquityUniverseFilter

  • Added better error message for allocation function on SignalStrategy

  • HistoricalDObject.history() can automatically calculate arbitrary data points from intraday data

Last updated

© 2023 SIG Technologies Limited