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()
Learn more
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 calledbond_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, addsraw_otr_series
to the parameters, and creates the strategy.Otherwise, if the
run_type
parameter is defined, the helper function addsrun_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]