• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lballabio / QuantLib / 21308179365

24 Jan 2026 03:09AM UTC coverage: 74.188% (+0.02%) from 74.172%
21308179365

Pull #2414

github

web-flow
Merge f5f442ce9 into 71e800be7
Pull Request #2414: Add FX Forward instrument, engine, and tests

106 of 115 new or added lines in 3 files covered. (92.17%)

345 existing lines in 25 files now uncovered.

57449 of 77437 relevant lines covered (74.19%)

8767392.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.24
/ql/instruments/fxforward.cpp
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2

3
/*
4
 Copyright (C) 2026 Chirag Desai
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/instruments/fxforward.hpp>
21
#include <ql/settings.hpp>
22

23
namespace QuantLib {
24

25
    FxForward::FxForward(Real sourceNominal,
11✔
26
                         const Currency& sourceCurrency,
27
                         Real targetNominal,
28
                         const Currency& targetCurrency,
29
                         const Date& maturityDate,
30
                         bool paySourceCurrency)
11✔
31
    : sourceNominal_(sourceNominal), sourceCurrency_(sourceCurrency), targetNominal_(targetNominal),
11✔
32
      targetCurrency_(targetCurrency), maturityDate_(maturityDate),
11✔
33
      paySourceCurrency_(paySourceCurrency), fairForwardRate_(Null<Real>()),
11✔
34
      npvSourceCurrency_(Null<Real>()), npvTargetCurrency_(Null<Real>()) {
22✔
35
        QL_REQUIRE(!sourceCurrency.empty(), "source currency must not be empty");
11✔
36
        QL_REQUIRE(!targetCurrency.empty(), "target currency must not be empty");
11✔
37
        QL_REQUIRE(sourceCurrency != targetCurrency,
11✔
38
                   "source and target currencies must be different");
39
        QL_REQUIRE(sourceNominal > 0.0, "source nominal must be positive");
11✔
40
        QL_REQUIRE(targetNominal > 0.0, "target nominal must be positive");
11✔
41
    }
11✔
42

43
    FxForward::FxForward(Real sourceNominal,
2✔
44
                         const Currency& sourceCurrency,
45
                         const Currency& targetCurrency,
46
                         Real forwardRate,
47
                         const Date& maturityDate,
48
                         bool sellingSource)
2✔
49
    : sourceNominal_(sourceNominal), sourceCurrency_(sourceCurrency),
2✔
50
      targetNominal_(sourceNominal * forwardRate), targetCurrency_(targetCurrency),
2✔
51
      maturityDate_(maturityDate), paySourceCurrency_(sellingSource),
2✔
52
      fairForwardRate_(Null<Real>()), npvSourceCurrency_(Null<Real>()),
2✔
53
      npvTargetCurrency_(Null<Real>()) {
4✔
54
        QL_REQUIRE(!sourceCurrency.empty(), "source currency must not be empty");
2✔
55
        QL_REQUIRE(!targetCurrency.empty(), "target currency must not be empty");
2✔
56
        QL_REQUIRE(sourceCurrency != targetCurrency,
2✔
57
                   "source and target currencies must be different");
58
        QL_REQUIRE(sourceNominal > 0.0, "source nominal must be positive");
2✔
59
        QL_REQUIRE(forwardRate > 0.0, "forward rate must be positive");
2✔
60
    }
2✔
61

62
    bool FxForward::isExpired() const {
15✔
63
        return maturityDate_ < Settings::instance().evaluationDate();
15✔
64
    }
65

66
    void FxForward::setupArguments(PricingEngine::arguments* args) const {
13✔
67
        auto* arguments = dynamic_cast<FxForward::arguments*>(args);
13✔
68
        QL_REQUIRE(arguments != nullptr, "wrong argument type");
13✔
69

70
        arguments->sourceNominal = sourceNominal_;
13✔
71
        arguments->sourceCurrency = sourceCurrency_;
72
        arguments->targetNominal = targetNominal_;
13✔
73
        arguments->targetCurrency = targetCurrency_;
74
        arguments->maturityDate = maturityDate_;
13✔
75
        arguments->paySourceCurrency = paySourceCurrency_;
13✔
76
    }
13✔
77

78
    void FxForward::fetchResults(const PricingEngine::results* r) const {
13✔
79
        Instrument::fetchResults(r);
13✔
80

81
        const auto* results = dynamic_cast<const FxForward::results*>(r);
13✔
82
        QL_REQUIRE(results != nullptr, "wrong result type");
13✔
83

84
        fairForwardRate_ = results->fairForwardRate;
13✔
85
        npvSourceCurrency_ = results->npvSourceCurrency;
13✔
86
        npvTargetCurrency_ = results->npvTargetCurrency;
13✔
87
    }
13✔
88

89
    Real FxForward::fairForwardRate() const {
3✔
90
        calculate();
3✔
91
        QL_REQUIRE(fairForwardRate_ != Null<Real>(), "fair forward rate not available");
3✔
92
        return fairForwardRate_;
3✔
93
    }
94

NEW
95
    Real FxForward::npvSourceCurrency() const {
×
NEW
96
        calculate();
×
NEW
97
        QL_REQUIRE(npvSourceCurrency_ != Null<Real>(), "NPV in source currency not available");
×
NEW
98
        return npvSourceCurrency_;
×
99
    }
100

NEW
101
    Real FxForward::npvTargetCurrency() const {
×
NEW
102
        calculate();
×
NEW
103
        QL_REQUIRE(npvTargetCurrency_ != Null<Real>(), "NPV in target currency not available");
×
NEW
104
        return npvTargetCurrency_;
×
105
    }
106

107
    void FxForward::arguments::validate() const {
13✔
108
        QL_REQUIRE(sourceNominal != Null<Real>(), "source nominal not set");
13✔
109
        QL_REQUIRE(targetNominal != Null<Real>(), "target nominal not set");
13✔
110
        QL_REQUIRE(!sourceCurrency.empty(), "source currency not set");
13✔
111
        QL_REQUIRE(!targetCurrency.empty(), "target currency not set");
13✔
112
        QL_REQUIRE(maturityDate != Date(), "maturity date not set");
13✔
113
    }
13✔
114

115
    void FxForward::results::reset() {
13✔
116
        Instrument::results::reset();
13✔
117
        fairForwardRate = Null<Real>();
13✔
118
        npvSourceCurrency = Null<Real>();
13✔
119
        npvTargetCurrency = Null<Real>();
13✔
120
    }
13✔
121

122
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc