Coverage Report

Created: 2025-08-11 06:28

/src/quantlib/ql/experimental/averageois/makearithmeticaverageois.cpp
Line
Count
Source (jump to first uncovered line)
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/makearithmeticaverageois.hpp>
21
#include <ql/pricingengines/swap/discountingswapengine.hpp>
22
#include <ql/indexes/iborindex.hpp>
23
#include <ql/time/schedule.hpp>
24
25
namespace QuantLib {
26
27
    QL_DEPRECATED_DISABLE_WARNING
28
29
    MakeArithmeticAverageOIS::MakeArithmeticAverageOIS(
30
        const Period& swapTenor,
31
        const ext::shared_ptr<OvernightIndex>& overnightIndex,
32
        Rate fixedRate,
33
        const Period& forwardStart)
34
0
    : swapTenor_(swapTenor), overnightIndex_(overnightIndex), fixedRate_(fixedRate),
35
0
      forwardStart_(forwardStart),
36
37
0
      calendar_(overnightIndex->fixingCalendar()),
38
39
0
      fixedDayCount_(overnightIndex->dayCounter()) {}
40
41
0
    MakeArithmeticAverageOIS::operator ArithmeticAverageOIS() const {
42
0
        ext::shared_ptr<ArithmeticAverageOIS> ois = *this;
43
0
        return *ois;
44
0
    }
45
46
0
    MakeArithmeticAverageOIS::operator ext::shared_ptr<ArithmeticAverageOIS>() const {
47
48
0
        Date startDate;
49
0
        if (effectiveDate_ != Date())
50
0
            startDate = effectiveDate_;
51
0
        else {
52
0
            Date refDate = Settings::instance().evaluationDate();
53
            // if the evaluation date is not a business day
54
            // then move to the next business day
55
0
            refDate = calendar_.adjust(refDate);
56
0
            Date spotDate = calendar_.advance(refDate,
57
0
                                              settlementDays_*Days);
58
0
            startDate = spotDate+forwardStart_;
59
0
            if (forwardStart_.length()<0)
60
0
                startDate = calendar_.adjust(startDate, Preceding);
61
0
            else
62
0
                startDate = calendar_.adjust(startDate, Following);
63
0
        }
64
65
        // OIS end of month default
66
0
        bool usedEndOfMonth = 
67
0
            isDefaultEOM_ ? calendar_.isEndOfMonth(startDate) : endOfMonth_;
68
69
0
        Date endDate = terminationDate_;
70
0
        if (endDate == Date()) {
71
0
            if (usedEndOfMonth)
72
0
                endDate = calendar_.advance(startDate,
73
0
                                            swapTenor_,
74
0
                                            ModifiedFollowing,
75
0
                                            usedEndOfMonth);
76
0
            else
77
0
                endDate = startDate + swapTenor_;
78
0
        }
79
80
0
        Schedule fixedLegSchedule(startDate, endDate,
81
0
                          Period(fixedLegPaymentFrequency_),
82
0
                          calendar_,
83
0
                          ModifiedFollowing,
84
0
                          ModifiedFollowing,
85
0
                          rule_,
86
0
                          usedEndOfMonth);
87
88
0
        Schedule overnightLegSchedule(startDate, endDate,
89
0
                          Period(overnightLegPaymentFrequency_),
90
0
                          calendar_,
91
0
                          ModifiedFollowing,
92
0
                          ModifiedFollowing,
93
0
                          rule_,
94
0
                          usedEndOfMonth);
95
96
0
        Rate usedFixedRate = fixedRate_;
97
0
        if (fixedRate_ == Null<Rate>()) {
98
0
            ArithmeticAverageOIS temp(type_, nominal_,
99
0
                                      fixedLegSchedule,
100
0
                                      0.0, // fixed rate
101
0
                                      fixedDayCount_,
102
0
                                      overnightIndex_,
103
0
                                      overnightLegSchedule,
104
0
                                      overnightSpread_,
105
0
                                      mrs_, vol_, byApprox_);
106
0
            if (engine_ == nullptr) {
107
0
                Handle<YieldTermStructure> disc =
108
0
                                    overnightIndex_->forwardingTermStructure();
109
0
                QL_REQUIRE(!disc.empty(),
110
0
                           "null term structure set to this instance of " <<
111
0
                           overnightIndex_->name());
112
0
                bool includeSettlementDateFlows = false;
113
0
                ext::shared_ptr<PricingEngine> engine(new
114
0
                    DiscountingSwapEngine(disc, includeSettlementDateFlows));
115
0
                temp.setPricingEngine(engine);
116
0
            } else
117
0
                temp.setPricingEngine(engine_);
118
119
0
            usedFixedRate = temp.fairRate();
120
0
        }
121
122
0
        ext::shared_ptr<ArithmeticAverageOIS> ois(new
123
0
            ArithmeticAverageOIS(type_, nominal_,
124
0
                                 fixedLegSchedule,
125
0
                                 usedFixedRate, fixedDayCount_,
126
0
                                 overnightIndex_,
127
0
                                 overnightLegSchedule,
128
0
                                 overnightSpread_,
129
0
                                 mrs_, vol_, byApprox_));
130
131
0
        if (engine_ == nullptr) {
132
0
            Handle<YieldTermStructure> disc =
133
0
                                overnightIndex_->forwardingTermStructure();
134
0
            bool includeSettlementDateFlows = false;
135
0
            ext::shared_ptr<PricingEngine> engine(new
136
0
                DiscountingSwapEngine(disc, includeSettlementDateFlows));
137
0
            ois->setPricingEngine(engine);
138
0
        } else
139
0
            ois->setPricingEngine(engine_);
140
141
0
        return ois;
142
0
    }
143
144
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::receiveFixed(bool flag) {
145
0
        type_ = flag ? Swap::Receiver : Swap::Payer;
146
0
        return *this;
147
0
    }
148
149
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withType(Swap::Type type) {
150
0
        type_ = type;
151
0
        return *this;
152
0
    }
153
154
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withNominal(Real n) {
155
0
        nominal_ = n;
156
0
        return *this;
157
0
    }
158
159
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withSettlementDays(Natural settlementDays) {
160
0
        settlementDays_ = settlementDays;
161
0
        effectiveDate_ = Date();
162
0
        return *this;
163
0
    }
164
165
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withEffectiveDate(const Date& effectiveDate) {
166
0
        effectiveDate_ = effectiveDate;
167
0
        return *this;
168
0
    }
169
170
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withTerminationDate(const Date& terminationDate) {
171
0
        terminationDate_ = terminationDate;
172
0
        swapTenor_ = Period();
173
0
        return *this;
174
0
    }
175
176
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withFixedLegPaymentFrequency(Frequency f) {
177
0
        fixedLegPaymentFrequency_ = f;
178
0
        if (fixedLegPaymentFrequency_ == Once)
179
0
            rule_ = DateGeneration::Zero;
180
0
        return *this;
181
0
    }
182
183
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withOvernightLegPaymentFrequency(Frequency f) {
184
0
        overnightLegPaymentFrequency_ = f;
185
0
        if (overnightLegPaymentFrequency_ == Once)
186
0
            rule_ = DateGeneration::Zero;
187
0
        return *this;
188
0
    }
189
190
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withRule(DateGeneration::Rule r) {
191
0
        rule_ = r;
192
0
        if (r==DateGeneration::Zero) {
193
0
            fixedLegPaymentFrequency_ = Once;
194
0
            overnightLegPaymentFrequency_ = Once;
195
0
        }
196
0
        return *this;
197
0
    }
198
199
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withDiscountingTermStructure(
200
0
                                        const Handle<YieldTermStructure>& d) {
201
0
        bool includeSettlementDateFlows = false;
202
0
        engine_ = ext::shared_ptr<PricingEngine>(new
203
0
            DiscountingSwapEngine(d, includeSettlementDateFlows));
204
0
        return *this;
205
0
    }
206
207
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withPricingEngine(
208
0
                             const ext::shared_ptr<PricingEngine>& engine) {
209
0
        engine_ = engine;
210
0
        return *this;
211
0
    }
212
213
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withFixedLegDayCount(const DayCounter& dc) {
214
0
        fixedDayCount_ = dc;
215
0
        return *this;
216
0
    }
217
218
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withEndOfMonth(bool flag) {
219
0
        endOfMonth_ = flag;
220
0
        isDefaultEOM_ = false;
221
0
        return *this;
222
0
    }
223
224
0
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withOvernightLegSpread(Spread sp) {
225
0
        overnightSpread_ = sp;
226
0
        return *this;
227
0
    }
228
229
    MakeArithmeticAverageOIS& MakeArithmeticAverageOIS::withArithmeticAverage(
230
                                            Real meanReversionSpeed,
231
                                            Real volatility,
232
0
                                            bool byApprox) {
233
0
        mrs_ = meanReversionSpeed;
234
0
        vol_ = volatility;
235
0
        byApprox_ = byApprox;
236
0
        return *this;
237
0
    }
238
239
    QL_DEPRECATED_ENABLE_WARNING
240
241
}