1 Introduction

Practical implementations of two relative value models which provide information on over-, respectively underpriced bonds. The first one is a simple model based on traditional yield to maturity analysis and the second one demonstrates the slightly more complex JP Morgan discount function model, an approach of term-structure of interest modelling.

2 Yield to Maturity

Yield to maturity, also called redemption yield based measures to find relative value in a universe of bonds is the traditional method used by most practitioners in the field. As is commonly known, yield to maturity assumes that an investor holds the bond to maturity and all the bond’s cash flow is reinvested at the computed yield to maturity. It is found by solving for the interest rate that will equate the current price to all cash flows from the bond to maturity. In this sense, it is the same as the internal rate of return.

2.1 Data

Link to current prices and bond data as well as utility scripts to maintain the bond baskets analysed.

nms=names(INPUTS_LST)[-c(11:13, 16:18)]
RST_TBL=map_dfc(nms, ~INPUTS_LST[[.x]]) %>% 
  set_names(
    c(
      nms[1:2], 
      paste0("CLEAN_PRICES_", names(INPUTS_LST$CLEAN_PRICES_RNG)), 
      names(INPUTS_LST$AMOUNT_RNG), 
      paste0("VOLUME_TRADED_", names(INPUTS_LST$VOLUME_TRADED_RNG)),
      nms[6:12]
    )
  )

RST_TBL %>%
  format.dt.f(
    ron_vars=names(RST_TBL)[c(3:11, 14:15)],
    perc_vars=names(RST_TBL)[c(16)]
  )

2.2 Benchmark Yields

The model implementation shown here derives a benchmark yield curve from observed bond redemption yields of government bonds by fitting a polynomial that minimizes the squared error of redemption yields.

2.2.2 Bid

INPUTS_LST$BENCHMARKS_LST$bid %>% format.dt.f(perc_vars=names(.)[2])

2.2.3 Ask

INPUTS_LST$BENCHMARKS_LST$ask %>% format.dt.f(perc_vars=names(.)[2])

2.2.4 Swap

INPUTS_LST$BENCHMARKS_LST$swap %>% format.dt.f(perc_vars=names(.)[2])

2.3 Credit Spreads

Corporate bonds are not homogeneous in their credit quality so bond managers compare their yield to some well established benchmark, e.g. government bond curve. This yield differential is then measured in basis points (bps) and gives an indication of the credit risk priced into the corporate bond.

credit.spreads.table.f(
  INPUTS_LST$CREDIT_PARAMETERS_RNG,
  c(0,0.25,0.5,0.75,1,1.25,1.5,1.75,2,2.25,2.5,2.75,3,3.25,3.5,3.75,4,4.25,4.5,4.75,5,6,7,8,9,10)
) %>%
  format.dt.f(perc_vars=NA, ron_vars=names(.))

Above we choose the desired term structure of credit spreads for each rating category by means of shape parameters

INPUTS_LST$CREDIT_PARAMETERS_RNG %>%
  format.dt.f()

The term structure is basically broken down into two sub-periods. A short-to medium term period to \(T∞\) which is followed by the long-term characteristics of the credit spread. As to the first period, a fourth order polynomial is fitted between zero and \(T∞\).

2.4 Cheap/Rich

Cheap/rich analysis for a universe of corporate bonds using the benchmark curve. Bonds priced below [above] their corresponding model price are cheap [rich].

RST_LST=lift_dl(cheap.rich.corp.bonds.f)(INPUTS_LST)
RST_TBL=RST_LST$trading

names(RST_TBL)
 [1] "no"                "valor"             "years_to_maturity"
 [4] "issuer"            "bid_price"         "bid_size"         
 [7] "ask_price"         "ask_size"          "hist_price"       
[10] "sel_ytw"           "sel_mat"           "sel_mid"          
[13] "bid_ytw"           "bid_mat"           "bid_mid"          
[16] "ask_ytw"           "ask_mat"           "ask_mid"          
[19] "benchmark_curve"   "swap_offer"        "benchmark_target" 
[22] "sel_model_price"   "bid_model_price"   "ask_model_price"  
[25] "action"            "issed_oustanding"  "trading_volume"   
[28] "rating_moodys"     "rating_spn"        "rating_internal"  
RST_TBL %>%
  format.dt.f(
    ron_vars=names(RST_TBL)[c(3, 5:10, 13, 16, 19:24, 26:27)],
    perc_vars=NA
  )

2.5 Limitations

Redemption yield based models have limitations. In line with the underlying assumptions, coupons need to be reinvested at the computed internal rate of return. To see this, consider the following two hypothetical five year government bonds \(A\) and \(B\). The two bonds differ in their coupon rate, which is \(10\%\) for \(A\) and \(2\%\) for \(B\). A pure yield to maturity based analysis would call for identical redemption yields yet there would be a great deal higher reinvestment risk for bond \(A\). For instance, assuming annual coupon payments, the coupon of bond \(A\), respectively \(B\) in year four would need to be reinvested for one year at that same five year rate. With yield curves generally upward sloping, this rate is likely to be lower and so the high-coupon bond \(A\) will probably achieve a lower return. Having said this, yield to maturity based models should nonetheless not be completely discounted. They are indeed appropriate for bond markets that are not too liquid with comparably wide bid/ask price spreads. This means the models need be somewhat less discerning to detect arbitrage in the markets.

3 Discount Factor

For liquid bond markets such as the one for US Treasuries, the shortcomings of pure yield to maturity analysis are too great. Here the proper approach is to think about bonds as a package of cash flows, more specifically as packages of zero-coupon instruments. To find, respectively explain the price of the whole package, each of this zero bonds is then discounted at a unique interest rate appropriate for the time period in which the cash flow will be received. A discount factor model refrains from modelling the unique interest rates at each point in time because these are, in colloquial terms, not very well behaved. Experience shows that interest term structures come in all kinds of shapes. There are not just upward or downward sloping curves but they often have “humps” and “kinks” that make the formulation of an suitable model very demanding. On the other hand, modelling the discount factors is an easier approach. The JP Morgan Discount Factor Model (JPM), for example, has a clear boundary at time zero and is monotonously declining over time. It is modeled as a polynomial with coefficients determined such that the sum of least square errors of market price minus model price is minimized. For a practical application of the JPM model please refer to the repository https://github.com/rnfermincota/academic/blob/main/teaching/NUS/Data-Engineering/4-Fixed-Income/Cheap-Rich/libs/cheap_rich.R