Rolling bond strategy#

Rolling bond strategies in the SigTech platform trade government bonds, either on- or off-the-run, and automatically reinvest the proceeds. This page explains how to create rolling bond strategies with the sig.RollingBondStrategy class.

Initialize SigTech

Import Python libraries:

import datetime as dtm
import numpy as np
import pandas as pd

import sigtech.framework as sig

Initialize the SigTech framework environment:

env = sig.init()

About rolling bond strategies#

A government treasury issues bonds in batches known as “runs”. An investor can trade on-the-run, trading from the most recently issued bond run; or off-the-run, trading from previously-issued bond runs.

Either way, when a government issues a new bond run, the investor trades their bonds for newer ones, maintaining a consistent exposure. This process is called rolling.

You create rolling bond strategies with the sig.RollingBondStrategy class. As well as handling the rolling process, the RollingBondStrategy class automatically reinvests bond coupon payments, using the proceeds to buy more of the same bond asset.

Create a rolling bond strategy#

Create a rolling bond strategy:

START_DATE = dtm.date(2023, 1, 1)
END_DATE = dtm.date(2024, 1, 1)
_5y_rbs = sig.RollingBondStrategy(
    start_date=START_DATE,
    end_date=END_DATE,
    currency="USD",
    country="US",
    run_type="ON_THE_RUN",
    tenor="5Y",
    ticker="RBS US 5Y ON_THE_RUN"
)
_5y_rbs.history().tail()

The rest of the examples on this page use a helper function, create_rbs, which creates rolling bond strategies. Define the create_rbs helper function:

def create_rbs(tenor, run_type, country="US", currency="USD"):
    rbs = sig.RollingBondStrategy(
        start_date=START_DATE,
        end_date=END_DATE,
        currency=currency,
        country=country,
        run_type=run_type,
        tenor=tenor,
        ticker=f"RBS {country} {tenor} {run_type}"
    )
    return rbs

Rolling bond strategy parameters#

When you create a rolling bond strategy, you specify the following parameters:

  • country: Two-letter country code of the government issuing the bond. (country="US")

  • tenor: Bond term in years. One or two numerical digits followed by "Y". (tenor="5Y")

  • run_type: The bond run to trade from and roll to. Default is "ON_THE_RUN".

    By default, a rolling bond strategy trades on-the-run (run_type="ON_THE_RUN"), meaning it rolls to the most recently issued set of bonds for the given country and tenor.

    To create an off-the-run strategy that trades from previously-issued bond runs, set run_type to "FIRST_OFF_THE_RUN", "SECOND_OFF_THE_RUN", or "THIRD_OFF_THE_RUN". Of the off-the-run options, "FIRST_OFF_THE_RUN" is the newest and "THIRD_OFF_THE_RUN" is the oldest.

Create some example rolling bond strategies:

rbs_params = [
    ("2Y", "ON_THE_RUN"),
    ("2Y", "FIRST_OFF_THE_RUN"),
    ("5Y", "ON_THE_RUN"),
    ("5Y", "FIRST_OFF_THE_RUN"),
    ("10Y", "ON_THE_RUN"),
    ("10Y", "FIRST_OFF_THE_RUN"),
]
rb_strats = [create_rbs(tenor, run_type) for tenor, run_type in rbs_params]
rb_strats

Retrieve data for a rolling bond strategy#

Retrieve historical performance data and data about underlying instruments for rolling bond strategy objects.

Retrieve historical performance data#

Retrieve historical performance data for a rolling bond strategy:

hist_series = _5y_rbs.history()
hist_series.tail()

Create a data frame of the historical performance data for rb_strats, a list of rolling bond strategies:

df = pd.DataFrame(data={
    rbs.name: rbs.history()
    for rbs in rb_strats
})
df.tail()

Plot the performance data:

df.plot()

Retrieve underlying instrument data#

Define a helper function, get_rbs_info, that formats some interesting data about the instruments in a rolling bond strategy:

