Skip to content

Commit 2a4e365

Browse files
pcaspersjenkins
authored andcommitted
QPR-12382 fix upfront amount pay date, update regression test
1 parent b537b9f commit 2a4e365

1 file changed

Lines changed: 31 additions & 20 deletions

File tree

QuantExt/qle/pricingengines/intrinsicascotengine.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
*/
1818

1919
#include <algorithm>
20-
#include <qle/pricingengines/binomialconvertibleengine.hpp>
21-
#include <qle/pricingengines/intrinsicascotengine.hpp>
2220
#include <ql/cashflows/cashflows.hpp>
2321
#include <ql/cashflows/iborcoupon.hpp>
2422
#include <ql/cashflows/simplecashflow.hpp>
23+
#include <qle/pricingengines/binomialconvertibleengine.hpp>
24+
#include <qle/pricingengines/intrinsicascotengine.hpp>
2525

2626
namespace QuantExt {
2727

@@ -38,31 +38,42 @@ void IntrinsicAscotEngine::calculate() const {
3838
Real bondPrice = arguments_.bondQuantity * bond.NPV();
3939

4040
Date referenceDate = discountCurve_->referenceDate();
41+
Date settlementDate = bond.calendar().advance(referenceDate, bond.settlementDays(), QuantLib::Days);
4142

42-
Leg notional;
43-
auto coupon = boost::dynamic_pointer_cast<QuantLib::Coupon>(bond.cashflows()[0]);
44-
QL_REQUIRE(coupon, "expected non-coupon legs");
45-
double initFlowAmt = coupon->nominal();
46-
Date initDate = coupon->accrualStartDate();
47-
initDate = bond.calendar().adjust(initDate, Following);
48-
if (initFlowAmt != 0)
49-
notional.push_back(boost::shared_ptr<CashFlow>(new SimpleCashFlow(initFlowAmt, initDate)));
43+
Real currentNotional = Null<Real>();
44+
for (auto const& c : bond.cashflows()) {
45+
if (auto coupon = boost::dynamic_pointer_cast<QuantLib::Coupon>(c)) {
46+
currentNotional = coupon->nominal();
47+
if (c->date() > referenceDate)
48+
break;
49+
}
50+
}
5051

51-
Real upfrontPayment = CashFlows::npv(notional, **discountCurve_, false, referenceDate, referenceDate);
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(boost::make_shared<SimpleCashFlow>(currentNotional, settlementDate));
57+
Real upfrontLegNpv = CashFlows::npv(upfrontLeg, **discountCurve_, false, referenceDate, referenceDate);
5258

5359
// includes redemption flows
54-
Real assetLeg = CashFlows::npv(bond.cashflows(), **discountCurve_, false, referenceDate, referenceDate);
60+
Real assetLegNpv = CashFlows::npv(bond.cashflows(), **discountCurve_, false, referenceDate, referenceDate);
5561

56-
Real redemptionLeg = CashFlows::npv(bond.redemptions(), **discountCurve_, false, referenceDate, referenceDate);
62+
Real redemptionLegNpv = CashFlows::npv(bond.redemptions(), **discountCurve_, false, referenceDate, referenceDate);
5763

5864
// multiplied by bondNotional already
59-
Real fundingLeg = CashFlows::npv(arguments_.fundingLeg, **discountCurve_, true, referenceDate, referenceDate);
60-
61-
Real X = arguments_.bondQuantity * (upfrontPayment + assetLeg - redemptionLeg) - fundingLeg;
62-
63-
boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(arguments_.callPut, X));
64-
65-
results_.value = (*payoff)(bondPrice);
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;
6677
}
6778

6879
} // namespace QuantExt

0 commit comments

Comments
 (0)