# CORRA linked FRN's accrual interest calculation using the QuantLib

In Canada, the CDOR index will be phased out in June 2024, and the replacement is the CORRA (Canadian Overnight Repo Rate Average), which is an OvernightIndex used for evaluating the FRN in Canada. Here is an example bond, the CUSIP is 13607HMS8, maturity date is 2025-03-04, issue date is 2021-02-25, and first settlement date is 2021-03-04, below is my testing code to get the clean price and accrual interest for the evaluation date 2022-04-29, and settlement date is 2022-05-03. I compare the results with the Bloomberg, the clean price is pretty close, but the accrual interest has 2 cents difference, which caught my attention at once, because I feel the accrual interest should be the exactly the same, since the coupon on the last reset date should be the same. Below is my testing code, during debug I see the current payment period is from 2022-03-04 to 2022-06-06, and it used the CORRA rate (0.43%) on 2022-03-04 as the fixing to calculate the rate = gear * fixing + spread, the spread is 0.46%, so the rate = 1 * 0.43% + 0.46% = 0.89%, but some of my friends told me for the overnightIndex should have some kind of compounding, using the single day fixing on 2022-03-04 to calculate the rate is not correct. I thought the OvernightIndex will automatically handle the daily compounding, but it did not, so can someone please help?

#include <ql/qldefines.hpp>
#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
#endif
#include <ql/instruments/bonds/zerocouponbond.hpp>
#include <ql/instruments/bonds/floatingratebond.hpp>
#include <ql/pricingengines/bond/discountingbondengine.hpp>
#include <ql/cashflows/couponpricer.hpp>
#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
#include <ql/termstructures/yield/bondhelpers.hpp>
#include <ql/termstructures/yield/overnightindexfutureratehelper.hpp>
#include <ql/termstructures/yield/zerocurve.hpp>
#include <ql/termstructures/volatility/optionlet/constantoptionletvol.hpp>
#include <ql/indexes/ibor/euribor.hpp>
#include <ql/indexes/ibor/usdlibor.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/calendars/unitedstates.hpp>
#include <ql/time/daycounters/actualactual.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <ql/time/daycounters/thirty360.hpp>
#include <ql/math/interpolations/linearinterpolation.hpp>

#include <iostream>
#include <iomanip>

using namespace QuantLib;

