36struct anyGetter :
public boost::static_visitor<boost::any> {
37 explicit anyGetter(
const QuantLib::ext::shared_ptr<Model>& model) :
model_(model) {}
38 boost::any operator()(
const RandomVariable& x)
const {
return model_->extractT0Result(x); }
39 boost::any operator()(
const EventVec& x)
const {
return x.value; }
40 boost::any operator()(
const IndexVec& x)
const {
return x.value; }
41 boost::any operator()(
const CurrencyVec& x)
const {
return x.value; }
42 boost::any operator()(
const DaycounterVec& x)
const {
return x.value; }
43 boost::any operator()(
const Filter& x)
const {
44 QL_FAIL(
"can not convert Filter to boost::any, unexpected call to anyGetter");
46 QuantLib::ext::shared_ptr<Model>
model_;
49boost::any valueToAny(
const QuantLib::ext::shared_ptr<Model>& model,
const ValueType& v) {
50 return boost::apply_visitor(anyGetter(model), v);
60 Real var =
variance(QuantLib::ext::get<RandomVariable>(v)).
at(0);
61 Real errEst = std::sqrt(var /
static_cast<double>(
model_->size()));
63 results_.additionalResults[label] = errEst;
72 struct MemoryReleaser {
73 ~MemoryReleaser() { model->releaseMemory(); }
74 QuantLib::ext::shared_ptr<Model> model;
76 MemoryReleaser memoryReleaser{
model_};
80 auto workingContext = QuantLib::ext::make_shared<Context>(*
context_);
87 workingContext->constants.insert(
"TODAY");
95 if (
model_->trainingSamples() != Null<Size>()) {
96 auto trainingContext = QuantLib::ext::make_shared<Context>(*workingContext);
97 trainingContext->resetSize(
model_->trainingSamples());
98 struct TrainingPathToggle {
99 TrainingPathToggle(QuantLib::ext::shared_ptr<Model> model) : model(model) { model->toggleTrainingPaths(); }
100 ~TrainingPathToggle() { model->toggleTrainingPaths(); }
101 QuantLib::ext::shared_ptr<Model> model;
111 QuantLib::ext::shared_ptr<PayLog> paylog;
113 paylog = QuantLib::ext::make_shared<PayLog>();
119 auto npv = workingContext->scalars.find(
npv_);
120 QL_REQUIRE(npv != workingContext->scalars.end(),
121 "did not find npv result variable '" <<
npv_ <<
"' as scalar in context");
123 "result variable '" <<
npv_ <<
"' must be of type NUMBER, got " << npv->second.which());
124 results_.value =
model_->extractT0Result(QuantLib::ext::get<RandomVariable>(npv->second));
132 auto s = workingContext->scalars.find(r.second);
133 bool resultSet =
false;
134 if (s != workingContext->scalars.end()) {
135 boost::any t = valueToAny(
model_, s->second);
136 results_.additionalResults[r.first] = t;
138 DLOG(
"got additional result '" << r.first <<
"' referencing script variable '" << r.second <<
"'");
141 auto v = workingContext->arrays.find(r.second);
142 if (v != workingContext->arrays.end()) {
143 QL_REQUIRE(!resultSet,
"result variable '"
144 << r.first <<
"' referencing script variable '" << r.second
145 <<
"' appears both as a scalar and an array, this is unexpected");
146 QL_REQUIRE(!v->second.empty(),
"result variable '" << v->first <<
"' is an empty array.");
147 std::vector<double> tmpdouble;
148 std::vector<std::string> tmpstring;
149 std::vector<QuantLib::Date> tmpdate;
150 for (
auto const& d : v->second) {
151 boost::any t = valueToAny(
model_, d);
152 if (t.type() ==
typeid(
double))
153 tmpdouble.push_back(boost::any_cast<double>(t));
154 else if (t.type() ==
typeid(std::string))
155 tmpstring.push_back(boost::any_cast<std::string>(t));
156 else if (t.type() ==
typeid(QuantLib::Date))
157 tmpdate.push_back(boost::any_cast<QuantLib::Date>(t));
159 QL_FAIL(
"unexpected result type '" << t.type().name() <<
"' for result variable '" << r.first
160 <<
"' referencing script variable '" << r.second <<
"'");
163 QL_REQUIRE((
int)!tmpdouble.empty() + (
int)!tmpstring.empty() + (
int)!tmpdate.empty() == 1,
164 "expected exactly one result type in result array '" << v->first <<
"'");
165 DLOG(
"got additional result '" << r.first <<
"' referencing script variable '" << r.second
166 <<
"' vector of size "
167 << tmpdouble.size() + tmpstring.size() + tmpdate.size());
168 if (!tmpdouble.empty())
169 results_.additionalResults[r.first] = tmpdouble;
170 else if (!tmpstring.empty())
171 results_.additionalResults[r.first] = tmpstring;
172 else if (!tmpdate.empty())
173 results_.additionalResults[r.first] = tmpdate;
175 QL_FAIL(
"got empty result vector for result variable '"
176 << r.first <<
"' referencing script variable '" << r.second <<
"', this is unexpected");
178 std::vector<double> errEst;
179 for (
auto const& d : v->second) {
182 if (!errEst.empty() && errEst.front() != Null<Real>())
183 results_.additionalResults[r.first +
"_MCErrEst"] = errEst;
186 QL_REQUIRE(resultSet,
"could not set additional result '" << r.first <<
"' referencing script variable '"
192 paylog->consolidateAndSort();
193 std::vector<CashFlowResults> cashFlowResults(paylog->size());
194 std::map<Size, Size> cashflowNumber;
195 for (Size i = 0; i < paylog->size(); ++i) {
200 if (paylog->dates().at(i) >
model_->referenceDate()) {
201 fx =
model_->fxSpotT0(paylog->currencies().at(i),
model_->baseCcy());
202 discount =
model_->discount(
referenceDate, paylog->dates().at(i), paylog->currencies().at(i)).at(0);
204 cashFlowResults[i].amount =
model_->extractT0Result(paylog->amounts().at(i)) / fx / discount;
205 cashFlowResults[i].payDate = paylog->dates().at(i);
206 cashFlowResults[i].currency = paylog->currencies().at(i);
207 cashFlowResults[i].legNumber = paylog->legNos().at(i);
208 cashFlowResults[i].type = paylog->cashflowTypes().at(i);
209 DLOG(
"got cashflow " << QuantLib::io::iso_date(cashFlowResults[i].payDate) <<
" "
210 << cashFlowResults[i].currency << cashFlowResults[i].amount <<
" "
211 << cashFlowResults[i].currency <<
"-" <<
model_->baseCcy() <<
" " << fx <<
" discount("
212 << cashFlowResults[i].currency <<
") " << discount);
213 if (paylog->dates().at(i) >
model_->referenceDate()) {
215 std::to_string(++cashflowNumber[paylog->legNos().at(i)]) +
"_MCErrEst",
216 paylog->amounts().at(i) /
220 results_.additionalResults[
"cashFlowResults"] = cashFlowResults;
224 results_.additionalResults.insert(
model_->additionalResults().begin(),
model_->additionalResults().end());
231 DLOG(
"add amc calculator to results");
232 results_.additionalResults[
"amcCalculator"] =
233 QuantLib::ext::static_pointer_cast<AmcCalculator>(QuantLib::ext::make_shared<ScriptedInstrumentAmcCalculator>(
const Instrument::results * results_
void run(const std::string &script="", bool interactive=false, QuantLib::ext::shared_ptr< PayLog > paylog=nullptr, bool includePastCashflows=false)
const QuantLib::ext::shared_ptr< Context > context_
const std::set< std::string > amcStickyCloseOutStates_
const std::string script_
void calculate() const override
Real addMcErrorEstimate(const std::string &label, const ValueType &v) const
const std::vector< std::pair< std::string, std::string > > additionalResults_
const QuantLib::ext::shared_ptr< Model > model_
const bool generateAdditionalResults_
bool lastCalculationWasValid_
const bool includePastCashflows_
const QuantLib::ext::shared_ptr< ModelCG > model_
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
RandomVariable variance(const RandomVariable &r)
void checkDuplicateName(const QuantLib::ext::shared_ptr< Context > context, const std::string &name)
boost::variant< RandomVariable, EventVec, CurrencyVec, IndexVec, DaycounterVec, Filter > ValueType
Serializable Credit Default Swap.
amc calculator for scripted trades
scripted instrument pricing engine
Real at(const Size i) const