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 ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi Toby,
my understanding is, that the BlackSwaptionEngine implements the standard market formula for cash settled swaptions as e.g. derived in Brigo/Mercurio 6.7.2, which is the physical delivery formula with the annuity A(0) replaced by the cash annuity G(S(0)). The latter is by definition the annuity (at time t=0) computed on a flat yield curve with rate InterestRate(atmForward, dayCount, Compounded, Annual) which can be computed using Real CashFlows::bps(const Leg& leg, const InterestRate& yield, bool includeSettlementDateFlows, Date settlementDate, Date npvDate) (note that in 2) you refer to a different signature of the bps method taking a curve instead of a single yield). In the call of bps the settlementDate is set to discountCurve_->referenceDate(), and since the npvDate is not given it is defaulted to the same date. This means that the annuity and therefore in the end the npv of the swaption is computed w.r.t. the reference date of the discountCurve_ of the pricing engine. What I am not toally sure about at the moment is the exact market definition of G(S), we have at least - Brigo/Mercurio 6.7.2 = QuantLib::BlackSwaptionEngine - the OpenGamma paper you mention, 2.2 - Andersen / Piterbarg 5.10.1 all of which being slightly different for certain date scenarios. Can someone clarify ? Also I believe the implied volatility quotes you can get on VCAP for EUR are for cash settled swaptions. Can someone confirm ? If true, how do you price physical delivered swaptions, with the same volatility ? Or do you imply a "physical" smile from the "cash" smile (say by "inverting" a replication model for the cash settled swaptions) ? best regards Peter On 6 February 2014 14:13, Nils Tobias Kramer <[hidden email]> wrote: > 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 > > ------------------------------------------------------------------------------ > Managing the Performance of Cloud-Based Applications > Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. > Read the Whitepaper. > http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk > _______________________________________________ > QuantLib-users mailing list > [hidden email] > https://lists.sourceforge.net/lists/listinfo/quantlib-users > ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi Peter,
thanks a lot for your reply. I was just copying the bps code for the yield curve because this is the last overload function that takes just a flat curve which is build by some other overload function that takes a single rate. So in the end it comes to the question how G(s) is defined. Your thought about the two different smiles is also interesting. Have a nice weekend Toby > On 08.02.2014, at 08:39, Peter Caspers <[hidden email]> wrote: > > Hi Toby, > > my understanding is, that the BlackSwaptionEngine implements the > standard market formula for cash settled swaptions as e.g. derived in > Brigo/Mercurio 6.7.2, which is the physical delivery formula with the > annuity A(0) replaced by the cash annuity G(S(0)). The latter is by > definition the annuity (at time t=0) computed on a flat yield curve > with rate > > InterestRate(atmForward, dayCount, Compounded, Annual) > > which can be computed using > > Real CashFlows::bps(const Leg& leg, > const InterestRate& yield, > bool includeSettlementDateFlows, > Date settlementDate, > Date npvDate) > > (note that in 2) you refer to a different signature of the bps method > taking a curve instead of a single yield). In the call of bps the > settlementDate is set to discountCurve_->referenceDate(), and since > the npvDate is not given it is defaulted to the same date. This means > that the annuity and therefore in the end the npv of the swaption is > computed w.r.t. the reference date of the discountCurve_ of the > pricing engine. > > What I am not toally sure about at the moment is the exact market > definition of G(S), we have at least > > - Brigo/Mercurio 6.7.2 = QuantLib::BlackSwaptionEngine > - the OpenGamma paper you mention, 2.2 > - Andersen / Piterbarg 5.10.1 > > all of which being slightly different for certain date scenarios. Can > someone clarify ? > > Also I believe the implied volatility quotes you can get on VCAP for > EUR are for cash settled swaptions. Can someone confirm ? If true, how > do you price physical delivered swaptions, with the same volatility ? > Or do you imply a "physical" smile from the "cash" smile (say by > "inverting" a replication model for the cash settled swaptions) ? > > best regards > Peter > >> On 6 February 2014 14:13, Nils Tobias Kramer <[hidden email]> wrote: >> 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 >> >> ------------------------------------------------------------------------------ >> Managing the Performance of Cloud-Based Applications >> Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. >> Read the Whitepaper. >> http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk >> _______________________________________________ >> QuantLib-users mailing list >> [hidden email] >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Free forum by Nabble | Edit this page |