pricing cash settled swaptions

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

pricing cash settled swaptions

Nils Tobias Kramer
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
Reply | Threaded
Open this post in threaded view
|

Re: pricing cash settled swaptions

Peter Caspers-4
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
Reply | Threaded
Open this post in threaded view
|

Re: pricing cash settled swaptions

Nils Tobias Kramer
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