1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4Copyright (C) 2023 Marcin Rybacki
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/cashflows/equitycashflow.hpp>
21#include <ql/cashflows/iborcoupon.hpp>
22#include <ql/cashflows/overnightindexedcoupon.hpp>
23#include <ql/indexes/equityindex.hpp>
24#include <ql/instruments/equitytotalreturnswap.hpp>
25#include <utility>
26
27namespace QuantLib {
28
29 namespace {
30 ext::shared_ptr<CashFlow>
31 createEquityCashFlow(const Schedule& schedule,
32 const ext::shared_ptr<EquityIndex>& equityIndex,
33 Real nominal,
34 const Calendar& paymentCalendar,
35 BusinessDayConvention paymentConvention,
36 Natural paymentDelay) {
37 Date startDate = schedule.startDate();
38 Date endDate = schedule.endDate();
39
40 Calendar cal = paymentCalendar;
41 if (cal.empty()) {
42 QL_REQUIRE(!schedule.calendar().empty(), "Calendar in schedule cannot be empty");
43 cal = schedule.calendar();
44 }
45 Date paymentDate =
46 cal.advance(endDate, n: paymentDelay, unit: Days, convention: paymentConvention, endOfMonth: schedule.endOfMonth());
47 return ext::make_shared<EquityCashFlow>(args&: nominal, args: equityIndex, args&: startDate, args&: endDate,
48 args&: paymentDate);
49 }
50
51 template <typename IndexType, typename LegType>
52 Leg createInterestLeg(const Schedule& schedule,
53 const ext::shared_ptr<IndexType>& interestRateIndex,
54 Real nominal,
55 const DayCounter& dayCounter,
56 Rate margin,
57 Real gearing,
58 const Calendar& paymentCalendar,
59 BusinessDayConvention paymentConvention,
60 Natural paymentDelay) {
61 return LegType(schedule, interestRateIndex)
62 .withNotionals(nominal)
63 .withPaymentDayCounter(dayCounter)
64 .withSpreads(margin)
65 .withGearings(gearing)
66 .withPaymentCalendar(paymentCalendar)
67 .withPaymentAdjustment(paymentConvention)
68 .withPaymentLag(paymentDelay);
69 }
70 }
71
72 EquityTotalReturnSwap::EquityTotalReturnSwap(
73 ext::shared_ptr<EquityIndex> equityIndex,
74 ext::shared_ptr<InterestRateIndex> interestRateIndex,
75 Type type,
76 Real nominal,
77 Schedule schedule,
78 DayCounter dayCounter,
79 Rate margin,
80 Real gearing,
81 Calendar paymentCalendar,
82 BusinessDayConvention paymentConvention,
83 Natural paymentDelay)
84 : Swap(2), equityIndex_(std::move(equityIndex)),
85 interestRateIndex_(std::move(interestRateIndex)), type_(type), nominal_(nominal),
86 schedule_(std::move(schedule)), dayCounter_(std::move(dayCounter)), margin_(margin),
87 gearing_(gearing), paymentCalendar_(std::move(paymentCalendar)),
88 paymentConvention_(paymentConvention), paymentDelay_(paymentDelay) {
89
90 QL_REQUIRE(!(nominal_ < 0.0), "Nominal cannot be negative");
91
92 legs_[0].push_back(x: createEquityCashFlow(schedule: schedule_, equityIndex: equityIndex_, nominal: nominal_, paymentCalendar: paymentCalendar_,
93 paymentConvention: paymentConvention_, paymentDelay: paymentDelay_));
94 for (Leg::const_iterator i = legs_[0].begin(); i < legs_[0].end(); ++i)
95 registerWith(h: *i);
96
97 switch (type_) {
98 case Payer:
99 payer_[0] = -1.0;
100 payer_[1] = +1.0;
101 break;
102 case Receiver:
103 payer_[0] = +1.0;
104 payer_[1] = -1.0;
105 break;
106 default:
107 QL_FAIL("unknown equity total return swap type");
108 }
109 }
110
111 EquityTotalReturnSwap::EquityTotalReturnSwap(Type type,
112 Real nominal,
113 Schedule schedule,
114 ext::shared_ptr<EquityIndex> equityIndex,
115 const ext::shared_ptr<IborIndex>& interestRateIndex,
116 DayCounter dayCounter,
117 Rate margin,
118 Real gearing,
119 Calendar paymentCalendar,
120 BusinessDayConvention paymentConvention,
121 Natural paymentDelay)
122 : EquityTotalReturnSwap(std::move(equityIndex),
123 interestRateIndex,
124 type,
125 nominal,
126 std::move(schedule),
127 std::move(dayCounter),
128 margin,
129 gearing,
130 std::move(paymentCalendar),
131 paymentConvention,
132 paymentDelay) {
133 legs_[1] = createInterestLeg<IborIndex, IborLeg>(
134 schedule: schedule_, interestRateIndex, nominal: nominal_, dayCounter: dayCounter_, margin: margin_, gearing: gearing_,
135 paymentCalendar: paymentCalendar_, paymentConvention: paymentConvention_, paymentDelay: paymentDelay_);
136 for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i)
137 registerWith(h: *i);
138 }
139
140 EquityTotalReturnSwap::EquityTotalReturnSwap(Type type,
141 Real nominal,
142 Schedule schedule,
143 ext::shared_ptr<EquityIndex> equityIndex,
144 const ext::shared_ptr<OvernightIndex>& interestRateIndex,
145 DayCounter dayCounter,
146 Rate margin,
147 Real gearing,
148 Calendar paymentCalendar,
149 BusinessDayConvention paymentConvention,
150 Natural paymentDelay)
151 : EquityTotalReturnSwap(std::move(equityIndex),
152 interestRateIndex,
153 type,
154 nominal,
155 std::move(schedule),
156 std::move(dayCounter),
157 margin,
158 gearing,
159 std::move(paymentCalendar),
160 paymentConvention,
161 paymentDelay) {
162 legs_[1] = createInterestLeg<OvernightIndex, OvernightLeg>(
163 schedule: schedule_, interestRateIndex, nominal: nominal_, dayCounter: dayCounter_, margin: margin_, gearing: gearing_,
164 paymentCalendar: paymentCalendar_, paymentConvention: paymentConvention_, paymentDelay: paymentDelay_);
165 for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i)
166 registerWith(h: *i);
167 }
168
169 const Leg& EquityTotalReturnSwap::equityLeg() const {
170 return leg(j: 0);
171 }
172
173 const Leg& EquityTotalReturnSwap::interestRateLeg() const {
174 return leg(j: 1);
175 }
176
177 Real EquityTotalReturnSwap::equityLegNPV() const {
178 return legNPV(j: 0);
179 }
180
181 Real EquityTotalReturnSwap::interestRateLegNPV() const {
182 return legNPV(j: 1);
183 }
184
185 Real EquityTotalReturnSwap::fairMargin() const {
186 // Knowing that for the fair margin NPV = 0.0, where:
187 // NPV = NPV Equity Leg + [NPV Floating Leg + margin * BPS / 10000]
188 // hence,
189 // fair margin = - [NPV Equity Leg + NPV Floating Leg] / BPS * 10000
190 const Spread basisPoint = 1.0e-4;
191 Real interestLegBps = legBPS(j: 1) / basisPoint;
192 Real exMarginInterestLegNpv = interestRateLegNPV() - margin() * interestLegBps;
193 return -(equityLegNPV() + exMarginInterestLegNpv) / interestLegBps;
194 }
195}

source code of quantlib/ql/instruments/equitytotalreturnswap.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.