| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /* |
| 4 | Copyright (C) 2014 Thema Consulting SA |
| 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 "binaryoption.hpp" |
| 21 | #include "utilities.hpp" |
| 22 | #include <ql/time/calendars/nullcalendar.hpp> |
| 23 | #include <ql/time/calendars/target.hpp> |
| 24 | #include <ql/time/daycounters/actual360.hpp> |
| 25 | #include <ql/math/interpolations/bicubicsplineinterpolation.hpp> |
| 26 | #include <ql/instruments/barrieroption.hpp> |
| 27 | #include <ql/models/equity/hestonmodel.hpp> |
| 28 | #include <ql/pricingengines/barrier/analyticbinarybarrierengine.hpp> |
| 29 | #include <ql/termstructures/yield/zerocurve.hpp> |
| 30 | #include <ql/termstructures/yield/flatforward.hpp> |
| 31 | #include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp> |
| 32 | #include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp> |
| 33 | #include <ql/termstructures/volatility/equityfx/blackvariancesurface.hpp> |
| 34 | #include <ql/utilities/dataformatters.hpp> |
| 35 | |
| 36 | using namespace QuantLib; |
| 37 | using namespace boost::unit_test_framework; |
| 38 | |
| 39 | #undef REPORT_FAILURE |
| 40 | #define REPORT_FAILURE(greekName, payoff, exercise, barrierType, barrier, s, q,\ |
| 41 | r, today, v, expected, calculated, error, tolerance) \ |
| 42 | BOOST_FAIL(payoff->optionType() << " option with " \ |
| 43 | << barrierTypeToString(barrierType) << " barrier type:\n" \ |
| 44 | << " barrier: " << barrier << "\n" \ |
| 45 | << payoffTypeToString(payoff) << " payoff:\n" \ |
| 46 | << " spot value: " << s << "\n" \ |
| 47 | << " strike: " << payoff->strike() << "\n" \ |
| 48 | << " dividend yield: " << io::rate(q) << "\n" \ |
| 49 | << " risk-free rate: " << io::rate(r) << "\n" \ |
| 50 | << " reference date: " << today << "\n" \ |
| 51 | << " maturity: " << exercise->lastDate() << "\n" \ |
| 52 | << " volatility: " << io::volatility(v) << "\n\n" \ |
| 53 | << " expected " << greekName << ": " << expected << "\n" \ |
| 54 | << " calculated " << greekName << ": " << calculated << "\n"\ |
| 55 | << " error: " << error << "\n" \ |
| 56 | << " tolerance: " << tolerance << "\n"); |
| 57 | |
| 58 | namespace binary_option_test { |
| 59 | |
| 60 | std::string barrierTypeToString(Barrier::Type type) { |
| 61 | switch(type){ |
| 62 | case Barrier::DownIn: |
| 63 | return std::string("Down-and-in" ); |
| 64 | case Barrier::UpIn: |
| 65 | return std::string("Up-and-in" ); |
| 66 | case Barrier::DownOut: |
| 67 | return std::string("Down-and-out" ); |
| 68 | case Barrier::UpOut: |
| 69 | return std::string("Up-and-out" ); |
| 70 | default: |
| 71 | QL_FAIL("unknown exercise type" ); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | struct BinaryOptionData { |
| 76 | Barrier::Type barrierType; |
| 77 | Real barrier; |
| 78 | Real cash; // cash payoff for cash-or-nothing |
| 79 | Option::Type type; |
| 80 | Real strike; |
| 81 | Real s; // spot |
| 82 | Rate q; // dividend |
| 83 | Rate r; // risk-free rate |
| 84 | Time t; // time to maturity |
| 85 | Volatility v; // volatility |
| 86 | Real result; // expected result |
| 87 | Real tol; // tolerance |
| 88 | }; |
| 89 | } |
| 90 | |
| 91 | |
| 92 | void BinaryOptionTest::testCashOrNothingHaugValues() { |
| 93 | |
| 94 | BOOST_TEST_MESSAGE("Testing cash-or-nothing barrier options against Haug's values..." ); |
| 95 | |
| 96 | using namespace binary_option_test; |
| 97 | |
| 98 | BinaryOptionData values[] = { |
| 99 | /* The data below are from |
| 100 | "Option pricing formulas 2nd Ed.", E.G. Haug, McGraw-Hill 2007 pag. 180 - cases 13,14,17,18,21,22,25,26 |
| 101 | Note: |
| 102 | q is the dividend rate, while the book gives b, the cost of carry (q=r-b) |
| 103 | */ |
| 104 | // barrierType, barrier, cash, type, strike, spot, q, r, t, vol, value, tol |
| 105 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 4.9289, .tol: 1e-4 }, |
| 106 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 6.2150, .tol: 1e-4 }, |
| 107 | // following value is wrong in book. |
| 108 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 5.8926, .tol: 1e-4 }, |
| 109 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 7.4519, .tol: 1e-4 }, |
| 110 | // 17,18 |
| 111 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 4.4314, .tol: 1e-4 }, |
| 112 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 3.1454, .tol: 1e-4 }, |
| 113 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 5.3297, .tol: 1e-4 }, |
| 114 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 3.7704, .tol: 1e-4 }, |
| 115 | // 21,22 |
| 116 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 4.8758, .tol: 1e-4 }, |
| 117 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 4.9081, .tol: 1e-4 }, |
| 118 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 119 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0407, .tol: 1e-4 }, |
| 120 | // 25,26 |
| 121 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0323, .tol: 1e-4 }, |
| 122 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 123 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 3.0461, .tol: 1e-4 }, |
| 124 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 3.0054, .tol: 1e-4 }, |
| 125 | |
| 126 | // other values calculated with book vba |
| 127 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 95.00,.q: -0.14, .r: 0.10, .t: 0.5, .v: 0.20, .result: 8.6806, .tol: 1e-4 }, |
| 128 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 102.00, .s: 95.00, .q: 0.03, .r: 0.10, .t: 0.5, .v: 0.20, .result: 5.3112, .tol: 1e-4 }, |
| 129 | // degenerate conditions (barrier touched) |
| 130 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 7.4926, .tol: 1e-4 }, |
| 131 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 11.1231, .tol: 1e-4 }, |
| 132 | // 17,18 |
| 133 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 98.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 7.1344, .tol: 1e-4 }, |
| 134 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 102.00, .s: 101.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 5.9299, .tol: 1e-4 }, |
| 135 | // 21,22 |
| 136 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 99.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 137 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Call, .strike: 98.00, .s: 101.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 138 | // 25,26 |
| 139 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 99.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 140 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 15.00, .type: Option::Put, .strike: 98.00, .s: 101.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 141 | }; |
| 142 | |
| 143 | DayCounter dc = Actual360(); |
| 144 | Date today = Date::todaysDate(); |
| 145 | |
| 146 | ext::shared_ptr<SimpleQuote> spot(new SimpleQuote(100.0)); |
| 147 | ext::shared_ptr<SimpleQuote> qRate(new SimpleQuote(0.04)); |
| 148 | ext::shared_ptr<YieldTermStructure> qTS = flatRate(today, forward: qRate, dc); |
| 149 | ext::shared_ptr<SimpleQuote> rRate(new SimpleQuote(0.01)); |
| 150 | ext::shared_ptr<YieldTermStructure> rTS = flatRate(today, forward: rRate, dc); |
| 151 | ext::shared_ptr<SimpleQuote> vol(new SimpleQuote(0.25)); |
| 152 | ext::shared_ptr<BlackVolTermStructure> volTS = flatVol(today, volatility: vol, dc); |
| 153 | |
| 154 | for (auto& value : values) { |
| 155 | |
| 156 | ext::shared_ptr<StrikedTypePayoff> payoff( |
| 157 | new CashOrNothingPayoff(value.type, value.strike, value.cash)); |
| 158 | |
| 159 | Date exDate = today + timeToDays(t: value.t); |
| 160 | ext::shared_ptr<Exercise> amExercise(new AmericanExercise(today, |
| 161 | exDate, |
| 162 | true)); |
| 163 | |
| 164 | spot->setValue(value.s); |
| 165 | qRate->setValue(value.q); |
| 166 | rRate->setValue(value.r); |
| 167 | vol->setValue(value.v); |
| 168 | |
| 169 | ext::shared_ptr<BlackScholesMertonProcess> stochProcess(new |
| 170 | BlackScholesMertonProcess(Handle<Quote>(spot), |
| 171 | Handle<YieldTermStructure>(qTS), |
| 172 | Handle<YieldTermStructure>(rTS), |
| 173 | Handle<BlackVolTermStructure>(volTS))); |
| 174 | ext::shared_ptr<PricingEngine> engine( |
| 175 | new AnalyticBinaryBarrierEngine(stochProcess)); |
| 176 | |
| 177 | BarrierOption opt(value.barrierType, value.barrier, 0, payoff, amExercise); |
| 178 | |
| 179 | opt.setPricingEngine(engine); |
| 180 | |
| 181 | Real calculated = opt.NPV(); |
| 182 | Real error = std::fabs(x: calculated - value.result); |
| 183 | if (error > value.tol) { |
| 184 | REPORT_FAILURE("value" , payoff, amExercise, value.barrierType, value.barrier, value.s, |
| 185 | value.q, value.r, today, value.v, value.result, calculated, error, |
| 186 | value.tol); |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | void BinaryOptionTest::testAssetOrNothingHaugValues() { |
| 192 | |
| 193 | BOOST_TEST_MESSAGE("Testing asset-or-nothing barrier options against Haug's values..." ); |
| 194 | |
| 195 | using namespace binary_option_test; |
| 196 | |
| 197 | BinaryOptionData values[] = { |
| 198 | /* The data below are from |
| 199 | "Option pricing formulas 2nd Ed.", E.G. Haug, McGraw-Hill 2007 pag. 180 - cases 15,16,19,20,23,24,27,28 |
| 200 | Note: |
| 201 | q is the dividend rate, while the book gives b, the cost of carry (q=r-b) |
| 202 | */ |
| 203 | // barrierType, barrier, cash, type, strike, spot, q, r, t, vol, value, tol |
| 204 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 37.2782, .tol: 1e-4 }, |
| 205 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 45.8530, .tol: 1e-4 }, |
| 206 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 44.5294, .tol: 1e-4 }, |
| 207 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 54.9262, .tol: 1e-4 }, |
| 208 | // 19,20 |
| 209 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 27.5644, .tol: 1e-4 }, |
| 210 | { .barrierType: Barrier::DownIn, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 18.9896, .tol: 1e-4 }, |
| 211 | // following value is wrong in book. |
| 212 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 33.1723, .tol: 1e-4 }, |
| 213 | { .barrierType: Barrier::UpIn, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 22.7755, .tol: 1e-4 }, |
| 214 | // 23,24 |
| 215 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 39.9391, .tol: 1e-4 }, |
| 216 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 40.1574, .tol: 1e-4 }, |
| 217 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 218 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 0.00, .type: Option::Call, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.2676, .tol: 1e-4 }, |
| 219 | // 27,28 |
| 220 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 102.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.2183, .tol: 1e-4 }, |
| 221 | { .barrierType: Barrier::DownOut, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 98.00, .s: 105.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 0.0000, .tol: 1e-4 }, |
| 222 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 102.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 17.2983, .tol: 1e-4 }, |
| 223 | { .barrierType: Barrier::UpOut, .barrier: 100.00, .cash: 0.00, .type: Option::Put, .strike: 98.00, .s: 95.00, .q: 0.00, .r: 0.10, .t: 0.5, .v: 0.20, .result: 17.0306, .tol: 1e-4 }, |
| 224 | }; |
| 225 | |
| 226 | DayCounter dc = Actual360(); |
| 227 | Date today = Date::todaysDate(); |
| 228 | |
| 229 | ext::shared_ptr<SimpleQuote> spot(new SimpleQuote(100.0)); |
| 230 | ext::shared_ptr<SimpleQuote> qRate(new SimpleQuote(0.04)); |
| 231 | ext::shared_ptr<YieldTermStructure> qTS = flatRate(today, forward: qRate, dc); |
| 232 | ext::shared_ptr<SimpleQuote> rRate(new SimpleQuote(0.01)); |
| 233 | ext::shared_ptr<YieldTermStructure> rTS = flatRate(today, forward: rRate, dc); |
| 234 | ext::shared_ptr<SimpleQuote> vol(new SimpleQuote(0.25)); |
| 235 | ext::shared_ptr<BlackVolTermStructure> volTS = flatVol(today, volatility: vol, dc); |
| 236 | |
| 237 | for (auto& value : values) { |
| 238 | |
| 239 | ext::shared_ptr<StrikedTypePayoff> payoff( |
| 240 | new AssetOrNothingPayoff(value.type, value.strike)); |
| 241 | |
| 242 | Date exDate = today + timeToDays(t: value.t); |
| 243 | ext::shared_ptr<Exercise> amExercise(new AmericanExercise(today, exDate, true)); |
| 244 | |
| 245 | spot->setValue(value.s); |
| 246 | qRate->setValue(value.q); |
| 247 | rRate->setValue(value.r); |
| 248 | vol->setValue(value.v); |
| 249 | |
| 250 | ext::shared_ptr<BlackScholesMertonProcess> stochProcess(new |
| 251 | BlackScholesMertonProcess(Handle<Quote>(spot), |
| 252 | Handle<YieldTermStructure>(qTS), |
| 253 | Handle<YieldTermStructure>(rTS), |
| 254 | Handle<BlackVolTermStructure>(volTS))); |
| 255 | ext::shared_ptr<PricingEngine> engine( |
| 256 | new AnalyticBinaryBarrierEngine(stochProcess)); |
| 257 | |
| 258 | BarrierOption opt(value.barrierType, value.barrier, 0, payoff, amExercise); |
| 259 | |
| 260 | opt.setPricingEngine(engine); |
| 261 | |
| 262 | Real calculated = opt.NPV(); |
| 263 | Real error = std::fabs(x: calculated - value.result); |
| 264 | if (error > value.tol) { |
| 265 | REPORT_FAILURE("value" , payoff, amExercise, value.barrierType, value.barrier, value.s, |
| 266 | value.q, value.r, today, value.v, value.result, calculated, error, |
| 267 | value.tol); |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | test_suite* BinaryOptionTest::suite() { |
| 273 | auto* suite = BOOST_TEST_SUITE("Binary" ); |
| 274 | suite->add(QUANTLIB_TEST_CASE(&BinaryOptionTest::testCashOrNothingHaugValues)); |
| 275 | suite->add(QUANTLIB_TEST_CASE(&BinaryOptionTest::testAssetOrNothingHaugValues)); |
| 276 | return suite; |
| 277 | } |
| 278 | |