1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4   Copyright (C) 2007 Cristina Duminuco
5   Copyright (C) 2007 Giorgio Facchinetti
6 
7  This file is part of QuantLib, a free-software/open-source library
8  for financial quantitative analysts and developers - http://quantlib.org/
9 
10  QuantLib is free software: you can redistribute it and/or modify it
11  under the terms of the QuantLib license.  You should have received a
12  copy of the license along with this program; if not, please email
13  <quantlib-dev@lists.sf.net>. The license is also available online at
14  <http://quantlib.org/license.shtml>.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the license for more details.
19 */
20 
21 /*! \file digitalcoupon.hpp
22     \brief Floating-rate coupon with digital call/put option
23 */
24 
25 #ifndef quantlib_digital_coupon_hpp
26 #define quantlib_digital_coupon_hpp
27 
28 #include <ql/cashflows/floatingratecoupon.hpp>
29 #include <ql/cashflows/couponpricer.hpp>
30 #include <ql/cashflows/replication.hpp>
31 #include <ql/position.hpp>
32 #include <ql/utilities/null.hpp>
33 
34 namespace QuantLib {
35 
36     //! Digital-payoff coupon
37     /*! Implementation of a floating-rate coupon with digital call/put option.
38         Payoffs:
39         - Coupon with cash-or-nothing Digital Call
40           rate + csi * payoffRate * Heaviside(rate-strike)
41         - Coupon with cash-or-nothing Digital Put
42           rate + csi * payoffRate * Heaviside(strike-rate)
43         where csi=+1 or csi=-1.
44         - Coupon with asset-or-nothing Digital Call
45           rate + csi * rate * Heaviside(rate-strike)
46         - Coupon with asset-or-nothing Digital Put
47           rate + csi * rate * Heaviside(strike-rate)
48         where csi=+1 or csi=-1. If nakedOption is true, the rate in the
49         payoffs is set to zero.
50         The evaluation of the coupon is made using the call/put spread
51         replication method.
52     */
53     /*! \ingroup instruments
54 
55         \test
56         - the correctness of the returned value in case of Asset-or-nothing
57           embedded option is tested by pricing the digital option with
58           Cox-Rubinstein formula.
59         - the correctness of the returned value in case of deep-in-the-money
60           Asset-or-nothing embedded option is tested vs the expected values of
61           coupon and option.
62         - the correctness of the returned value in case of deep-out-of-the-money
63           Asset-or-nothing embedded option is tested vs the expected values of
64           coupon and option.
65         - the correctness of the returned value in case of Cash-or-nothing
66           embedded option is tested by pricing the digital option with
67           Reiner-Rubinstein formula.
68         - the correctness of the returned value in case of deep-in-the-money
69           Cash-or-nothing embedded option is tested vs the expected values of
70           coupon and option.
71         - the correctness of the returned value in case of deep-out-of-the-money
72           Cash-or-nothing embedded option is tested vs the expected values of
73           coupon and option.
74         - the correctness of the returned value is tested checking the correctness
75           of the call-put parity relation.
76         - the correctness of the returned value is tested by the relationship
77           between prices in case of different replication types.
78     */
79     class DigitalCoupon : public FloatingRateCoupon {
80       public:
81         //! \name Constructors
82         //@{
83         //! general constructor
84         DigitalCoupon(const ext::shared_ptr<FloatingRateCoupon>& underlying,
85                       Rate callStrike = Null<Rate>(),
86                       Position::Type callPosition = Position::Long,
87                       bool isCallITMIncluded = false,
88                       Rate callDigitalPayoff = Null<Rate>(),
89                       Rate putStrike = Null<Rate>(),
90                       Position::Type putPosition = Position::Long,
91                       bool isPutITMIncluded = false,
92                       Rate putDigitalPayoff = Null<Rate>(),
93                       const ext::shared_ptr<DigitalReplication>& replication =
94                         ext::shared_ptr<DigitalReplication>(),
95                       bool nakedOption = false);
96 
97         //@}
98         //! \name Coupon interface
99         //@{
100         Rate rate() const;
101         Rate convexityAdjustment() const;
102         //@}
103         //@}
104         //! \name Digital inspectors
105         //@{
106         Rate callStrike() const;
107         Rate putStrike() const;
108         Rate callDigitalPayoff() const;
109         Rate putDigitalPayoff() const;
hasPut() const110         bool hasPut() const { return hasPutStrike_; }
hasCall() const111         bool hasCall() const {return hasCallStrike_; }
hasCollar() const112         bool hasCollar() const {return (hasCallStrike_ && hasPutStrike_); }
isLongPut() const113         bool isLongPut() const { return (putCsi_==1.); }
isLongCall() const114         bool isLongCall() const { return (callCsi_==1.); }
underlying() const115         ext::shared_ptr<FloatingRateCoupon> underlying() const { return underlying_; }
116         /*! Returns the call option rate
117            (multiplied by: nominal*accrualperiod*discount is the NPV of the option)
118         */
119         Rate callOptionRate() const;
120         /*! Returns the put option rate
121            (multiplied by: nominal*accrualperiod*discount is the NPV of the option)
122         */
123         Rate putOptionRate() const;
124         //@}
125         //! \name Observer interface
126         //@{
127         void update();
128         //@}
129         //! \name Visitability
130         //@{
131         virtual void accept(AcyclicVisitor&);
132 
setPricer(const ext::shared_ptr<FloatingRateCouponPricer> & pricer)133         void setPricer(
134             const ext::shared_ptr<FloatingRateCouponPricer>& pricer) {
135             if (pricer_ != 0)
136                 unregisterWith(pricer_);
137             pricer_ = pricer;
138             if (pricer_ != 0)
139                 registerWith(pricer_);
140             update();
141             underlying_->setPricer(pricer);
142         }
143 
144         protected:
145         //! \name Data members
146         //@{
147         //!
148         ext::shared_ptr<FloatingRateCoupon> underlying_;
149         //! strike rate for the the call option
150         Rate callStrike_;
151         //! strike rate for the the put option
152         Rate putStrike_;
153         //! multiplicative factor of call payoff
154         Real callCsi_;
155         //! multiplicative factor of put payoff
156         Real putCsi_;
157         //! inclusion flag og the call payoff if the call option ends at-the-money
158         bool isCallATMIncluded_;
159         //! inclusion flag og the put payoff if the put option ends at-the-money
160         bool isPutATMIncluded_;
161         //! digital call option type: if true, cash-or-nothing, if false asset-or-nothing
162         bool isCallCashOrNothing_;
163         //! digital put option type: if true, cash-or-nothing, if false asset-or-nothing
164         bool isPutCashOrNothing_;
165         //! digital call option payoff rate, if any
166         Rate callDigitalPayoff_;
167         //! digital put option payoff rate, if any
168         Rate putDigitalPayoff_;
169         //! the left and right gaps applied in payoff replication for call
170         Real callLeftEps_, callRightEps_;
171         //! the left and right gaps applied in payoff replication for put
172         Real putLeftEps_, putRightEps_;
173         //!
174         bool hasPutStrike_, hasCallStrike_;
175         //! Type of replication
176         Replication::Type replicationType_;
177         //! underlying excluded from the payoff
178         bool nakedOption_;
179 
180         //@}
181       private:
182         Rate callPayoff() const;
183         Rate putPayoff() const;
184 
185     };
186 
187 }
188 
189 #endif
190