Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/cashflows/equitycashflow.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) 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/indexedcashflow.hpp>
22
#include <ql/indexes/equityindex.hpp>
23
#include <ql/termstructures/yield/quantotermstructure.hpp>
24
#include <ql/termstructures/yield/flatforward.hpp>
25
#include <ql/time/calendars/nullcalendar.hpp>
26
#include <ql/quotes/simplequote.hpp>
27
#include <ql/time/daycounters/actual365fixed.hpp>
28
29
namespace QuantLib {
30
31
    namespace {
32
        Handle<YieldTermStructure>
33
0
            configureDividendHandle(const Handle<YieldTermStructure>& dividendHandle) {
34
0
            if (dividendHandle.empty()) {
35
0
                ext::shared_ptr<YieldTermStructure> flatTs(ext::make_shared<FlatForward>(
36
0
                    0, NullCalendar(), Handle<Quote>(ext::make_shared<SimpleQuote>(0.0)),
37
0
                    Actual365Fixed()));
38
0
                return Handle<YieldTermStructure>(flatTs);
39
0
            }
40
0
            return dividendHandle;
41
0
        }
42
    }
43
44
0
    void setCouponPricer(const Leg& leg, const ext::shared_ptr<EquityCashFlowPricer>& p) {
45
0
        for (const auto& i : leg) {
46
0
            ext::shared_ptr<EquityCashFlow> c =
47
0
                ext::dynamic_pointer_cast<EquityCashFlow>(i);
48
0
            if (c != nullptr)
49
0
                c->setPricer(p);
50
0
        }
51
0
    }
52
53
    EquityCashFlow::EquityCashFlow(Real notional,
54
                                   ext::shared_ptr<EquityIndex> index,
55
                                   const Date& baseDate,
56
                                   const Date& fixingDate,
57
                                   const Date& paymentDate,
58
                                   bool growthOnly)
59
0
    : IndexedCashFlow(notional, std::move(index), baseDate, fixingDate, paymentDate, growthOnly) {}
Unexecuted instantiation: QuantLib::EquityCashFlow::EquityCashFlow(double, boost::shared_ptr<QuantLib::EquityIndex>, QuantLib::Date const&, QuantLib::Date const&, QuantLib::Date const&, bool)
Unexecuted instantiation: QuantLib::EquityCashFlow::EquityCashFlow(double, boost::shared_ptr<QuantLib::EquityIndex>, QuantLib::Date const&, QuantLib::Date const&, QuantLib::Date const&, bool)
60
61
0
    void EquityCashFlow::setPricer(const ext::shared_ptr<EquityCashFlowPricer>& pricer) {
62
0
        if (pricer_ != nullptr)
63
0
            unregisterWith(pricer_);
64
0
        pricer_ = pricer;
65
0
        if (pricer_ != nullptr)
66
0
            registerWith(pricer_);
67
0
        update();
68
0
    }
69
70
0
    Real EquityCashFlow::amount() const {
71
0
        if (!pricer_)
72
0
            return IndexedCashFlow::amount();
73
0
        pricer_->initialize(*this);
74
0
        return notional() * pricer_->price();
75
0
    }
76
77
  EquityQuantoCashFlowPricer::EquityQuantoCashFlowPricer(
78
        Handle<YieldTermStructure> quantoCurrencyTermStructure,
79
        Handle<BlackVolTermStructure> equityVolatility,
80
        Handle<BlackVolTermStructure> fxVolatility,
81
        Handle<Quote> correlation)
82
0
    : quantoCurrencyTermStructure_(std::move(quantoCurrencyTermStructure)),
83
0
      equityVolatility_(std::move(equityVolatility)), fxVolatility_(std::move(fxVolatility)),
84
0
      correlation_(std::move(correlation)){
85
0
        registerWith(quantoCurrencyTermStructure_);
86
0
        registerWith(equityVolatility_);
87
0
        registerWith(fxVolatility_);
88
0
        registerWith(correlation_);
89
0
    }
Unexecuted instantiation: QuantLib::EquityQuantoCashFlowPricer::EquityQuantoCashFlowPricer(QuantLib::Handle<QuantLib::YieldTermStructure>, QuantLib::Handle<QuantLib::BlackVolTermStructure>, QuantLib::Handle<QuantLib::BlackVolTermStructure>, QuantLib::Handle<QuantLib::Quote>)
Unexecuted instantiation: QuantLib::EquityQuantoCashFlowPricer::EquityQuantoCashFlowPricer(QuantLib::Handle<QuantLib::YieldTermStructure>, QuantLib::Handle<QuantLib::BlackVolTermStructure>, QuantLib::Handle<QuantLib::BlackVolTermStructure>, QuantLib::Handle<QuantLib::Quote>)
90
91
0
    void EquityQuantoCashFlowPricer::initialize(const EquityCashFlow& cashFlow) {
92
0
        index_ = ext::dynamic_pointer_cast<EquityIndex>(cashFlow.index());
93
0
        if (!index_) {
94
0
            QL_FAIL("Equity index required.");
95
0
        }
96
0
        baseDate_ = cashFlow.baseDate();
97
0
        fixingDate_ = cashFlow.fixingDate();
98
0
        QL_REQUIRE(fixingDate_ >= baseDate_, "Fixing date cannot fall before base date.");
99
0
        growthOnlyPayoff_ = cashFlow.growthOnly();
100
        
101
0
        QL_REQUIRE(!quantoCurrencyTermStructure_.empty(),
102
0
                   "Quanto currency term structure handle cannot be empty.");
103
0
        QL_REQUIRE(!equityVolatility_.empty(),
104
0
                   "Equity volatility term structure handle cannot be empty.");
105
0
        QL_REQUIRE(!fxVolatility_.empty(),
106
0
                   "FX volatility term structure handle cannot be empty.");
107
0
        QL_REQUIRE(!correlation_.empty(), "Correlation handle cannot be empty.");
108
109
0
        QL_REQUIRE(quantoCurrencyTermStructure_->referenceDate() ==
110
0
                           equityVolatility_->referenceDate() &&
111
0
                       equityVolatility_->referenceDate() == fxVolatility_->referenceDate(),
112
0
                   "Quanto currency term structure, equity and FX volatility need to have the same "
113
0
                   "reference date.");
114
0
    }
115
116
0
    Real EquityQuantoCashFlowPricer::price() const {
117
0
        Real strike = index_->fixing(fixingDate_);
118
0
        Handle<YieldTermStructure> dividendHandle =
119
0
            configureDividendHandle(index_->equityDividendCurve());
120
121
0
        Handle<YieldTermStructure> quantoTermStructure(ext::make_shared<QuantoTermStructure>(
122
0
            dividendHandle, quantoCurrencyTermStructure_,
123
0
            index_->equityInterestRateCurve(), equityVolatility_, strike, fxVolatility_, 1.0,
124
0
            correlation_->value()));
125
0
        ext::shared_ptr<EquityIndex> quantoIndex =
126
0
            index_->clone(quantoCurrencyTermStructure_, quantoTermStructure, index_->spot());
127
128
0
        Real I0 = quantoIndex->fixing(baseDate_);
129
0
        Real I1 = quantoIndex->fixing(fixingDate_);
130
131
0
        if (growthOnlyPayoff_)
132
0
            return I1 / I0 - 1.0;
133
0
        return I1 / I0;
134
0
    }
135
}