1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2007, 2009, 2011 Chris Kenyon
5  Copyright (C) 2009 StatPro Italia srl
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 cpiswap.hpp
22  \brief zero-inflation-indexed-ratio-with-base swap
23  */
24 
25 #ifndef quantlib_zeroinflationswap_hpp
26 #define quantlib_zeroinflationswap_hpp
27 
28 #include <ql/instruments/swap.hpp>
29 #include <ql/time/calendar.hpp>
30 #include <ql/time/daycounter.hpp>
31 #include <ql/time/schedule.hpp>
32 #include <ql/indexes/iborindex.hpp>
33 #include <ql/cashflows/cpicoupon.hpp>
34 
35 namespace QuantLib {
36 
37     class ZeroInflationIndex;
38 
39     //! zero-inflation-indexed swap,
40     /*! fixed x zero-inflation, i.e. fixed x CPI(i'th fixing)/CPI(base)
41         versus floating + spread
42 
43         Note that this does ony the inflation-vs-floating-leg.
44         Extension to inflation-vs-fixed-leg.  is simple - just replace
45         the floating leg with a fixed leg.
46 
47         Typically there are notional exchanges at the end: either
48         inflated-notional vs notional; or just (inflated-notional -
49         notional) vs zero.  The latter is perhaphs more typical.
50         \warning Setting subtractInflationNominal to true means that
51         the original inflation nominal is subtracted from both
52         nominals before they are exchanged, even if they are
53         different.
54 
55         This swap can mimic a ZCIIS where [(1+q)^n - 1] is exchanged
56         against (cpi ratio - 1), by using differnt nominals on each
57         leg and setting subtractInflationNominal to true.  ALSO -
58         there must be just one date in each schedule.
59 
60         The two legs can have different schedules, fixing (days vs
61         lag), settlement, and roll conventions.  N.B. accrual
62         adjustment periods are already in the schedules.  Trade date
63         and swap settlement date are outside the scope of the
64         instrument.
65     */
66     class CPISwap : public Swap {
67       public:
68         enum Type { Receiver = -1, Payer = 1 };
69         class arguments;
70         class results;
71         class engine;
72 
73         CPISwap(Type type,
74                 Real nominal,
75                 bool subtractInflationNominal,
76                 // float+spread leg
77                 Spread spread,
78                 const DayCounter& floatDayCount,
79                 const Schedule& floatSchedule,
80                 const BusinessDayConvention& floatRoll,
81                 Natural fixingDays,
82                 const ext::shared_ptr<IborIndex>& floatIndex,
83                 // fixed x inflation leg
84                 Rate fixedRate,
85                 Real baseCPI,
86                 const DayCounter& fixedDayCount,
87                 const Schedule& fixedSchedule,
88                 const BusinessDayConvention& fixedRoll,
89                 const Period& observationLag,
90                 const ext::shared_ptr<ZeroInflationIndex>& fixedIndex,
91                 CPI::InterpolationType observationInterpolation = CPI::AsIndex,
92                 Real inflationNominal = Null<Real>()
93                 );
94 
95         // results
96         // float+spread
97         virtual Real floatLegNPV() const;
98         virtual Spread fairSpread() const;
99         // fixed rate x inflation
100         virtual Real fixedLegNPV() const;
101         virtual Rate fairRate() const;
102 
103         // inspectors
104         virtual Type type() const;
105         virtual Real nominal() const;
106         virtual bool subtractInflationNominal() const;
107 
108         // float+spread
109         virtual Spread spread() const;
110         virtual const DayCounter& floatDayCount() const;
111         virtual const Schedule& floatSchedule() const;
112         virtual const BusinessDayConvention& floatPaymentRoll() const;
113         virtual Natural fixingDays() const;
114         virtual const ext::shared_ptr<IborIndex>& floatIndex() const;
115 
116         // fixed rate x inflation
117         virtual Rate fixedRate() const;
118         virtual Real baseCPI() const;
119         virtual const DayCounter& fixedDayCount() const;
120         virtual const Schedule& fixedSchedule() const;
121         virtual const BusinessDayConvention& fixedPaymentRoll() const;
122         virtual Period observationLag() const;
123         virtual const ext::shared_ptr<ZeroInflationIndex>& fixedIndex() const;
124         virtual CPI::InterpolationType observationInterpolation() const;
125         virtual Real inflationNominal() const;
126 
127         // legs
128         virtual const Leg& cpiLeg() const;
129         virtual const Leg& floatLeg() const;
130 
131         // other
132         void setupArguments(PricingEngine::arguments* args) const;
133         void fetchResults(const PricingEngine::results*) const;
134 
135       private:
136         void setupExpired() const;
137 
138         Type type_;
139         Real nominal_;
140         bool subtractInflationNominal_;
141 
142         // float+spread leg
143         Spread spread_;
144         DayCounter floatDayCount_;
145         Schedule floatSchedule_;
146         BusinessDayConvention floatPaymentRoll_;
147         Natural fixingDays_;
148         ext::shared_ptr<IborIndex> floatIndex_;
149 
150         // fixed x inflation leg
151         Rate fixedRate_;
152         Real baseCPI_;
153         DayCounter fixedDayCount_;
154         Schedule fixedSchedule_;
155         BusinessDayConvention fixedPaymentRoll_;
156         ext::shared_ptr<ZeroInflationIndex> fixedIndex_;
157         Period observationLag_;
158         CPI::InterpolationType observationInterpolation_;
159         Real inflationNominal_;
160         // results
161         mutable Spread fairSpread_;
162         mutable Rate fairRate_;
163 
164     };
165 
166 
167     //! %Arguments for swap calculation
168     class CPISwap::arguments : public Swap::arguments {
169     public:
arguments()170         arguments() : type(Receiver),
171         nominal(Null<Real>()) {}
172         Type type;
173         Real nominal;
174 
175         void validate() const;
176     };
177 
178     //! %Results from swap calculation
179     class CPISwap::results : public Swap::results {
180     public:
181         Rate fairRate;
182         Spread fairSpread;
183         void reset();
184     };
185 
186     class CPISwap::engine : public GenericEngine<CPISwap::arguments,
187                                                  CPISwap::results> {};
188 
189 
190     // inline definitions
191 
192     // inspectors
type() const193     inline  CPISwap::Type CPISwap::type() const { return type_; }
nominal() const194     inline  Real CPISwap::nominal() const { return nominal_; }
subtractInflationNominal() const195     inline  bool CPISwap::subtractInflationNominal() const { return subtractInflationNominal_; }
196 
197     // float+spread
spread() const198     inline Spread CPISwap::spread() const { return spread_; }
floatDayCount() const199     inline const DayCounter& CPISwap::floatDayCount() const { return floatDayCount_; }
floatSchedule() const200     inline const Schedule& CPISwap::floatSchedule() const { return floatSchedule_; }
floatPaymentRoll() const201     inline const BusinessDayConvention& CPISwap::floatPaymentRoll() const { return floatPaymentRoll_; }
fixingDays() const202     inline Natural CPISwap::fixingDays() const { return fixingDays_; }
floatIndex() const203     inline const ext::shared_ptr<IborIndex>& CPISwap::floatIndex() const { return floatIndex_; }
204 
205     // fixed rate x inflation
fixedRate() const206     inline Rate CPISwap::fixedRate() const { return fixedRate_; }
baseCPI() const207     inline Real CPISwap::baseCPI() const { return baseCPI_; }
fixedDayCount() const208     inline const DayCounter& CPISwap::fixedDayCount() const { return fixedDayCount_; }
fixedSchedule() const209     inline const Schedule& CPISwap::fixedSchedule() const { return fixedSchedule_; }
fixedPaymentRoll() const210     inline const BusinessDayConvention& CPISwap::fixedPaymentRoll() const { return fixedPaymentRoll_; }
observationLag() const211     inline Period CPISwap::observationLag() const { return observationLag_; }
fixedIndex() const212     inline const ext::shared_ptr<ZeroInflationIndex>& CPISwap::fixedIndex() const { return fixedIndex_; }
observationInterpolation() const213     inline CPI::InterpolationType CPISwap::observationInterpolation() const { return observationInterpolation_; }
inflationNominal() const214     inline Real CPISwap::inflationNominal() const { return inflationNominal_; }
215 
cpiLeg() const216     inline const Leg& CPISwap::cpiLeg() const {//inflation indexed
217         return legs_[0];
218     }
219 
floatLeg() const220     inline const Leg& CPISwap::floatLeg() const {
221         return legs_[1];
222     }
223 
224     std::ostream& operator<<(std::ostream& out, CPISwap::Type t);
225 
226 }
227 
228 #endif
229 
230