Coverage Report

Created: 2025-11-04 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/barrieroption/mcdoublebarrierengine.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2020 Lew Wei Hao
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/experimental/barrieroption/mcdoublebarrierengine.hpp>
21
#include <utility>
22
23
namespace QuantLib {
24
25
    DoubleBarrierPathPricer::DoubleBarrierPathPricer(DoubleBarrier::Type barrierType,
26
                                                     Real barrierLow,
27
                                                     Real barrierHigh,
28
                                                     Real rebate,
29
                                                     Option::Type type,
30
                                                     Real strike,
31
                                                     std::vector<DiscountFactor> discounts)
32
0
    : barrierType_(barrierType), barrierLow_(barrierLow), barrierHigh_(barrierHigh),
33
0
      rebate_(rebate), payoff_(type, strike), discounts_(std::move(discounts)) {
34
0
        QL_REQUIRE(strike>=0.0,
35
0
                   "strike less than zero not allowed");
36
0
        QL_REQUIRE(barrierLow>0.0,
37
0
                   "low barrier less/equal zero not allowed");
38
0
        QL_REQUIRE(barrierHigh>0.0,
39
0
                   "high barrier less/equal zero not allowed");
40
0
    }
41
42
0
    Real DoubleBarrierPathPricer::operator()(const Path& path) const {
43
0
        static Size null = Null<Size>();
44
0
        Size n = path.length();
45
0
        QL_REQUIRE(n>1, "the path cannot be empty");
46
47
0
        bool isOptionActive = false;
48
0
        Size knockNode = null;
49
0
        Real terminal_price = path.back();
50
0
        Real new_asset_price;
51
0
        Size i;
52
53
0
        switch (barrierType_) {
54
0
            case DoubleBarrier::KnockOut:
55
0
                isOptionActive = true;
56
0
                for (i = 0; i < n-1; i++) {
57
0
                    new_asset_price = path[i + 1];
58
59
0
                    if (new_asset_price >= barrierHigh_ || new_asset_price <= barrierLow_){
60
0
                        isOptionActive = false;
61
0
                        if (knockNode == null)
62
0
                            knockNode = i+1;
63
0
                        break;
64
0
                    }
65
0
                }
66
0
                break;
67
0
            case DoubleBarrier::KnockIn:
68
0
                isOptionActive = false;
69
0
                for (i = 0; i < n-1; i++) {
70
0
                    new_asset_price = path[i + 1];
71
72
0
                    if (new_asset_price >= barrierHigh_ || new_asset_price <= barrierLow_){
73
0
                        isOptionActive = true;
74
0
                        if (knockNode == null)
75
0
                            knockNode = i+1;
76
0
                        break;
77
0
                    }
78
0
                }
79
0
                break;
80
0
            default:
81
0
                QL_FAIL("unknown barrier type");
82
0
        }
83
84
0
        if (isOptionActive) {
85
0
            return payoff_(terminal_price) * discounts_.back();
86
0
        } else {
87
0
            switch (barrierType_) {
88
0
                case DoubleBarrier::KnockOut:
89
0
                    return rebate_*discounts_[knockNode];
90
0
                case DoubleBarrier::KnockIn:
91
0
                    return rebate_*discounts_.back();
92
0
                default:
93
                    QL_FAIL("unknown barrier type");
94
0
            }
95
0
        }
96
0
    }
97
98
}