This example evaluates a repo on a fixed-coupon bond.
#include <ql/qldefines.hpp>
#ifdef BOOST_MSVC
# include <ql/auto_link.hpp>
#endif
#include <ql/instruments/fixedratebondforward.hpp>
#include <ql/pricingengines/bond/discountingbondengine.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/schedule.hpp>
#include <ql/time/calendars/nullcalendar.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <ql/time/daycounters/thirty360.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>
#if defined(QL_ENABLE_SESSIONS)
}
#endif
int main(int, char* []) {
try {
boost::timer timer;
std::cout << std::endl;
Date repoSettlementDate(14,February,2000);;
Date repoDeliveryDate(15,August,2000);
Date bondIssueDate(15,September,1995);
Date bondDatedDate(15,September,1995);
Date bondMaturityDate(15,September,2005);
Real bondCleanPrice = 89.97693786;
Real bondRedemption = 100.0;
Settings::instance().evaluationDate() = repoSettlementDate;
bondCurve.
linkTo(boost::shared_ptr<YieldTermStructure>(
.01,
bondDayCountConvention,
Compounded,
bondCouponFrequency)));
Schedule bondSchedule(bondDatedDate, bondMaturityDate,
bondCalendar,bondBusinessDayConvention,
bondBusinessDayConvention,
DateGeneration::Backward,false);
boost::shared_ptr<FixedRateBond> bond(
faceAmount,
bondSchedule,
std::vector<Rate>(1,bondCoupon),
bondDayCountConvention,
bondBusinessDayConvention,
bondRedemption,
bondIssueDate));
bond->setPricingEngine(boost::shared_ptr<PricingEngine>(
new DiscountingBondEngine(bondCurve)));
bondCurve.linkTo(boost::shared_ptr<YieldTermStructure> (
bond->yield(bondCleanPrice,
bondDayCountConvention,
Compounded,
bondCouponFrequency),
bondDayCountConvention,
bondCouponFrequency)));
Position::Type fwdType = Position::Long;
double dummyStrike = 91.5745;
repoCurve.linkTo(boost::shared_ptr<YieldTermStructure> (
repoRate,
repoDayCountConvention,
repoCompounding,
repoCompoundFreq)));
repoDeliveryDate,
fwdType,
dummyStrike,
repoSettlementDays,
repoDayCountConvention,
bondCalendar,
bondBusinessDayConvention,
bond,
repoCurve,
repoCurve);
cout << "Underlying bond clean price: "
<< bond->cleanPrice()
<< endl;
cout << "Underlying bond dirty price: "
<< bond->dirtyPrice()
<< endl;
cout << "Underlying bond accrued at settlement: "
<< bond->accruedAmount(repoSettlementDate)
<< endl;
cout << "Underlying bond accrued at delivery: "
<< bond->accruedAmount(repoDeliveryDate)
<< endl;
cout << "Underlying bond spot income: "
<< bondFwd.spotIncome(repoCurve)
<< endl;
cout << "Underlying bond fwd income: "
<< bondFwd.spotIncome(repoCurve)/
repoCurve->discount(repoDeliveryDate)
<< endl;
cout << "Repo strike: "
<< dummyStrike
<< endl;
cout << "Repo NPV: "
<< bondFwd.NPV()
<< endl;
cout << "Repo clean forward price: "
<< bondFwd.cleanForwardPrice()
<< endl;
cout << "Repo dirty forward price: "
<< bondFwd.forwardPrice()
<< endl;
cout << "Repo implied yield: "
<< bondFwd.impliedYield(bond->dirtyPrice(),
dummyStrike,
repoSettlementDate,
repoCompounding,
repoDayCountConvention)
<< endl;
cout << "Market repo rate: "
<< repoCurve->zeroRate(repoDeliveryDate,
repoDayCountConvention,
repoCompounding,
repoCompoundFreq)
<< endl
<< endl;
cout << "Compare with example given at \n"
<< "http://www.fincad.com/support/developerFunc/mathref/BFWD.htm"
<< endl;
cout << "Clean forward price = 88.2408"
<< endl
<< endl;
cout << "In that example, it is unknown what bond calendar they are\n"
<< "using, as well as settlement Days. For that reason, I have\n"
<< "made the simplest possible assumptions here: NullCalendar\n"
<< "and 0 settlement days."
<< endl;
double seconds = timer.elapsed();
seconds -= hours * 3600;
seconds -= minutes * 60;
cout << " \nRun completed in ";
if (hours > 0)
cout << hours << " h ";
if (hours > 0 || minutes > 0)
cout << minutes << " m ";
cout << fixed << setprecision(0)
<< seconds << " s\n" << endl;
return 0;
} catch (exception& e) {
cerr << e.what() << endl;
return 1;
} catch (...) {
cerr << "unknown error" << endl;
return 1;
}
}