Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cliquetoptionmcscriptengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
24#include <ql/exercise.hpp>
25#include <ql/instruments/payoffs.hpp>
26
27using namespace QuantLib;
28using namespace QuantExt;
29
30namespace ore {
31namespace data {
32
33CliquetOptionMcScriptEngine::CliquetOptionMcScriptEngine(const std::string& underlying, const std::string& baseCcy,
34 const std::string& underlyingCcy,
35 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& p,
36 const std::set<std::string>& tradeTypes, Size samples,
37 Size regressionOrder, bool interactive,
38 bool scriptedLibraryOverride)
39 : underlying_(underlying), baseCcy_(baseCcy), underlyingCcy_(underlyingCcy), p_(p), samples_(samples),
40 regressionOrder_(regressionOrder), interactive_(interactive) {
41
42 string scriptStr;
43
44 if (scriptedLibraryOverride) {
45 QL_REQUIRE(tradeTypes.size() == 1, "");
46 string scriptName = *tradeTypes.begin();
47
48 QL_REQUIRE(ScriptLibraryStorage::instance().get().has(scriptName, ""),
49 "script '" << scriptName << "' not found in library");
50 ScriptedTradeScriptData script = ScriptLibraryStorage::instance().get().get(scriptName, "").second;
51 scriptStr = script.code();
52 } else {
53 scriptStr = "NUMBER Payoff, d, premiumPayment;\n"
54 "Payoff = 0;\n"
55 "premiumPayment = 0;\n"
56 "IF PremiumPaymentDate >= TODAY THEN"
57 " premiumPayment = PAY(LongShort * Notional * Premium, PremiumPaymentDate, PremiumPaymentDate, "
58 "PremiumCurrency);"
59 "END;\n"
60 "FOR d IN (2, SIZE(ValuationDates), 1) DO"
61 " Payoff = Payoff + min( max( Type * ( (Underlying(ValuationDates[d]) / "
62 "Underlying(ValuationDates[d-1])) - Moneyness ), LocalFloor ), LocalCap );"
63 "END;\n"
64 "Option = premiumPayment + PAY( LongShort * Notional * min( max( Payoff, GlobalFloor ), GlobalCap "
65 "), Expiry, PayDate, PayCcy );\n";
66 }
67
68 ScriptParser parser(scriptStr);
69 QL_REQUIRE(parser.success(), "could not initialise AST for McScriptEuropeanEngine: " << parser.error());
70 ast_ = parser.ast();
71 registerWith(p_);
72}
73
75
76 // some checks (copied from QuantLib::AnalyticEuropeanEngine)
77
78 QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "not an European option");
79 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoff = QuantLib::ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
80 QL_REQUIRE(payoff, "non-striked payoff given");
81
82 // set up the script engine model
83
84 // cas use time steps = 0 for black scholes
85 auto builder = QuantLib::ext::make_shared<BlackScholesModelBuilder>(p_->riskFreeRate(), p_, arguments_.valuationDates,
86 std::set<Date>(), 0);
87 // the black scholes model wrapper won't notify the model of changes in curves and vols, so we register manually
88 builder->model()->registerWith(p_);
89 Model::McParams mcParams;
91 auto model = QuantLib::ext::make_shared<BlackScholes>(samples_, baseCcy_, p_->riskFreeRate(), underlying_, underlyingCcy_,
92 builder->model(), mcParams, arguments_.valuationDates);
93
94 // populate context
95
96 auto context = QuantLib::ext::make_shared<Context>();
97 context->scalars["TODAY"] = EventVec{samples_, Settings::instance().evaluationDate()};
98 context->scalars["Underlying"] = IndexVec{samples_, underlying_};
99 std::vector<ValueType> tmp;
100 for (auto const& d : arguments_.valuationDates)
101 tmp.push_back(EventVec{samples_, d});
102 context->arrays["ValuationDates"] = tmp;
103 context->scalars["Expiry"] = EventVec{samples_, arguments_.exercise->lastDate()};
104 context->scalars["PayCcy"] = CurrencyVec{samples_, baseCcy_};
105 context->scalars["PayDate"] = EventVec{samples_, arguments_.paymentDate};
106 context->scalars["Moneyness"] = RandomVariable{samples_, arguments_.moneyness};
107 context->scalars["Type"] = RandomVariable{samples_, arguments_.type == Option::Type::Call ? 1.0 : -1.0};
108 context->scalars["LongShort"] =
109 RandomVariable{samples_, arguments_.longShort == QuantLib::Position::Type::Long ? 1.0 : -1.0};
110 context->scalars["LocalCap"] =
111 RandomVariable{samples_, arguments_.localCap == Null<Real>() ? QL_MAX_REAL : arguments_.localCap};
112 context->scalars["LocalFloor"] =
113 RandomVariable{samples_, arguments_.localFloor == Null<Real>() ? -QL_MAX_REAL : arguments_.localFloor};
114 context->scalars["GlobalCap"] =
115 RandomVariable{samples_, arguments_.globalCap == Null<Real>() ? QL_MAX_REAL : arguments_.globalCap};
116 context->scalars["GlobalFloor"] =
117 RandomVariable{samples_, arguments_.globalFloor == Null<Real>() ? -QL_MAX_REAL : arguments_.globalFloor};
118 context->scalars["Notional"] = RandomVariable{samples_, arguments_.notional};
119 context->scalars["Premium"] =
120 RandomVariable{samples_, arguments_.premium == Null<Real>() ? 0.0 : arguments_.premium};
121 context->scalars["PremiumPaymentDate"] = EventVec{samples_, arguments_.premiumPayDate};
122 context->scalars["PremiumCurrency"] = CurrencyVec{samples_, arguments_.premiumCurrency};
123 context->scalars["Option"] = RandomVariable(samples_, 0.0); // result
124
125 // run the script engine and set the result
126
127 ScriptEngine engine(ast_, context, model);
128 engine.run("", interactive_);
129 results_.value = expectation(QuantLib::ext::get<RandomVariable>(context->scalars.at("Option"))).at(0);
130}
131
132} // namespace data
133} // namespace ore
std::string script
black scholes model for n underlyings (fx, equity or commodity)
builder for an array of black scholes processes
const Instrument::results * results_
const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > p_
CliquetOptionMcScriptEngine(const std::string &underlying, const std::string &baseCcy, const std::string &underlyingCcy, const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &p, const std::set< std::string > &tradeTypes, const Size samples, const Size regressionOrder, bool interactive, bool scriptedLibraryOverride)
void run(const std::string &script="", bool interactive=false, QuantLib::ext::shared_ptr< PayLog > paylog=nullptr, bool includePastCashflows=false)
ASTNodePtr ast() const
const ParserError & error() const
bool & interactive_
@ data
Definition: log.hpp:77
RandomVariable expectation(const RandomVariable &r)
Serializable Credit Default Swap.
Definition: namespaces.docs:23
scriptengine
script parser
Real at(const Size i) const
Swap::arguments * arguments_