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
2626namespace 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