Tutorial: duration weighted strategy#

Introduction#

The purpose of this tutorial is to show users that are new to the SigTech platform how to construct a systematic investment strategy by creating a duration weighted spread between different tenors of government bonds by the same issuer. This tutorial is specifically targeted towards new users.

A notebook containing all the code used in this page can be accessed via your research environment’s File Browser. See Example notebooks.

To be able to run the related Jupyter notebook the appropriate data entitlements need to be in place for your organisation. If you would like to access SigTech’s Bond data, please contactsales@Sigtech.com

Workflow overview#

When creating an investment strategy on the SigTech platform, the workflow tends to follow these steps:

  1. Set up the environment

  2. Define the investment universe

  3. Create the strategy

  4. Construct the portfolio

  5. Generate the performance report

This tutorial will go through the above-mentioned steps, and explain each one in turn. Additionally, there will be links to more in-depth information to allow for further learning.

Environment#

Setting up your environment takes three steps:

  • Import the relevant internal and external libraries

  • Configure the environment parameters

  • Initialise the environment

import sigtech.framework as sig

import pandas as pd
import datetime as dtm
import seaborn as sns

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

Learn more: setting up the environment.

Define the investment universe#

In this step, the user will define a range of constant used for creating the investment strategy. The bond group will be specific for each government issuing the government bonds, e.g. US GOVT BOND GROUP, see Market Data Browser to find the government bond groups that are available. Additionally, the constants defined in the below code block relates to the tenors that are of interest as well as the start date of the strategy.

start_date = dtm.date(2018, 1, 5)
group = sig.obj.get('US GOVT BOND GROUP')
tenors = ['30Y', '5Y']

When the investment universe contains bond contracts, it’s of high importance to handle the rolling of specific bond contracts; since a given country issues new securities for a given tenor point periodically, it’s crucial to systematically handle how the strategy trades in and out of bond contracts to maintain the exposure. See Bonds for more information on the bond instrument. The SigTech platform offers the RollingBondStrategy class which allows the user to easily handle the rolling of securities.

In this tutorial we will create two RollingBondStrategy objects, one for each tenor defined above. The below defined function allows for creating multiple RollingBondStrategy objects by passing in a few parameters.

The RollingBondStrategy objects are instantiated using parameters such as country, run_type , etc. These parameters will not be discussed in detail here; see Rolling Bond Strategy to learn more about them and its alternatives. Note that the RollingBondStrategy objects assumes a constant long exposure from start date to end date.

def create_otr(group, tenor, start_date):
    return sig.RollingBondStrategy(
        # Assing the country of the bond group
        country=group.country,

        # The strategy denomination currency
        currency='USD',

        # Which bonds to be used as part of the strategy,
        # could e.g. be 'ON_THE_RUN', 'FIRST_OFF_THE_RUN',
        # 'SECOND_OFF_THE_RUN' etc.
        run_type='ON_THE_RUN',

        # Start date of strategy
        start_date=start_date,

        # Tenor of strategy
        tenor=tenor,

        # Name of strategy
        ticker=f'{tenor} {group.country} OTR'
    )

Via a dictionary comprehension in the below code block, an on-the-run RollingBondStrategy will be created for each tenor defined above.

otr_dict = {
    tenor: create_otr(group, tenor, start_date)
    for tenor in tenors
}

Create the strategy#

The strategy will consist of a duration weighted exposure of the spread between the 30 year and 5 year tenors of the on-the-run US treasury bonds. This way the strategy will be immune to parallel curve shifts.

In the below code block, the .anno1_serios() method will return the modified duration time series for the specific bond object.

dur_dict = {
    tenor: otr_dict[tenor].ann01_series()
    for tenor in tenors
}

To generate our weighted duration signal we keep constant the notional of one leg and find the duration weight of the second leg as per equation below:

\[5Y_{weight} = \frac{Duration_{30Y}}{Duration_{5Y}}\times Notional\]

where \(Notional\) = 1 unit of currency.

Finally, we inverse the result and apply a negative sign in the 5Y tenor point as our intention is to have a short exposure.

Python:

df = pd.DataFrame({
    otr_dict['5Y'].name: - dur_dict['30Y'] / dur_dict['5Y'],
    otr_dict['30Y'].name: 1
}).dropna()
df.head()

Output:

Construct the portfolio#

To apply the strategy to the universe and combine all the assets into a portfolio, the SignalStrategy class is used. But before we can use the SignalStrategy class, we need to convert the pandas DataFrame of signals into a signal object - this is done below:

Python:

signal_obj = sig.signal_library.from_ts(df)
signal_obj

Output:

IDENTITY 5DFA5E3F SIGNAL <class 'sigtech.framework.signal.signal_object.Signal'>[5393342720]

Once the signal object is created, we can create a SignalStrategy object. There are numerous different parameters and alternatives that the user can make use of, e.g. different allocation functions between the assets in the strategy. For further information on the SignalStrategy class, see Signal Strategy.

duration_weighted_strat = sig.SignalStrategy(
    # Start date of strategy
    start_date=start_date,

    # Currency in which the strategy is denominated in
    currency='USD',

    # Reference to the signal object
    signal_name=signal_obj.name,

    # On the instruments which have a negative weight,
    # refrain from creating a short version of that
    # instrument
    convert_long_short_weight=False
)

Generate the performance report#

After having created the strategy, the script below can be used to create a performance report which contains information on metrics, rolling performance charts and performance calendar. There are a wide range of different performance views and reports available for the user which might be relevant depending on the specific use case, see Performance Analytics for further information on different performance reports, views and metrics.

Python:

sig.PerformanceReport(duration_weighted_strat).report()

Output:

Next Steps#

The following resources are available for continued learning: