Floaters and inflation-linked bonds

How TrackRecords projects unknown coupons and principal for floating-rate and inflation-linked bonds

Overview

When a coupon or principal depends on a future rate, TrackRecords projects those cash flows under a scenario.

You can use:

  • a custom scenario of rate paths
  • a flat scenario: unknown coupons and principal stay at the last known level (as of the calculation date)
  • an implied scenario (default): market-implied paths of the base indicators, recovered from liquid floaters and inflation-linked government bonds

The implied scenario estimates market expectations for the relevant base rates (for example overnight, inflation and policy rate) on the calculation date.

Implied scenario

For bonds whose coupon or principal depends on those base rates, TrackRecords recovers implied forwards from a basket of liquid government floaters and linkers (and, for the policy-rate path, high-grade corporates). The basket is reviewed quarterly.

The implied rate for a given maturity is interpolated between the two nearest reference bonds:

impl_rate_for_duration =
  (1 + yield_low)^((dur_up - dur) / (dur_up - dur_low))
  * (1 + yield_up)^((dur - dur_low) / (dur_up - dur_low))
  - 1
  • yield_up / dur_up: implied rate and maturity of the nearest longer reference bond
  • yield_low / dur_low: implied rate and maturity of the nearest shorter reference bond
  • dur: maturity of the bond being valued
  • if there is no shorter reference bond, the implied rate is the actual rate on the calculation date
  • puts and calls are ignored when choosing dur_low and dur_up

Implied inflation

Dirty price of the linker on the calculation date:

dirty_price = first_nonzero(close, waprice, bid) / 100 * outstanding_face + accrued

A government yield curve on the calculation date (3m … 30y) is the risk-free discount curve. Tenors that do not sit on a knot are linearly interpolated.

Implied inflation is the rate that equates the discounted inflation-adjusted cash flows to the dirty price. The solver is bisection on inflation in [-10%, +60%] until the price error is below 1e-5 (or 1,000 iterations).

Implied floating rate (premium to a base rate)

For a floater with a known premium, the implied base rate is the residual that equates dirty price to discounted known coupons, discounted premium on unknown coupons, and discounted principal.

Discounting uses the government curve. For corporates used as policy-rate references, a credit spread from a high-grade bond index is added to that curve.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def get_implied_yield(stated_at, dirtyprice, nominal, cashflows, daily_rates_on_stated_at, premium):
    PR1 = 0
    PR2 = 0
    pv = dirtyprice
    Nom = nominal
    stated_at = pd.to_datetime(stated_at).date()
    if len(cashflows) == 0:
        return 0
    dc = cashflows.to_dict('records')
    N = len(dc)
    for i in range(N):
        d = dc[i]['coupon_date']
        cur_coupon = dc[i]['cf_coupon']
        if d > stated_at:
            delta_days = (d - stated_at).days
            dKBD = (1 + get_kbdrate_from_data(daily_rates_on_stated_at, delta_days, 'RUB') / 100) ** (delta_days / 365)
            if cur_coupon > 0:
                PR2 += cur_coupon / dKBD
            else:
                prev_d = dc[i - 1]['coupon_date'] if i > 0 else stated_at
                delta_prev_days = (d - prev_d).days
                PR1 += delta_prev_days / 365.0 / dKBD
                PR2 += Nom * premium * delta_prev_days / 365 / dKBD
            if i == N - 1:
                PR2 += Nom / dKBD
    return (pv - PR2) / (PR1 * Nom)