int main(int, char* []) {

try {

std::cout << std::endl;

/*********************
***  MARKET DATA  ***
*********************/

DayCounter dayCounter = Actual365Fixed();

Date settlementDate(3, May, 2022);
// must be a business day

Integer fixingDays = 2;
Natural settlementDays = 2;

Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
// nothing to do with Date::todaysDate
Settings::instance().evaluationDate() = todaysDate;

std::cout << "Today: " << todaysDate.weekday()
<< ", " << todaysDate << std::endl;

std::cout << "Settlement date: " << settlementDate.weekday()
<< ", " << settlementDate << std::endl;

//
// Building of the CORRA forecasting curve
//
std::vector<ext::shared_ptr<RateHelper>> corraFutureHelpers;
std::map<Date, Real> futurePrices;
futurePrices[Date(15, June, 2022)] = 99.12;
futurePrices[Date(21, September, 2022)] = 98.08;
futurePrices[Date(21, December, 2022)] = 97.3;
futurePrices[Date(15, March, 2023)] = 96.99;
futurePrices[Date(21, June, 2023)] = 96.96;
futurePrices[Date(20, September, 2023)] = 96.93;
futurePrices[Date(20, December, 2023)] = 96.90;
futurePrices[Date(20, March, 2024)] = 96.87;
futurePrices[Date(19, June, 2024)] = 96.83;
futurePrices[Date(18, September, 2024)] = 96.80;
futurePrices[Date(18, December, 2024)] = 96.78;
futurePrices[Date(19, March, 2025)] = 96.76;

const ext::shared_ptr<OvernightIndex> corraIndex(new OvernightIndex("CORRA", Natural(fixingDays), currency, calendar, dayCounter));

std::map<Date, Real>::iterator it = futurePrices.begin();
// Iterate over the map using Iterator till end.
while (it != futurePrices.end()) {
// Accessing KEY from element pointed by it.
Date date = it->first;
Real price = it->second;
ext::shared_ptr<Quote> quoteHandle(new SimpleQuote(price));
ext::shared_ptr<RateHelper> futureRateHelper(new OvernightIndexFutureRateHelper(
Handle<Quote>(quoteHandle),
todaysDate,
date,
corraIndex));
corraFutureHelpers.push_back(futureRateHelper);
it++;
}

ext::shared_ptr<YieldTermStructure> corraForecastTermStructure(new PiecewiseYieldCurve<Discount, LogLinear>(settlementDate, corraFutureHelpers, dayCounter));

//
//
std::vector<Rate> rates;
std::vector<Date> dates;
std::map<Date, Rate> curvePoints;
curvePoints[Date(29, April, 2022)] = 0.01175992;
curvePoints[Date(29, May, 2022)] = 0.01279924;
curvePoints[Date(29, June, 2022)] = 0.01479078;
curvePoints[Date(29, July, 2022)] = 0.016785321;
curvePoints[Date(29, August, 2022)] = 0.018477552;
curvePoints[Date(29, September, 2022)] = 0.020169783;
curvePoints[Date(29, October, 2022)] = 0.021807427;
curvePoints[Date(29, November, 2022)] = 0.023499658;
curvePoints[Date(29, December, 2022)] = 0.025165168;
curvePoints[Date(29, January, 2023)] = 0.026893393;
curvePoints[Date(28, February, 2023)] = 0.028565869;
curvePoints[Date(29, March, 2023)] = 0.030182596;
curvePoints[Date(29, April, 2023)] = 0.031910822;
curvePoints[Date(29, July, 2023)] = 0.032000324;
curvePoints[Date(29, October, 2023)] = 0.034663883;
curvePoints[Date(29, January, 2024)] = 0.036994209;
curvePoints[Date(29, April, 2024)] = 0.037462802;
curvePoints[Date(29, July, 2024)] = 0.037931396;
curvePoints[Date(29, October, 2024)] = 0.038628441;
curvePoints[Date(29, January, 2025)] = 0.039433535;
curvePoints[Date(29, April, 2025)] = 0.038443031;
curvePoints[Date(29, July, 2025)] = 0.036722382;
curvePoints[Date(29, October, 2025)] = 0.038809456;
curvePoints[Date(29, January, 2026)] = 0.04069903;
curvePoints[Date(29, April, 2026)] = 0.040963241;
curvePoints[Date(29, October, 2026)] = 0.041631359;
curvePoints[Date(29, April, 2027)] = 0.041631359;

std::map<Date, Rate>::iterator itPoints = curvePoints.begin();
// Iterate over the map using Iterator till end.
while (itPoints != curvePoints.end()) {
// Accessing KEY from element pointed by it.
Date date = itPoints->first;
Rate point = itPoints->second;
dates.push_back(date);
rates.push_back(point);
itPoints++;
}

ext::shared_ptr<YieldTermStructure> cibcDiscountTermStructure(new InterpolatedZeroCurve<Linear>(dates, rates, dayCounter, calendar, Linear()));

// Term structures that will be used for pricing:
// the one used for discounting cash flows
// the one used for forward rate forecasting

/*********************
* BONDS TO BE PRICED *
**********************/

// Common data
Real faceAmount = 100;

// Pricing engine
ext::shared_ptr<PricingEngine> bondEngine(new DiscountingBondEngine(discountingTermStructure));

// Floating rate bond (CORRA index)
// Populate all the past CORRA rate fixing which I downloaded from the Bank Of Canada web site,
const ext::shared_ptr<OvernightIndex> corraIndex1(new OvernightIndex("CORRA", Natural(fixingDays), currency, calendar, dayCounter, forecastingTermStructure));

Schedule floatingBondSchedule(
Date(4, March, 2021),
Date(4, March, 2025),
Period(Quarterly),
calendar,
ModifiedFollowing, // need to play around this setting
ModifiedFollowing,
DateGeneration::Backward,
false);

DayCounter floater_day_count = ActualActual(ActualActual::ISMA);
FloatingRateBond floatingRateBond(
settlementDays,
faceAmount,
floatingBondSchedule,
corraIndex1,
floater_day_count,
ModifiedFollowing,
Natural(0),
// Gearings
std::vector<Rate>(),
// Caps
std::vector<Rate>(),
// Floors
std::vector<Rate>(),
// Fixing in arrears, need to play around this value
false,
Real(100.0),
Date(25, February, 2021));

floatingRateBond.setPricingEngine(bondEngine);

// Yield curve bootstrapping

/***************
* BOND PRICING *
****************/

std::cout << std::endl;

Leg leg = floatingRateBond.cashflows();
Leg::const_iterator i;
for (i = leg.begin(); i < leg.end(); ++i) {
std::cout << "cashflow date: "
<< (*i)->date() << " cashflow amount: " << (*i)->amount()
<< std::endl;
}

std::cout << "Previous cashflow date: "
<< floatingRateBond.previousCashFlowDate()
<< std::endl;

std::cout << "Next cashflow date: "
<< floatingRateBond.nextCashFlowDate()
<< std::endl;

std::cout << "Accrued coupon: "
<< floatingRateBond.accruedAmount()
<< std::endl;

std::cout << "Previous coupon: "
<< io::rate(floatingRateBond.previousCouponRate())
<< std::endl;

std::cout << "Next coupon: "
<< io::rate(floatingRateBond.nextCouponRate())
<< std::endl;

std::cout << "Net present value: "
<< floatingRateBond.NPV()
<< std::endl;

std::cout << "Clean price: "
<< floatingRateBond.cleanPrice()
<< std::endl;

std::cout << "Dirty price: "
<< floatingRateBond.dirtyPrice()
<< std::endl;

std::cout << "Yield: "
<< floatingRateBond.yield(dayCounter, Compounded, Semiannual)
<< std::endl;

std::cout << std::endl;

return 0;

}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
}
catch (...) {
std::cerr << "unknown error" << std::endl;
return 1;
}


}