http://quantlib.414.s1.nabble.com/pricing-cash-settled-swaptions-tp14943.html
Hi there,
I'm using QuantLib to price cash settled swaptions in C# using the swig interface and I'm using Quantlib 1.2.1.
When pricing a cash settled swaption I expect the cashflows of the swap to be discounted using the constant swap rate looking from the swaption expiration date (=swap start date). So I expected the discount factor used to calculate the annuity factor in front of the black scholes formula used to price physical swaptions to be Sum_i[(1+YF*SR)^(i)] (where YF is the year fraction between the swap's payments, SR is the swap par rate calculated at my valuation date, and i is an integer for the swap's payment dates).
However I think QuantLib uses a different time span, namely the time between swap payments and the discount curve reference date and not swaption expiry date.
In order to fix this I calculate the swaptions NPV and then multiply this by (1+SR)^(YF), where YF is the year fraction between evaluation date and the swap
start date using 30/360 day count convention. This way the pricing is in line with
http://developers.opengamma.com/quantitative-research/Swaption-
Pricing-OpenGamma.pdf p.3, 5.1, where G(S) is defined at the top of p. 2.
The problem I have is that I need to calculate the swap par rate and therefore I need to create a swap and price this swap which I actually don't need.
Here are the relevant lines:
1) blackswaptionengine.cpp:
case Settlement::Cash: {
const Leg& fixedLeg = swap.fixedLeg();
boost::shared_ptr<FixedRateCoupon> firstCoupon =
boost::dynamic_pointer_cast<FixedRateCoupon>(fixedLeg[0]);
DayCounter dayCount = firstCoupon->dayCounter();
Real fixedLegCashBPS =
CashFlows::bps(fixedLeg,
InterestRate(atmForward, dayCount, Compounded, Annual),
false, discountCurve_->referenceDate()) ;
annuity = std::fabs(fixedLegCashBPS/basisPoint);
break;
}
-> especially CashFlows::bps(fixedLeg, InterestRate(atmForward, dayCount, Compounded, Annual), false, discountCurve_->referenceDate());
2) cashflows.cpp:
Real CashFlows::bps(const Leg& leg,
const YieldTermStructure& discountCurve,
bool includeSettlementDateFlows,
Date settlementDate,
Date npvDate) {
if (leg.empty())
return 0.0;
if (settlementDate == Date())
settlementDate = Settings::instance().evaluationDate();
if (npvDate == Date())
npvDate = settlementDate;
BPSCalculator calc(discountCurve);
for (Size i=0; i<leg.size(); ++i) {
if (!leg[i]->hasOccurred(settlementDate,
includeSettlementDateFlows))
leg[i]->accept(calc);
}
return basisPoint_*calc.bps()/discountCurve.discount(npvDate);
}
-> especially return basisPoint_*calc.bps()/discountCurve.discount(npvDate);
This surprises me as discountCurve.discount(npvDate) is equal to discountCurve.discount(discountCurve_->referenceDate()) which should be 1, right?
Anyways I'm a bit confused and every suggestion is appreciated.
Thanks
Toby