def get_rbs_info(rbs):
    info = f"{rbs.name}:\n"
    info += f"    asset description: {rbs.asset_description}\n"
    info += f"    bond group:        {rbs.group().name}\n"
    info += f"    first instrument:  {rbs.roll_schedule.iloc[0]}\n"
    info += f"    run type:          {rbs.run_type}\n"
    info += f"    tenor:             {rbs.tenor}\n"
    return info

Print data about the underlying instruments for each rolling bond strategy in the list rb_strats:

[print(get_rbs_info(rbs)) for rbs in rb_strats];

Work with roll schedules#

When you create a rolling bond strategy, SigTech computes its roll schedule. For the period between the strategy’s start and end dates, the roll schedule specifies which underlying bond instruments the strategy trades.

You can retrieve individual bond instruments from a rolling bond strategy’s roll schedule. Roll schedules also work the other way; you can retrieve a predefined roll schedule and use it to create a rolling bond strategy.

Retrieve instruments from a roll schedule#

To retrieve the bond instruments from an existing rolling bond strategy’s roll schedule, use the strategy’s roll_schedule instance property.

_5y_rbs.roll_schedule.tail()

The roll schedule is indexed by a date string in the format "YYYY-MM-DD". Retrieve the bond instrument for a specified date in the roll schedule:

print(rs["2023-08-02"])
bond_instrument_obj = sig.obj.get(rs["2023-08-02"])
bond_instrument_obj

Learn more: Bond instruments

Retrieve a predefined roll schedule#

To retrieve a predefined roll schedule, use the otr_series function in the sig.schedules.roll_schedules.bond_schedule module.

Define a helper function to get predefined roll schedules:

def get_schedule(tenor, shift, country="US"):
    schedule = sig.schedules.roll_schedules.bond_schedule.otr_series(
        start=START_DATE,
        end=END_DATE,
        group_name=f"{country} GOVT BOND GROUP",
        tenor=tenor,
        shift=shift,
    )
    return schedule

In the code block above:

  • The shift parameter specifies the run type; 0 corresponds to "ON_THE_RUN", 1 corresponds to "FIRST_OFF_THE_RUN", and so on.

  • The return value, schedule, is a pandas data frame. The data frame has a single column called bond_name. The index of the data frame is a date string in the format "YYYY-MM-DD".

Get some predefined roll schedules:

rs_params = [
    ("10Y", 0),
    ("10Y", 1),
    ("10Y", 2),
]
scheds = [get_schedule(tenor, shift) for tenor, shift in rs_params]
scheds[0]

Create a rolling bond strategy from a roll schedule#

After retrieving a predefined roll schedule, you can use it to create a rolling bond strategy.

When you create the strategy object, set the raw_otr_series parameter to the "bond_name" column of the

To do this, when you create the strategy using sig.RollingBondStrategy, set the raw_otr_series parameter to the "bond_name" column of a roll schedule data frame.

The code block below modifies the create_rbs helper function defined above, adding an alternative way to create rolling bond schedules.

  • If the shift parameter is defined, the helper function retrieves a roll schedule, adds raw_otr_series to the parameters, and creates the strategy.

  • Otherwise, if the run_type parameter is defined, the helper function adds run_type to the parameters and creates the strategy.

def create_rbs(tenor, run_type=None, country="US", currency="USD", shift=None):
    params = {
        "start_date": START_DATE,
        "end_date": END_DATE,
        "currency": currency,
        "country": country,
        "tenor": tenor,
    }
    if shift:
        schedule = get_schedule(tenor, shift, country)
        rbs = sig.RollingBondStrategy(**params,
            raw_otr_series=schedule["bond_name"],
            ticker=f"RBS {country} {tenor} SHIFT {shift}",
        )
    else:
        rbs = sig.RollingBondStrategy(**params,
            run_type=run_type,
            ticker=f"RBS {country} {tenor} {run_type}",
        )
    return rbs

Create some rolling bond strategies from roll schedules:

rb_strats_from_scheds = [create_rbs(tenor, shift=shift) for tenor, shift in rs_params]

Retrieve performance data for the rolling bond strategies:

[print(strat.history().tail()) for strat in rb_strats_from_scheds]