1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2016 Stefano Fondi
5 
6  This file is part of QuantLib, a free-software/open-source library
7  for financial quantitative analysts and developers - http://quantlib.org/
8 
9  QuantLib is free software: you can redistribute it and/or modify it
10  under the terms of the QuantLib license.  You should have received a
11  copy of the license along with this program; if not, please email
12  <quantlib-dev@lists.sf.net>. The license is also available online at
13  <http://quantlib.org/license.shtml>.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the license for more details.
18 */
19 
20 #include <ql/experimental/averageois/arithmeticaverageois.hpp>
21 #include <ql/experimental/averageois/averageoiscouponpricer.hpp>
22 #include <ql/cashflows/overnightindexedcoupon.hpp>
23 #include <ql/cashflows/fixedratecoupon.hpp>
24 
25 namespace QuantLib {
26 
ArithmeticAverageOIS(Type type,Real nominal,const Schedule & fixedLegSchedule,Rate fixedRate,const DayCounter & fixedDC,const ext::shared_ptr<OvernightIndex> & overnightIndex,const Schedule & overnightLegSchedule,Spread spread,Real meanReversionSpeed,Real volatility,bool byApprox)27     ArithmeticAverageOIS::ArithmeticAverageOIS(
28                     Type type,
29                     Real nominal,
30                     const Schedule& fixedLegSchedule,
31                     Rate fixedRate,
32                     const DayCounter& fixedDC,
33                     const ext::shared_ptr<OvernightIndex>& overnightIndex,
34                     const Schedule& overnightLegSchedule,
35                     Spread spread,
36                     Real meanReversionSpeed,
37                     Real volatility,
38                     bool byApprox)
39     : Swap(2), type_(type),
40       nominals_(std::vector<Real>(1, nominal)),
41       fixedLegPaymentFrequency_(fixedLegSchedule.tenor().frequency()),
42       overnightLegPaymentFrequency_(overnightLegSchedule.tenor().frequency()),
43       fixedRate_(fixedRate), fixedDC_(fixedDC),
44       overnightIndex_(overnightIndex),
45       spread_(spread), byApprox_(byApprox), mrs_(meanReversionSpeed),
46       vol_(volatility) {
47 
48         initialize(fixedLegSchedule, overnightLegSchedule);
49 
50     }
51 
ArithmeticAverageOIS(Type type,const std::vector<Real> & nominals,const Schedule & fixedLegSchedule,Rate fixedRate,const DayCounter & fixedDC,const ext::shared_ptr<OvernightIndex> & overnightIndex,const Schedule & overnightLegSchedule,Spread spread,Real meanReversionSpeed,Real volatility,bool byApprox)52     ArithmeticAverageOIS::ArithmeticAverageOIS(
53         Type type,
54         const std::vector<Real>& nominals,
55         const Schedule& fixedLegSchedule,
56         Rate fixedRate,
57         const DayCounter& fixedDC,
58         const ext::shared_ptr<OvernightIndex>& overnightIndex,
59         const Schedule& overnightLegSchedule,
60         Spread spread,
61         Real meanReversionSpeed,
62         Real volatility,
63         bool byApprox)
64     : Swap(2), type_(type), nominals_(nominals),
65       fixedLegPaymentFrequency_(fixedLegSchedule.tenor().frequency()),
66       overnightLegPaymentFrequency_(overnightLegSchedule.tenor().frequency()),
67       fixedRate_(fixedRate), fixedDC_(fixedDC), overnightIndex_(overnightIndex), spread_(spread),
68       byApprox_(byApprox), mrs_(meanReversionSpeed), vol_(volatility) {
69 
70         initialize(fixedLegSchedule, overnightLegSchedule);
71 
72     }
73 
initialize(const Schedule & fixedLegSchedule,const Schedule & overnightLegSchedule)74     void ArithmeticAverageOIS::initialize(const Schedule& fixedLegSchedule,
75                                           const Schedule& overnightLegSchedule) {
76         if (fixedDC_==DayCounter())
77             fixedDC_ = overnightIndex_->dayCounter();
78         legs_[0] = FixedRateLeg(fixedLegSchedule)
79             .withNotionals(nominals_)
80             .withCouponRates(fixedRate_, fixedDC_);
81 
82         legs_[1] = OvernightLeg(overnightLegSchedule, overnightIndex_)
83             .withNotionals(nominals_)
84             .withSpreads(spread_);
85 
86         ext::shared_ptr<FloatingRateCouponPricer> arithmeticPricer(
87                 new ArithmeticAveragedOvernightIndexedCouponPricer(mrs_, vol_, byApprox_));
88 
89         for (Size i = 0; i < legs_[1].size(); i++) {
90             ext::shared_ptr<OvernightIndexedCoupon>
91                 c = ext::dynamic_pointer_cast<OvernightIndexedCoupon> (legs_[1][i]);
92             c->setPricer(arithmeticPricer);
93         }
94 
95         for (Size j=0; j<2; ++j) {
96             for (Leg::iterator i = legs_[j].begin(); i!= legs_[j].end(); ++i)
97                 registerWith(*i);
98         }
99 
100         switch (type_) {
101           case Payer:
102             payer_[0] = -1.0;
103             payer_[1] = +1.0;
104             break;
105           case Receiver:
106             payer_[0] = +1.0;
107             payer_[1] = -1.0;
108             break;
109           default:
110             QL_FAIL("Unknown overnight-swap type");
111         }
112     }
113 
fairRate() const114     Real ArithmeticAverageOIS::fairRate() const {
115         static Spread basisPoint = 1.0e-4;
116         calculate();
117         return fixedRate_ - NPV_/(fixedLegBPS()/basisPoint);
118     }
119 
fairSpread() const120     Spread ArithmeticAverageOIS::fairSpread() const {
121         static Spread basisPoint = 1.0e-4;
122         calculate();
123         return spread_ - NPV_/(overnightLegBPS()/basisPoint);
124     }
125 
fixedLegBPS() const126     Real ArithmeticAverageOIS::fixedLegBPS() const {
127         calculate();
128         QL_REQUIRE(legBPS_[0] != Null<Real>(), "result not available");
129         return legBPS_[0];
130     }
131 
overnightLegBPS() const132     Real ArithmeticAverageOIS::overnightLegBPS() const {
133         calculate();
134         QL_REQUIRE(legBPS_[1] != Null<Real>(), "result not available");
135         return legBPS_[1];
136     }
137 
fixedLegNPV() const138     Real ArithmeticAverageOIS::fixedLegNPV() const {
139         calculate();
140         QL_REQUIRE(legNPV_[0] != Null<Real>(), "result not available");
141         return legNPV_[0];
142     }
143 
overnightLegNPV() const144     Real ArithmeticAverageOIS::overnightLegNPV() const {
145         calculate();
146         QL_REQUIRE(legNPV_[1] != Null<Real>(), "result not available");
147         return legNPV_[1];
148     }
149 
150 }
151