Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
intrinsicascotengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 Quaternion Risk Managment 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
19#include <algorithm>
20#include <ql/cashflows/cashflows.hpp>
21#include <ql/cashflows/iborcoupon.hpp>
22#include <ql/cashflows/simplecashflow.hpp>
25
26namespace QuantExt {
27
28IntrinsicAscotEngine::IntrinsicAscotEngine(const Handle<YieldTermStructure>& discountCurve)
29 : discountCurve_(discountCurve) {
30 registerWith(discountCurve_);
31}
32
34
35 QL_REQUIRE(arguments_.exercise->type() == Exercise::American, "not an American option");
36
37 ConvertibleBond2 bond = *arguments_.bond;
38 Real bondPrice = arguments_.bondQuantity * bond.NPV();
39
40 Date referenceDate = discountCurve_->referenceDate();
41 Date settlementDate = bond.calendar().advance(referenceDate, bond.settlementDays(), QuantLib::Days);
42
43 Real currentNotional = Null<Real>();
44 for (auto const& c : bond.cashflows()) {
45 if (auto coupon = QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(c)) {
46 currentNotional = coupon->nominal();
47 if (c->date() > referenceDate)
48 break;
49 }
50 }
51
52 QL_REQUIRE(currentNotional != Null<Real>(), "IntrinsicAscotEngine::calculate(): could not determine current "
53 "notional, underlying bond must have at least one coupon");
54
55 Leg upfrontLeg;
56 upfrontLeg.push_back(QuantLib::ext::make_shared<SimpleCashFlow>(currentNotional, settlementDate));
57 Real upfrontLegNpv = CashFlows::npv(upfrontLeg, **discountCurve_, false, referenceDate, referenceDate);
58
59 // includes redemption flows
60 Real assetLegNpv = CashFlows::npv(bond.cashflows(), **discountCurve_, false, referenceDate, referenceDate);
61
62 Real redemptionLegNpv = CashFlows::npv(bond.redemptions(), **discountCurve_, false, referenceDate, referenceDate);
63
64 // multiplied by bondNotional already
65 Real fundingLegNpv = CashFlows::npv(arguments_.fundingLeg, **discountCurve_, true, referenceDate, referenceDate);
66
67 Real strike = arguments_.bondQuantity * (upfrontLegNpv + assetLegNpv - redemptionLegNpv) - fundingLegNpv;
68
69 results_.value = PlainVanillaPayoff(arguments_.callPut, strike)(bondPrice);
70 results_.additionalResults["bondPrice"] = bondPrice;
71 results_.additionalResults["strike"] = strike;
72 results_.additionalResults["fundingLegNpv"] = fundingLegNpv;
73 results_.additionalResults["redemptionLegNpv"] = redemptionLegNpv * arguments_.bondQuantity;
74 results_.additionalResults["assetLegNpv"] = assetLegNpv * arguments_.bondQuantity;
75 results_.additionalResults["upfrontLegNpv"] = upfrontLegNpv * arguments_.bondQuantity;
76 results_.additionalResults["bondQuantity"] = arguments_.bondQuantity;
77}
78
79} // namespace QuantExt
binomial engine for convertible bonds
const Instrument::results * results_
Definition: cdsoption.cpp:81
Handle< YieldTermStructure > discountCurve_
IntrinsicAscotEngine(const Handle< YieldTermStructure > &discountCurve)
intrinsic engine for Ascots
Swap::arguments * arguments_