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

lballabio / QuantLib / 21247173144

22 Jan 2026 11:44AM UTC coverage: 74.184% (+0.01%) from 74.172%
21247173144

Pull #2414

github

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

102 of 111 new or added lines in 3 files covered. (91.89%)

345 existing lines in 25 files now uncovered.

57443 of 77433 relevant lines covered (74.18%)

8775180.22 hits per line

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

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

3
/*
4
 Copyright (C) 2024 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 nominal1,
10✔
26
                         const Currency& currency1,
27
                         Real nominal2,
28
                         const Currency& currency2,
29
                         const Date& maturityDate,
30
                         bool payCurrency1)
10✔
31
    : nominal1_(nominal1), currency1_(currency1), nominal2_(nominal2), currency2_(currency2),
10✔
32
      maturityDate_(maturityDate), payCurrency1_(payCurrency1), fairForwardRate_(Null<Real>()),
10✔
33
      npvCurrency1_(Null<Real>()), npvCurrency2_(Null<Real>()) {
20✔
34
        QL_REQUIRE(!currency1.empty(), "currency1 must not be empty");
10✔
35
        QL_REQUIRE(!currency2.empty(), "currency2 must not be empty");
10✔
36
        QL_REQUIRE(currency1 != currency2, "currency1 and currency2 must be different");
10✔
37
        QL_REQUIRE(nominal1 > 0.0, "nominal1 must be positive");
10✔
38
        QL_REQUIRE(nominal2 > 0.0, "nominal2 must be positive");
10✔
39
    }
10✔
40

41
    FxForward::FxForward(Real nominal,
1✔
42
                         const Currency& sourceCurrency,
43
                         const Currency& targetCurrency,
44
                         Real forwardRate,
45
                         const Date& maturityDate,
46
                         bool sellingSource)
1✔
47
    : nominal1_(nominal), currency1_(sourceCurrency), nominal2_(nominal * forwardRate),
1✔
48
      currency2_(targetCurrency), maturityDate_(maturityDate), payCurrency1_(sellingSource),
1✔
49
      fairForwardRate_(Null<Real>()), npvCurrency1_(Null<Real>()), npvCurrency2_(Null<Real>()) {
2✔
50
        QL_REQUIRE(!sourceCurrency.empty(), "source currency must not be empty");
1✔
51
        QL_REQUIRE(!targetCurrency.empty(), "target currency must not be empty");
1✔
52
        QL_REQUIRE(sourceCurrency != targetCurrency,
1✔
53
                   "source and target currencies must be different");
54
        QL_REQUIRE(nominal > 0.0, "nominal must be positive");
1✔
55
        QL_REQUIRE(forwardRate > 0.0, "forward rate must be positive");
1✔
56
    }
1✔
57

58
    bool FxForward::isExpired() const {
14✔
59
        return maturityDate_ < Settings::instance().evaluationDate();
14✔
60
    }
61

62
    void FxForward::setupArguments(PricingEngine::arguments* args) const {
12✔
63
        auto* arguments = dynamic_cast<FxForward::arguments*>(args);
12✔
64
        QL_REQUIRE(arguments != nullptr, "wrong argument type");
12✔
65

66
        arguments->nominal1 = nominal1_;
12✔
67
        arguments->currency1 = currency1_;
68
        arguments->nominal2 = nominal2_;
12✔
69
        arguments->currency2 = currency2_;
70
        arguments->maturityDate = maturityDate_;
12✔
71
        arguments->payCurrency1 = payCurrency1_;
12✔
72
    }
12✔
73

74
    void FxForward::fetchResults(const PricingEngine::results* r) const {
12✔
75
        Instrument::fetchResults(r);
12✔
76

77
        const auto* results = dynamic_cast<const FxForward::results*>(r);
12✔
78
        QL_REQUIRE(results != nullptr, "wrong result type");
12✔
79

80
        fairForwardRate_ = results->fairForwardRate;
12✔
81
        npvCurrency1_ = results->npvCurrency1;
12✔
82
        npvCurrency2_ = results->npvCurrency2;
12✔
83
    }
12✔
84

85
    Real FxForward::fairForwardRate() const {
2✔
86
        calculate();
2✔
87
        QL_REQUIRE(fairForwardRate_ != Null<Real>(), "fair forward rate not available");
2✔
88
        return fairForwardRate_;
2✔
89
    }
90

NEW
91
    Real FxForward::npvCurrency1() const {
×
NEW
92
        calculate();
×
NEW
93
        QL_REQUIRE(npvCurrency1_ != Null<Real>(), "NPV in currency1 not available");
×
NEW
94
        return npvCurrency1_;
×
95
    }
96

NEW
97
    Real FxForward::npvCurrency2() const {
×
NEW
98
        calculate();
×
NEW
99
        QL_REQUIRE(npvCurrency2_ != Null<Real>(), "NPV in currency2 not available");
×
NEW
100
        return npvCurrency2_;
×
101
    }
102

103
    void FxForward::arguments::validate() const {
12✔
104
        QL_REQUIRE(nominal1 != Null<Real>(), "nominal1 not set");
12✔
105
        QL_REQUIRE(nominal2 != Null<Real>(), "nominal2 not set");
12✔
106
        QL_REQUIRE(!currency1.empty(), "currency1 not set");
12✔
107
        QL_REQUIRE(!currency2.empty(), "currency2 not set");
12✔
108
        QL_REQUIRE(maturityDate != Date(), "maturity date not set");
12✔
109
    }
12✔
110

111
    void FxForward::results::reset() {
12✔
112
        Instrument::results::reset();
12✔
113
        fairForwardRate = Null<Real>();
12✔
114
        npvCurrency1 = Null<Real>();
12✔
115
        npvCurrency2 = Null<Real>();
12✔
116
    }
12✔
117

118
}
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