Coverage Report

Created: 2026-03-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/indexes/equityindex.cpp
Line
Count
Source
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
 <https://www.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/indexes/equityindex.hpp>
21
#include <ql/settings.hpp>
22
#include <utility>
23
24
namespace QuantLib {
25
26
    namespace {
27
0
        Real resolveSpot(const Handle<Quote>& spot, Real lastFixing) {
28
0
            QL_REQUIRE(!spot.empty() || lastFixing != Null<Real>(),
29
0
                       "Cannot forecast equity index, missing both spot and historical index");
30
0
            return spot.empty() ? lastFixing : spot->value();
31
0
        }
32
    }
33
34
    EquityIndex::EquityIndex(std::string name,
35
                             Calendar fixingCalendar,
36
                             Currency currency,
37
                             Handle<YieldTermStructure> interest,
38
                             Handle<YieldTermStructure> dividend,
39
                             Handle<Quote> spot)
40
0
    : name_(std::move(name)), fixingCalendar_(std::move(fixingCalendar)),
41
0
      currency_(std::move(currency)), interest_(std::move(interest)),
42
0
      dividend_(std::move(dividend)), spot_(std::move(spot)) {
43
44
0
        registerWith(interest_);
45
0
        registerWith(dividend_);
46
0
        registerWith(spot_);
47
0
        registerWith(Settings::instance().evaluationDate());
48
0
        registerWith(notifier());
49
0
    }
50
51
0
    Real EquityIndex::fixing(const Date& fixingDate, bool forecastTodaysFixing) const {
52
53
0
        QL_REQUIRE(isValidFixingDate(fixingDate), "Fixing date " << fixingDate << " is not valid");
54
55
0
        Date today = Settings::instance().evaluationDate();
56
57
0
        if (fixingDate > today || (fixingDate == today && forecastTodaysFixing))
58
0
            return forecastFixing(fixingDate);
59
60
0
        Real result = pastFixing(fixingDate);
61
62
0
        if (result != Null<Real>())
63
            // if historical fixing is present use it
64
0
            return result;
65
        
66
0
        if (fixingDate == today && !spot_.empty())
67
            // Today's fixing is missing, but spot is
68
            // provided, so use it as proxy
69
0
            return spot_->value();
70
        
71
0
        QL_FAIL("Missing " << name() << " fixing for " << fixingDate);
72
0
    }
73
74
0
    Real EquityIndex::forecastFixing(const Date& fixingDate) const {
75
0
        QL_REQUIRE(!interest_.empty(),
76
0
                   "null interest rate term structure set to this instance of " << name());
77
78
0
        Date today = Settings::instance().evaluationDate();
79
0
        Date lastFixingDate = fixingCalendar_.adjust(today, BusinessDayConvention::Preceding);
80
81
0
        Real spot = resolveSpot(spot_, pastFixing(lastFixingDate));
82
83
0
        Real forward;
84
0
        if (!dividend_.empty()) {
85
0
            forward = spot * dividend_->discount(fixingDate) / interest_->discount(fixingDate);
86
0
        } else {
87
0
            forward = spot / interest_->discount(fixingDate);
88
0
        }
89
0
        return forward;
90
0
    }
91
92
    ext::shared_ptr<EquityIndex> EquityIndex::clone(const Handle<YieldTermStructure>& interest,
93
                                                    const Handle<YieldTermStructure>& dividend,
94
0
                                                    const Handle<Quote>& spot) const {
95
0
        return ext::make_shared<EquityIndex>(name(), fixingCalendar(), currency(), interest,
96
0
                                             dividend, spot);
97
0
    }
98
}