I'm trying to understand how QuantLib creates (bootstraps) a yield curve from a vanilla swap at the source level. I have the following test code:
void testYieldFromIRSwap()
{
Settings::instance().evaluationDate() = Date(1, Jan, 2015);
auto dc = Actual360();
auto h1 = boost::shared_ptr<RateHelper>(new DepositRateHelper
(0.03, Period(1, Years), 0.0, UnitedStates(), Following, false, Actual360()));
auto h2 = boost::shared_ptr<RateHelper>(new DepositRateHelper
(0.04, Period(2, Years), 0.0, UnitedStates(), Following, false, Actual360()));
auto index = boost::shared_ptr<IborIndex>(new EURLibor1Y());
auto h3 = boost::shared_ptr<RateHelper>(
new SwapRateHelper(0.05, Period(3, Years), UnitedStates(), Annual,
Following, Actual360(), index));
std::vector<boost::shared_ptr<RateHelper>> helpers;
helpers.push_back(h1);
helpers.push_back(h2);
helpers.push_back(h3);
boost::shared_ptr<YieldTermStructure> yield(
new PiecewiseYieldCurve<Discount,LogLinear>(
Settings::instance().evaluationDate(), helpers,
Actual360()));
const auto t1 = dc.yearFraction(Date(1, Jan, 2015), Date(1, Jan, 2016)); // 1.014
const auto t2 = dc.yearFraction(Date(1, Jan, 2015), Date(1, Jan, 2017)); // 2.031
const auto t3 = dc.yearFraction(Date(1, Jan, 2015), Date(1, Jan, 2018)); // 3.044
std::cout << yield->discount(0) << std::endl; // Must be 1
std::cout << yield->discount(t1) << std::endl; // 1/((1+0.03) ^ 1.014) = 0.9704721
std::cout << yield->discount(t2) << std::endl; // 1/(1+0.04) ^ 2.031 = 0.9234328
std::cout << yield->discount(t3) << std::endl;
}
This is obviously a toy example. I have two deposits that gives the discount rates for the first two years. My swap is an annual 3y swap, I expect the swap gives me the discount rate for the the third year. I do get the value but I don't understand how it's computed.
The code for bootstrapping a discount factor from a swap is:
Real SwapRateHelper::impliedQuote() const {
QL_REQUIRE(termStructure_ != 0, "term structure not set");
// we didn't register as observers - force calculation
swap_->recalculate();
// weak implementation... to be improved
static const Spread basisPoint = 1.0e-4;
Real floatingLegNPV = swap_->floatingLegNPV();
Spread spread = spread_.empty() ? 0.0 : spread_->value();
Real spreadNPV = swap_->floatingLegBPS()/basisPoint*spread;
Real totNPV = - (floatingLegNPV+spreadNPV);
Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
return result;
}
Everytime when QuantLib guesses a new discount factor (i.e. iteratively bootstrapping), this function computes a new NPV for the floating leg. I'd expect this NPV be set to equal to the NPV for the fixed leg, from which a new swap rate can be computed.
What I don't understand is this particular line:
Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
I think BPS is the sum of accurate interest and is computed by:
bps += cp->nominal() * cp->accrualPeriod() * df;
Question:
Why do we need to divide the new fixed-leg NPV by BPS and basisPoint? Why basisPoint is set to 1.0e-4 (1 basis point)? What's the point of doing it?