Skip to content
All library documents

Debugging Daily Bond Yield Calculations with Root Finding in R

Article Quant Q&A · Author: Joe.Dillen

Summary

The document describes an attempt to calculate daily yields to maturity for a panel of euro-area government bonds using prices, coupons, and time to maturity. The proposed approach defines a bond valuation function and applies a root-finding routine to solve for the yield that makes calculated value match observed price. A loop is intended to store a yield for each date and bond, with zeros assigned to matured or missing observations.

The reported errors point to a mismatch between the intended scalar calculation and operations on whole matrices: the condition checks a full price matrix, and the root-finding function receives matrix-wide inputs instead of values for the current row and column. The post includes no accepted solution, and the stated valuation formula and inputs may also need review for coupon timing and units. It is therefore a troubleshooting example, not a validated yield method.

Key ideas

  • Yield to maturity can be estimated by solving for the rate that equates a bond valuation to its market price.
  • A daily panel calculation must pass the current bond and date values to the root finder.
  • An if condition expects a scalar logical value, so testing an entire price matrix causes warnings.
  • Missing and matured observations need explicit handling before solving for yield.
  • The document does not provide a corrected implementation or validate its bond pricing assumptions.

Tags

Full text
# Daily yield to maturity using `uniroot` in R: error


# Daily yield to maturity using `uniroot` in R: error












So, I'm trying to compute the daily yielt to maturity on basis of data retrieved from Datastream. The data comprises EMU Treasury bonds with Prices, Coupon and Maturity date. In R the matrices are constructed that daily all prices, coupons and time-to maturites are arranged corresponding to their date. When matured, all three variables are 0 (zero).

Using the bondvalue function:

```
bondvalue = function(c,T,r,par)  { bv = c/r + (par - c/r) * (1+r)^(-2*T) bv }
```

I essentially use:

```
Yields = c(Yields,  uniroot(function(r) bondvalue(Coupon*100, Prices, r, 100) - Prices,  c(-1, 1))$root)
```

to find yield to maturities. However, as stated before I would like to compute daily yield to maturities. Therefore I use a for loop:

```
daily_ytm <- matrix(NA,ncol = ncol(Prices), nrow = nrow(Prices))
for (i in 1:nrow(Prices)) {
for (j in 1:ncol(Prices)) {
 if (Prices[i,j] == 0){
  daily_ytm[i,j]=0
}  
else if (Prices > 0){
daily_ytm[i,j]=c(daily_ytm, 
            uniroot(function(r) bondvalue(Coupon*100, Prices, r, 100)
            - Prices, 
            c(-1, 1))$root)
}
}
}
```

Where I would like to get a 0 (zero) in the new matrix, whenever the Price/Coupon/Maturity is zero (or NA originally), otherwise it should find the ytm using uniroot().

However, I receive the error:

```
>Error in pmax.int(pmin(x, .Machine$double.xmax), -.Machine$double.xmax) :  invalid input type In addition: Warning messages:
>1: In if (Prices > 0) { : the condition has length > 1 and only the first element will be used
>2: In if (is.na(f.lower)) stop("f.lower = f(lower) is NA") : the condition has length > 1 and only the first element will be used
>3: In if (is.na(f.upper)) stop("f.upper = f(upper) is NA") : the condition has length > 1 and only the first element will be used
>4: In cbind(is.na(mmm), is.na(each)) : number of rows of result is not a multiple of vector length (arg 2)
```

What am I doing wrong here?

```
> head(Prices)
              PTOTEAOE0013 PTOTEMOE0001 DE0004109103 PTOTEOOE0009
1999-12-31       105.88       100.13      120.033        108.4   
2000-01-03       105.75       100.13      120.033        108.4 
2000-01-04       105.85       100.13      120.033        108.4          
2000-01-05       105.92       100.13      120.033        108.4          
2000-01-06       105.92       100.13      120.033        108.4          
2000-01-07       106.20       100.13      120.033        108.4          

> head(Coupon[,1:4])
       PTOTEUOE0001 PTOTEAOE0013 PTOTEMOE0001 DE0004109103
1999-12-31       0.0875     0.048125      0.10625      0.07125
2000-01-03       0.0875     0.048125      0.10625      0.07125
2000-01-04       0.0875     0.048125      0.10625      0.07125
2000-01-05       0.0875     0.048125      0.10625      0.07125
2000-01-06       0.0875     0.048125      0.10625      0.07125
2000-01-07       0.0875     0.048125      0.10625      0.07125

> head(ttm_y[,1:4])
PTOTEUOE0001 PTOTEAOE0013 PTOTEMOE0001 DE0004109103
1      1.16667         3.25      3.41667      3.50000
2      1.16667         3.25      3.41667      3.41667
3      1.16667         3.25      3.41667      3.41667
4      1.16667         3.25      3.41667      3.41667
5      1.16667         3.25      3.41667      3.41667
6      1.16667         3.25      3.41667      3.41667
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.