Estoy tratando de entender cómo QuantLib crea (se levanta) una curva de rendimiento de una vainilla de intercambio en el nivel de la fuente. Tengo el siguiente código de prueba:
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;
}
Esta es, obviamente, un juguete ejemplo. Tengo dos depósitos que se da a las tasas de descuento para los primeros dos años. Mi swap es un evento anual de 3 años de swap, espero que el swap me da la tasa de descuento para el tercer año. Tengo el valor, pero no entiendo cómo se calcula.
El código de arranque de un factor de descuento de un swap es:
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;
}
Cada vez QuantLib adivina un nuevo factor de descuento (es decir, de forma iterativa bootstrapping), esta función calcula un nuevo valor actual neto para el flotante de la pierna. Yo esperaría que este VPN se establece igual a la VPN de la pata fija, a partir de la cual un nuevo swap de tasa puede ser calculada.
Lo que no entiendo es esta línea en particular:
Real result = totNPV/(swap_->fixedLegBPS()/basisPoint);
Creo BPS es la suma exacta de interés y se calcula por:
bps += cp->nominal() * cp->accrualPeriod() * df;
Pregunta:
¿Por qué necesitamos dividir el nuevo fijo piernas VAN por el BPS y basisPoint? Por qué basisPoint se establece a 1.0 e-4 (1 punto)? ¿Cuál es el punto de hacerlo?