eddelbuettel / rquantlib

R interface to the QuantLib library
117 stars 50 forks source link

Differences in Schedule and FixedRateBond #189

Open tomasnobrega opened 1 month ago

tomasnobrega commented 1 month ago

Hello, I'm trying to price a sample bond, but for some reason, the schedule object differs when I run it within Schedule() compared to when I use a list inside FixedRateBond(). Specifically, the bond function is omitting the first cashflow. Am I missing something? Is this the expected behaviour?

Schedule Function

> schedule <- Schedule(
 list(
     effectiveDate=as.Date("2023-06-01"),
     maturityDate=as.Date("2024-12-01"),
     period='Semiannual',
     calendar='UnitedStates/Settlement',
     businessDayConvention='Unadjusted',
     terminationDateConvention='Unadjusted',
     dateGeneration='Forward',
     endOfMonth=0
 ))
> schedule
[1] "2023-06-01" "2023-12-01" "2024-06-01" "2024-12-01"

FixedRateBond

schedule <- 
  list(
    effectiveDate=as.Date("2023-06-01"),
    maturityDate=as.Date("2024-12-01"),
    period='Semiannual',
    calendar='UnitedStates/Settlement',
    businessDayConvention='Unadjusted',
    terminationDateConvention='Unadjusted',
    dateGeneration='Forward',
    endOfMonth=1
)
#Create the discount rate curve to compute present values
date <- as.Date("2023-05-04")
discountCurve <- DiscountCurve(
  list(
    tradeDate = date,
    settleDate = date + 2,
    dt = .25,
    interpWhat="zero",
    interpHow="linear"
  ),
  tsQuotes = list(flat = 0.042675)
)
#Create the bond
bondinfo <- list(
  settlementDays = 2
)
setEvaluationDate(as.Date("2023-05-04"))
FixedRateBond(
  bondinfo,
  rates = c(0.085),
  schedule,
  list(
    dayCounter="Thirty360",
    compounding='Compounded',
    freq='Semiannual',
    durationType='Modified'
  ),
  discountCurve = discountCurve
)

Which gives output:

Concise summary of valuation for FixedRateBond 
 Net present value :  105.67 
       clean price :  105.69 
       dirty price :  105.69 
    accrued coupon :  0 
             yield :  0.043301 
          duration :  1.4762 
   settlement date :  2023-05-08 
        cash flows : 
       Date Amount
 2023-12-01   4.25
 2024-06-03   4.25
 2024-12-02   4.25
 2024-12-02 100.00
eddelbuettel commented 1 month ago

I don't understand your question.

tomasnobrega commented 1 month ago

In the schedule part, there is a schedule for "2023-06-01" however the bond function gives a cash-flow starting at "2023-12-01". Why is the bond function skipping the first schedule if the arguments inside schedule are the same?

eddelbuettel commented 1 month ago

I see. Good question. You would have to dig into the code to see if we drop something somewhere.

I usually start from the self-contained C++ examples.

eddelbuettel commented 1 month ago

It's been too long since I worked on a bond desk but I would tend to agree with you that there should be an initial June cash flow. The cash flow vector 'generator' (in utils.cpp) look fine (no off by one one error) so it may be the schedule -- but if so then all the pricers would be off. Some I am puzzled.

I don't have access to benchmarking tools (ie Bloomberg or alike) so I can't help on that side.

tomasnobrega commented 1 month ago

Thank you. I've modified the code to initiate the schedule a semester earlier, and now the price closely aligns with the benchmark. I suspect the schedule accounts for the first period as an issuance or a type of "non-payment" start date, although I'm not sure.

eddelbuettel commented 1 month ago

I also noticed that this uses the 'discount curve given' pricer when the alternates (for price or yield) may be more common. And I am with you that it is probably something intrinsic to the Schedule class.