public FloatingRateCoupon lastFloatingRateCoupon() { CashFlow lastCF = floatingLeg_.Last(); FloatingRateCoupon lastFloatingCoupon = lastCF as FloatingRateCoupon; return(lastFloatingCoupon); }
protected override void initializeDates() { // dummy ibor index with curve/swap arguments IborIndex clonedIborIndex = iborIndex_.clone(termStructureHandle_); // do not pass the spread here, as it might be a Quote i.e. it can dinamically change swap_ = new MakeVanillaSwap(tenor_, clonedIborIndex, 0.0, fwdStart_) .withFixedLegDayCount(fixedDayCount_) .withFixedLegTenor(new Period(fixedFrequency_)) .withFixedLegConvention(fixedConvention_) .withFixedLegTerminationDateConvention(fixedConvention_) .withFixedLegCalendar(calendar_) .withFloatingLegCalendar(calendar_); earliestDate_ = swap_.startDate(); // Usually... latestDate_ = swap_.maturityDate(); // ...but due to adjustments, the last floating coupon might // need a later date for fixing #if QL_USE_INDEXED_COUPON FloatingRateCoupon lastFloating = (FloatingRateCoupon)swap_.floatingLeg()[swap_.floatingLeg().Count - 1]; Date fixingValueDate = iborIndex_.valueDate(lastFloating.fixingDate()); Date endValueDate = iborIndex_.maturityDate(fixingValueDate); latestDate_ = Date.Max(latestDate_, endValueDate); #endif }
public override void initialize(FloatingRateCoupon coupon) { gearing_ = coupon.gearing(); spread_ = coupon.spread(); accrualPeriod_ = coupon.accrualPeriod(); Utils.QL_REQUIRE(accrualPeriod_.IsNotEqual(0.0), () => "null accrual period"); index_ = coupon.index() as IborIndex; if (index_ == null) { // check if the coupon was right IborCoupon c = coupon as IborCoupon; Utils.QL_REQUIRE(c != null, () => "IborCoupon required"); // coupon was right, index is not Utils.QL_FAIL("IborIndex required"); } Handle <YieldTermStructure> rateCurve = index_.forwardingTermStructure(); Date paymentDate = coupon.date(); if (paymentDate > rateCurve.link.referenceDate()) { discount_ = rateCurve.link.discount(paymentDate); } else { discount_ = 1.0; } spreadLegValue_ = spread_ * accrualPeriod_ * discount_; coupon_ = coupon; }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as OvernightIndexedCoupon; if (coupon_ == null) { throw new ApplicationException("wrong coupon type"); } }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as AverageBMACoupon; if (coupon_ == null) { throw new Exception("wrong coupon type"); } }
//===========================================================================// // BlackIborCouponPricer // //===========================================================================// public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as IborCoupon; if (coupon_ == null) throw new ApplicationException("Libor coupon required"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); Date paymentDate = coupon_.date(); IborIndex index = coupon_.index() as IborIndex; Handle<YieldTermStructure> rateCurve = index.forwardingTermStructure(); if (paymentDate > rateCurve.link.referenceDate()) discount_ = rateCurve.link.discount(paymentDate); else discount_ = 1.0; spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; }
// other public override void setupArguments(IPricingEngineArguments args) { base.setupArguments(args); AssetSwap.Arguments arguments = args as AssetSwap.Arguments; if (arguments == null) // it's a swap engine... { return; } List <CashFlow> fixedCoupons = bondLeg(); arguments.fixedResetDates = arguments.fixedPayDates = new List <Date>(fixedCoupons.Count); arguments.fixedCoupons = new List <double>(fixedCoupons.Count); for (int i = 0; i < fixedCoupons.Count; ++i) { FixedRateCoupon coupon = fixedCoupons[i] as FixedRateCoupon; arguments.fixedPayDates[i] = coupon.date(); arguments.fixedResetDates[i] = coupon.accrualStartDate(); arguments.fixedCoupons[i] = coupon.amount(); } List <CashFlow> floatingCoupons = floatingLeg(); arguments.floatingResetDates = arguments.floatingPayDates = arguments.floatingFixingDates = new List <Date>(floatingCoupons.Count); arguments.floatingAccrualTimes = new List <double>(floatingCoupons.Count); arguments.floatingSpreads = new List <double>(floatingCoupons.Count); for (int i = 0; i < floatingCoupons.Count; ++i) { FloatingRateCoupon coupon = floatingCoupons[i] as FloatingRateCoupon; arguments.floatingResetDates[i] = coupon.accrualStartDate(); arguments.floatingPayDates[i] = coupon.date(); arguments.floatingFixingDates[i] = coupon.fixingDate(); arguments.floatingAccrualTimes[i] = coupon.accrualPeriod(); arguments.floatingSpreads[i] = coupon.spread(); } }
public void testAccessViolation() { // Testing dynamic cast of coupon in Black pricer... SavedSettings backup = new SavedSettings(); Date todaysDate = new Date(7, Month.April, 2010); Date settlementDate = new Date(9, Month.April, 2010); Settings.setEvaluationDate(todaysDate); Calendar calendar = new TARGET(); Handle<YieldTermStructure> rhTermStructure = new Handle<YieldTermStructure>( Utilities.flatRate(settlementDate, 0.04875825, new Actual365Fixed())); double volatility = 0.10; Handle<OptionletVolatilityStructure> vol= new Handle<OptionletVolatilityStructure>( new ConstantOptionletVolatility(2, calendar, BusinessDayConvention.ModifiedFollowing, volatility, new Actual365Fixed())); IborIndex index3m =new USDLibor(new Period(3,TimeUnit.Months), rhTermStructure); Date payDate = new Date(20, Month.December, 2013); Date startDate = new Date(20, Month.September, 2013); Date endDate = new Date(20, Month.December, 2013); double spread = 0.0115; IborCouponPricer pricer = new BlackIborCouponPricer(vol); FloatingRateCoupon coupon = new FloatingRateCoupon(100,payDate, startDate, endDate, 2, index3m, 1.0 , spread / 100); coupon.setPricer(pricer); try { // this caused an access violation in version 1.0 coupon.amount(); } catch (Exception ) { // ok; proper exception thrown } }
public CappedFlooredCoupon(FloatingRateCoupon underlying, double?cap = null, double?floor = null) : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears()) { underlying_ = underlying; isCapped_ = false; isFloored_ = false; if (gearing_ > 0) { if (cap != null) { isCapped_ = true; cap_ = cap; } if (floor != null) { floor_ = floor; isFloored_ = true; } } else { if (cap != null) { floor_ = cap; isFloored_ = true; } if (floor != null) { isCapped_ = true; cap_ = floor; } } if (isCapped_ && isFloored_) { if (!(cap >= floor)) { throw new ApplicationException("cap level (" + cap + ") less than floor level (" + floor + ")"); } } underlying.registerWith(update); }
public CappedFlooredCoupon(FloatingRateCoupon underlying, double? cap = null, double? floor = null) : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears()) { underlying_ = underlying; isCapped_ = false; isFloored_ = false; if (gearing_ > 0) { if (cap != null) { isCapped_ = true; cap_ = cap; } if (floor != null) { floor_ = floor; isFloored_ = true; } } else { if (cap != null) { floor_ = cap; isFloored_ = true; } if (floor != null) { isCapped_ = true; cap_ = floor; } } if (isCapped_ && isFloored_) if (!(cap >= floor)) throw new ApplicationException("cap level (" + cap + ") less than floor level (" + floor + ")"); underlying.registerWith(update); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as RangeAccrualFloatersCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "range-accrual coupon required"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); Date paymentDate = coupon_.date(); IborIndex index = coupon_.index() as IborIndex; Utils.QL_REQUIRE(index != null, () => "invalid index"); Handle <YieldTermStructure> rateCurve = index.forwardingTermStructure(); discount_ = rateCurve.link.discount(paymentDate); accrualFactor_ = coupon_.accrualPeriod(); spreadLegValue_ = spread_ * accrualFactor_ * discount_; startTime_ = coupon_.startTime(); endTime_ = coupon_.endTime(); observationTimes_ = coupon_.observationTimes(); lowerTrigger_ = coupon_.lowerTrigger(); upperTrigger_ = coupon_.upperTrigger(); observationsNo_ = coupon_.observationsNo(); List <Date> observationDates = coupon_.observationsSchedule().dates(); Utils.QL_REQUIRE(observationDates.Count == observationsNo_ + 2, () => "incompatible size of initialValues vector"); initialValues_ = new InitializedList <double>(observationDates.Count, 0.0); Calendar calendar = index.fixingCalendar(); for (int i = 0; i < observationDates.Count; i++) { initialValues_[i] = index.fixing( calendar.advance(observationDates[i], -coupon_.fixingDays, TimeUnit.Days)); } }
//===========================================================================// // BlackIborCouponPricer // //===========================================================================// public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as IborCoupon; if (coupon_ == null) { throw new ApplicationException("Libor coupon required"); } gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); Date paymentDate = coupon_.date(); IborIndex index = coupon_.index() as IborIndex; Handle <YieldTermStructure> rateCurve = index.forwardingTermStructure(); if (paymentDate > rateCurve.link.referenceDate()) { discount_ = rateCurve.link.discount(paymentDate); } else { discount_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; }
public override void setupArguments(IPricingEngineArguments args) { CapFloor.Arguments arguments = args as CapFloor.Arguments; if (arguments == null) { throw new ArgumentException("wrong argument type"); } int n = floatingLeg_.Count; arguments.startDates = new InitializedList <Date>(n); arguments.fixingDates = new InitializedList <Date>(n); arguments.endDates = new InitializedList <Date>(n); arguments.accrualTimes = new InitializedList <double>(n); arguments.forwards = new InitializedList <double?>(n); arguments.nominals = new InitializedList <double>(n); arguments.gearings = new InitializedList <double>(n); arguments.capRates = new InitializedList <double?>(n); arguments.floorRates = new InitializedList <double?>(n); arguments.spreads = new InitializedList <double>(n); arguments.type = type_; Date today = Settings.evaluationDate(); for (int i = 0; i < n; ++i) { FloatingRateCoupon coupon = floatingLeg_[i] as FloatingRateCoupon; if (coupon == null) { throw new ArgumentException("non-FloatingRateCoupon given"); } arguments.startDates[i] = coupon.accrualStartDate(); arguments.fixingDates[i] = coupon.fixingDate(); arguments.endDates[i] = coupon.date(); // this is passed explicitly for precision arguments.accrualTimes[i] = coupon.accrualPeriod(); // this is passed explicitly for precision... if (arguments.endDates[i] >= today) { // ...but only if needed arguments.forwards[i] = coupon.adjustedFixing; } else { arguments.forwards[i] = null; } arguments.nominals[i] = coupon.nominal(); double spread = coupon.spread(); double gearing = coupon.gearing(); arguments.gearings[i] = gearing; arguments.spreads[i] = spread; if (type_ == CapFloorType.Cap || type_ == CapFloorType.Collar) { arguments.capRates[i] = (capRates_[i] - spread) / gearing; } else { arguments.capRates[i] = null; } if (type_ == CapFloorType.Floor || type_ == CapFloorType.Collar) { arguments.floorRates[i] = (floorRates_[i] - spread) / gearing; } else { arguments.floorRates[i] = null; } } }
//! \name LazyObject interface //@{ protected override void performCalculations() { // update dates Date referenceDate = termVolSurface_.referenceDate(); DayCounter dc = termVolSurface_.dayCounter(); BlackCapFloorEngine dummy = new BlackCapFloorEngine( // discounting does not matter here iborIndex_.forwardingTermStructure(), 0.20, dc); for (int i = 0; i < nOptionletTenors_; ++i) { CapFloor temp = new MakeCapFloor(CapFloorType.Cap, capFloorLengths_[i], iborIndex_, 0.04, // dummy strike new Period(0, TimeUnit.Days)) .withPricingEngine(dummy); FloatingRateCoupon lFRC = temp.lastFloatingRateCoupon(); optionletDates_[i] = lFRC.fixingDate(); optionletPaymentDates_[i] = lFRC.date(); optionletAccrualPeriods_[i] = lFRC.accrualPeriod(); optionletTimes_[i] = dc.yearFraction(referenceDate, optionletDates_[i]); atmOptionletRate_[i] = lFRC.indexFixing(); } if (floatingSwitchStrike_ && capFlooMatrixNotInitialized_) { double averageAtmOptionletRate = 0.0; for (int i = 0; i < nOptionletTenors_; ++i) { averageAtmOptionletRate += atmOptionletRate_[i]; } switchStrike_ = averageAtmOptionletRate / nOptionletTenors_; } Handle <YieldTermStructure> discountCurve = discount_.empty() ? iborIndex_.forwardingTermStructure() : discount_; List <double> strikes = new List <double>(termVolSurface_.strikes()); // initialize CapFloorMatrix if (capFlooMatrixNotInitialized_) { for (int i = 0; i < nOptionletTenors_; ++i) { capFloors_[i] = new List <CapFloor>(nStrikes_); } // construction might go here for (int j = 0; j < nStrikes_; ++j) { // using out-of-the-money options CapFloorType capFloorType = strikes[j] < switchStrike_ ? CapFloorType.Floor : CapFloorType.Cap; for (int i = 0; i < nOptionletTenors_; ++i) { //volQuotes_[i][j] = new SimpleQuote(); if (volatilityType_ == VolatilityType.ShiftedLognormal) { BlackCapFloorEngine engine = new BlackCapFloorEngine(discountCurve, new Handle <Quote>(volQuotes_[i][j]), dc, displacement_); capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j], new Period(0, TimeUnit.Days)).withPricingEngine(engine)); } else if (volatilityType_ == VolatilityType.Normal) { BachelierCapFloorEngine engine = new BachelierCapFloorEngine(discountCurve, new Handle <Quote>(volQuotes_[i][j]), dc); capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j], new Period(0, TimeUnit.Days)).withPricingEngine(engine)); } else { Utils.QL_FAIL("unknown volatility type: " + volatilityType_); } } } capFlooMatrixNotInitialized_ = false; } for (int j = 0; j < nStrikes_; ++j) { Option.Type optionletType = strikes[j] < switchStrike_ ? Option.Type.Put : Option.Type.Call; double previousCapFloorPrice = 0.0; for (int i = 0; i < nOptionletTenors_; ++i) { capFloorVols_[i, j] = termVolSurface_.volatility(capFloorLengths_[i], strikes[j], true); volQuotes_[i][j].setValue(capFloorVols_[i, j]); capFloorPrices_[i, j] = capFloors_[i][j].NPV(); optionletPrices_[i, j] = capFloorPrices_[i, j] - previousCapFloorPrice; previousCapFloorPrice = capFloorPrices_[i, j]; double d = discountCurve.link.discount(optionletPaymentDates_[i]); double optionletAnnuity = optionletAccrualPeriods_[i] * d; try { if (volatilityType_ == VolatilityType.ShiftedLognormal) { optionletStDevs_[i, j] = Utils.blackFormulaImpliedStdDev(optionletType, strikes[j], atmOptionletRate_[i], optionletPrices_[i, j], optionletAnnuity, displacement_, optionletStDevs_[i, j], accuracy_, maxIter_); } else if (volatilityType_ == VolatilityType.Normal) { optionletStDevs_[i, j] = Math.Sqrt(optionletTimes_[i]) * Utils.bachelierBlackFormulaImpliedVol( optionletType, strikes[j], atmOptionletRate_[i], optionletTimes_[i], optionletPrices_[i, j], optionletAnnuity); } else { Utils.QL_FAIL("Unknown volatility type: " + volatilityType_); } } catch (Exception e) { if (dontThrow_) { optionletStDevs_[i, j] = 0.0; } else { Utils.QL_FAIL("could not bootstrap optionlet:" + "\n type: " + optionletType + "\n strike: " + (strikes[j]) + "\n atm: " + (atmOptionletRate_[i]) + "\n price: " + optionletPrices_[i, j] + "\n annuity: " + optionletAnnuity + "\n expiry: " + optionletDates_[i] + "\n error: " + e.Message); } } optionletVolatilities_[i][j] = optionletStDevs_[i, j] / Math.Sqrt(optionletTimes_[i]); } } }
//! \name Constructors //@{ //! general constructor public DigitalCoupon(FloatingRateCoupon underlying, double? callStrike = null, Position.Type callPosition = Position.Type.Long, bool isCallATMIncluded = false, double? callDigitalPayoff = null, double? putStrike = null, Position.Type putPosition = Position.Type.Long, bool isPutATMIncluded = false, double? putDigitalPayoff = null, DigitalReplication replication = null) : base(underlying.nominal(), underlying.Date, underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears()) { if (replication == null) replication = new DigitalReplication(); underlying_ = underlying; callCsi_ = 0.0; putCsi_ = 0.0; isCallATMIncluded_ = isCallATMIncluded; isPutATMIncluded_ = isPutATMIncluded; isCallCashOrNothing_ = false; isPutCashOrNothing_ = false; callLeftEps_ = replication.gap() / 2.0; callRightEps_ = replication.gap() / 2.0; putLeftEps_ = replication.gap() / 2.0; putRightEps_ = replication.gap() / 2.0; hasPutStrike_ = false; hasCallStrike_ = false; replicationType_ = replication.replicationType(); if (!(replication.gap() > 0.0)) throw new ApplicationException("Non positive epsilon not allowed"); if (putStrike == null) if (!(putDigitalPayoff == null)) throw new ApplicationException("Put Cash rate non allowed if put strike is null"); if (callStrike == null) if (!(callDigitalPayoff == null)) throw new ApplicationException("Call Cash rate non allowed if call strike is null"); if (callStrike != null) { if (!(callStrike >= 0.0)) throw new ApplicationException("negative call strike not allowed"); hasCallStrike_ = true; callStrike_ = callStrike.GetValueOrDefault(); if (!(callStrike_ >= replication.gap() / 2.0)) throw new ApplicationException("call strike < eps/2"); switch (callPosition) { case Position.Type.Long: callCsi_ = 1.0; break; case Position.Type.Short: callCsi_ = -1.0; break; default: throw new ApplicationException("unsupported position type"); } if (callDigitalPayoff != null) { callDigitalPayoff_ = callDigitalPayoff.GetValueOrDefault(); isCallCashOrNothing_ = true; } } if (putStrike != null) { if (!(putStrike >= 0.0)) throw new ApplicationException("negative put strike not allowed"); hasPutStrike_ = true; putStrike_ = putStrike.GetValueOrDefault(); switch (putPosition) { case Position.Type.Long: putCsi_ = 1.0; break; case Position.Type.Short: putCsi_ = -1.0; break; default: throw new ApplicationException("unsupported position type"); } if (putDigitalPayoff != null) { putDigitalPayoff_ = putDigitalPayoff.GetValueOrDefault(); isPutCashOrNothing_ = true; } } switch (replicationType_) { case Replication.Type.Central: // do nothing break; case Replication.Type.Sub: if (hasCallStrike_) { switch (callPosition) { case Position.Type.Long: callLeftEps_ = 0.0; callRightEps_ = replication.gap(); break; case Position.Type.Short: callLeftEps_ = replication.gap(); callRightEps_ = 0.0; break; default: throw new ApplicationException("unsupported position type"); } } if (hasPutStrike_) { switch (putPosition) { case Position.Type.Long: putLeftEps_ = replication.gap(); putRightEps_ = 0.0; break; case Position.Type.Short: putLeftEps_ = 0.0; putRightEps_ = replication.gap(); break; default: throw new ApplicationException("unsupported position type"); } } break; case Replication.Type.Super: if (hasCallStrike_) { switch (callPosition) { case Position.Type.Long: callLeftEps_ = replication.gap(); callRightEps_ = 0.0; break; case Position.Type.Short: callLeftEps_ = 0.0; callRightEps_ = replication.gap(); break; default: throw new ApplicationException("unsupported position type"); } } if (hasPutStrike_) { switch (putPosition) { case Position.Type.Long: putLeftEps_ = 0.0; putRightEps_ = replication.gap(); break; case Position.Type.Short: putLeftEps_ = replication.gap(); putRightEps_ = 0.0; break; default: throw new ApplicationException("unsupported position type"); } } break; default: throw new ApplicationException("unsupported position type"); } underlying.registerWith(update); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as AverageBMACoupon; if (coupon_ == null) throw new ApplicationException("wrong coupon type"); }
// other public override void setupArguments(IPricingEngineArguments args) { base.setupArguments(args); Arguments arguments = args as Arguments; Utils.QL_REQUIRE(arguments != null, () => "argument type does not match"); arguments.type = type_; arguments.nominal1 = nominal1_; arguments.nominal2 = nominal2_; arguments.index1 = index1_; arguments.index2 = index2_; List <CashFlow> leg1Coupons = leg1(); List <CashFlow> leg2Coupons = leg2(); arguments.leg1ResetDates = arguments.leg1PayDates = arguments.leg1FixingDates = new InitializedList <Date>(leg1Coupons.Count); arguments.leg2ResetDates = arguments.leg2PayDates = arguments.leg2FixingDates = new InitializedList <Date>(leg2Coupons.Count); arguments.leg1Spreads = arguments.leg1AccrualTimes = arguments.leg1Gearings = new InitializedList <double>(leg1Coupons.Count); arguments.leg2Spreads = arguments.leg2AccrualTimes = arguments.leg2Gearings = new InitializedList <double>(leg2Coupons.Count); arguments.leg1Coupons = new InitializedList <double?>(leg1Coupons.Count, null); arguments.leg2Coupons = new InitializedList <double?>(leg2Coupons.Count, null); arguments.leg1IsRedemptionFlow = new InitializedList <bool>(leg1Coupons.Count, false); arguments.leg2IsRedemptionFlow = new InitializedList <bool>(leg2Coupons.Count, false); arguments.leg1CappedRates = arguments.leg1FlooredRates = new InitializedList <double?>(leg1Coupons.Count, null); arguments.leg2CappedRates = arguments.leg2FlooredRates = new InitializedList <double?>(leg2Coupons.Count, null); for (int i = 0; i < leg1Coupons.Count; ++i) { FloatingRateCoupon coupon = leg1Coupons[i] as FloatingRateCoupon; if (coupon != null) { arguments.leg1AccrualTimes[i] = coupon.accrualPeriod(); arguments.leg1PayDates[i] = coupon.date(); arguments.leg1ResetDates[i] = coupon.accrualStartDate(); arguments.leg1FixingDates[i] = coupon.fixingDate(); arguments.leg1Spreads[i] = coupon.spread(); arguments.leg1Gearings[i] = coupon.gearing(); try { arguments.leg1Coupons[i] = coupon.amount(); } catch (Exception) { arguments.leg1Coupons[i] = null; } CappedFlooredCoupon cfcoupon = leg1Coupons[i] as CappedFlooredCoupon; if (cfcoupon != null) { arguments.leg1CappedRates[i] = cfcoupon.cap(); arguments.leg1FlooredRates[i] = cfcoupon.floor(); } } else { CashFlow cashflow = leg1Coupons[i] as CashFlow; int j = arguments.leg1PayDates.FindIndex(x => x == cashflow.date()); Utils.QL_REQUIRE(j != -1, () => "nominal redemption on " + cashflow.date() + "has no corresponding coupon"); int jIdx = j; // Size jIdx = j - arguments->leg1PayDates.begin(); arguments.leg1IsRedemptionFlow[i] = true; arguments.leg1Coupons[i] = cashflow.amount(); arguments.leg1ResetDates[i] = arguments.leg1ResetDates[jIdx]; arguments.leg1FixingDates[i] = arguments.leg1FixingDates[jIdx]; arguments.leg1AccrualTimes[i] = 0.0; arguments.leg1Spreads[i] = 0.0; arguments.leg1Gearings[i] = 1.0; arguments.leg1PayDates[i] = cashflow.date(); } } for (int i = 0; i < leg2Coupons.Count; ++i) { FloatingRateCoupon coupon = leg2Coupons[i] as FloatingRateCoupon; if (coupon != null) { arguments.leg2AccrualTimes[i] = coupon.accrualPeriod(); arguments.leg2PayDates[i] = coupon.date(); arguments.leg2ResetDates[i] = coupon.accrualStartDate(); arguments.leg2FixingDates[i] = coupon.fixingDate(); arguments.leg2Spreads[i] = coupon.spread(); arguments.leg2Gearings[i] = coupon.gearing(); try { arguments.leg2Coupons[i] = coupon.amount(); } catch (Exception) { arguments.leg2Coupons[i] = null; } CappedFlooredCoupon cfcoupon = leg2Coupons[i] as CappedFlooredCoupon; if (cfcoupon != null) { arguments.leg2CappedRates[i] = cfcoupon.cap(); arguments.leg2FlooredRates[i] = cfcoupon.floor(); } } else { CashFlow cashflow = leg2Coupons[i] as CashFlow; int j = arguments.leg2PayDates.FindIndex(x => x == cashflow.date()); Utils.QL_REQUIRE(j != -1, () => "nominal redemption on " + cashflow.date() + "has no corresponding coupon"); int jIdx = j; // j - arguments->leg2PayDates.begin(); arguments.leg2IsRedemptionFlow[i] = true; arguments.leg2Coupons[i] = cashflow.amount(); arguments.leg2ResetDates[i] = arguments.leg2ResetDates[jIdx]; arguments.leg2FixingDates[i] = arguments.leg2FixingDates[jIdx]; arguments.leg2AccrualTimes[i] = 0.0; arguments.leg2Spreads[i] = 0.0; arguments.leg2Gearings[i] = 1.0; arguments.leg2PayDates[i] = cashflow.date(); } } }
// Factory - for Leg generators public virtual CashFlow factory(FloatingRateCoupon underlying, double? callStrike, Position.Type callPosition, bool isCallATMIncluded, double? callDigitalPayoff, double? putStrike, Position.Type putPosition, bool isPutATMIncluded, double? putDigitalPayoff, DigitalReplication replication) { return new DigitalCoupon(underlying, callStrike, callPosition, isCallATMIncluded, callDigitalPayoff, putStrike, putPosition, isPutATMIncluded, putDigitalPayoff, replication); }
public abstract void initialize(FloatingRateCoupon coupon);
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as OvernightIndexedCoupon; if (coupon_ == null) throw new ApplicationException("wrong coupon type"); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as OvernightIndexedCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "wrong coupon type"); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as AverageBMACoupon; Utils.QL_REQUIRE(coupon_ != null, () => "wrong coupon type"); }
// Factory - for Leg generators public virtual CashFlow factory(FloatingRateCoupon underlying, double?callStrike, Position.Type callPosition, bool isCallATMIncluded, double?callDigitalPayoff, double?putStrike, Position.Type putPosition, bool isPutATMIncluded, double?putDigitalPayoff, DigitalReplication replication) { return(new DigitalCoupon(underlying, callStrike, callPosition, isCallATMIncluded, callDigitalPayoff, putStrike, putPosition, isPutATMIncluded, putDigitalPayoff, replication)); }
//! \name Constructors //@{ //! general constructor public DigitalCoupon(FloatingRateCoupon underlying, double?callStrike = null, Position.Type callPosition = Position.Type.Long, bool isCallATMIncluded = false, double?callDigitalPayoff = null, double?putStrike = null, Position.Type putPosition = Position.Type.Long, bool isPutATMIncluded = false, double?putDigitalPayoff = null, DigitalReplication replication = null) : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears()) { if (replication == null) { replication = new DigitalReplication(); } underlying_ = underlying; callCsi_ = 0.0; putCsi_ = 0.0; isCallATMIncluded_ = isCallATMIncluded; isPutATMIncluded_ = isPutATMIncluded; isCallCashOrNothing_ = false; isPutCashOrNothing_ = false; callLeftEps_ = replication.gap() / 2.0; callRightEps_ = replication.gap() / 2.0; putLeftEps_ = replication.gap() / 2.0; putRightEps_ = replication.gap() / 2.0; hasPutStrike_ = false; hasCallStrike_ = false; replicationType_ = replication.replicationType(); if (!(replication.gap() > 0.0)) { throw new ApplicationException("Non positive epsilon not allowed"); } if (putStrike == null) { if (!(putDigitalPayoff == null)) { throw new ApplicationException("Put Cash rate non allowed if put strike is null"); } } if (callStrike == null) { if (!(callDigitalPayoff == null)) { throw new ApplicationException("Call Cash rate non allowed if call strike is null"); } } if (callStrike != null) { if (!(callStrike >= 0.0)) { throw new ApplicationException("negative call strike not allowed"); } hasCallStrike_ = true; callStrike_ = callStrike.GetValueOrDefault(); if (!(callStrike_ >= replication.gap() / 2.0)) { throw new ApplicationException("call strike < eps/2"); } switch (callPosition) { case Position.Type.Long: callCsi_ = 1.0; break; case Position.Type.Short: callCsi_ = -1.0; break; default: throw new ApplicationException("unsupported position type"); } if (callDigitalPayoff != null) { callDigitalPayoff_ = callDigitalPayoff.GetValueOrDefault(); isCallCashOrNothing_ = true; } } if (putStrike != null) { if (!(putStrike >= 0.0)) { throw new ApplicationException("negative put strike not allowed"); } hasPutStrike_ = true; putStrike_ = putStrike.GetValueOrDefault(); switch (putPosition) { case Position.Type.Long: putCsi_ = 1.0; break; case Position.Type.Short: putCsi_ = -1.0; break; default: throw new ApplicationException("unsupported position type"); } if (putDigitalPayoff != null) { putDigitalPayoff_ = putDigitalPayoff.GetValueOrDefault(); isPutCashOrNothing_ = true; } } switch (replicationType_) { case Replication.Type.Central: // do nothing break; case Replication.Type.Sub: if (hasCallStrike_) { switch (callPosition) { case Position.Type.Long: callLeftEps_ = 0.0; callRightEps_ = replication.gap(); break; case Position.Type.Short: callLeftEps_ = replication.gap(); callRightEps_ = 0.0; break; default: throw new ApplicationException("unsupported position type"); } } if (hasPutStrike_) { switch (putPosition) { case Position.Type.Long: putLeftEps_ = replication.gap(); putRightEps_ = 0.0; break; case Position.Type.Short: putLeftEps_ = 0.0; putRightEps_ = replication.gap(); break; default: throw new ApplicationException("unsupported position type"); } } break; case Replication.Type.Super: if (hasCallStrike_) { switch (callPosition) { case Position.Type.Long: callLeftEps_ = replication.gap(); callRightEps_ = 0.0; break; case Position.Type.Short: callLeftEps_ = 0.0; callRightEps_ = replication.gap(); break; default: throw new ApplicationException("unsupported position type"); } } if (hasPutStrike_) { switch (putPosition) { case Position.Type.Long: putLeftEps_ = 0.0; putRightEps_ = replication.gap(); break; case Position.Type.Short: putLeftEps_ = replication.gap(); putRightEps_ = 0.0; break; default: throw new ApplicationException("unsupported position type"); } } break; default: throw new ApplicationException("unsupported position type"); } underlying.registerWith(update); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as CmsCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); fixingDate_ = coupon_.fixingDate(); paymentDate_ = coupon_.date(); swapIndex_ = coupon_.swapIndex(); forwardCurve_ = swapIndex_.forwardingTermStructure(); if (swapIndex_.exogenousDiscount()) { discountCurve_ = swapIndex_.discountingTermStructure(); } else { discountCurve_ = forwardCurve_; } // if no coupon discount curve is given just use the discounting curve // from the swap index. for rate calculation this curve cancels out in // the computation, so e.g. the discounting swap engine will produce // correct results, even if the couponDiscountCurve is not set here. // only the price member function in this class will be dependent on the // coupon discount curve. today_ = QLNet.Settings.evaluationDate(); if (paymentDate_ > today_ && !couponDiscountCurve_.empty()) { couponDiscountRatio_ = couponDiscountCurve_.link.discount(paymentDate_) / discountCurve_.link.discount(paymentDate_); } else { couponDiscountRatio_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discountCurve_.link.discount(paymentDate_) * couponDiscountRatio_; if (fixingDate_ > today_) { swapTenor_ = swapIndex_.tenor(); swap_ = swapIndex_.underlyingSwap(fixingDate_); swapRateValue_ = swap_.fairRate(); annuity_ = 1.0E4 * Math.Abs(swap_.fixedLegBPS()); SmileSection sectionTmp = swaptionVolatility().link.smileSection(fixingDate_, swapTenor_); // adjust bounds by section's shift shiftedLowerBound_ = settings_.lowerRateBound_ - sectionTmp.shift(); shiftedUpperBound_ = settings_.upperRateBound_ - sectionTmp.shift(); // if the section does not provide an atm level, we enhance it to // have one, no need to exit with an exception ... if (sectionTmp.atmLevel() == null) { smileSection_ = new AtmSmileSection(sectionTmp, swapRateValue_); } else { smileSection_ = sectionTmp; } // compute linear model's parameters double gx = 0.0, gy = 0.0; for (int i = 0; i < swap_.fixedLeg().Count; i++) { Coupon c = swap_.fixedLeg()[i] as Coupon; double yf = c.accrualPeriod(); Date d = c.date(); double pv = yf * discountCurve_.link.discount(d); gx += pv * GsrG(d); gy += pv; } double gamma = gx / gy; Date lastd = swap_.fixedLeg().Last().date(); a_ = discountCurve_.link.discount(paymentDate_) * (gamma - GsrG(paymentDate_)) / (discountCurve_.link.discount(lastd) * GsrG(lastd) + swapRateValue_ * gy * gamma); b_ = discountCurve_.link.discount(paymentDate_) / gy - a_ * swapRateValue_; } }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as CmsCoupon; Utils.QL_REQUIRE( coupon_ != null, () => "CMS coupon needed" ); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); fixingDate_ = coupon_.fixingDate(); paymentDate_ = coupon_.date(); SwapIndex swapIndex = coupon_.swapIndex(); rateCurve_ = swapIndex.forwardingTermStructure().link; Date today = Settings.evaluationDate(); if (paymentDate_ > today) discount_ = rateCurve_.discount(paymentDate_); else discount_ = 1.0; spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; if (fixingDate_ > today) { swapTenor_ = swapIndex.tenor(); VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_); swapRateValue_ = swap.fairRate(); double bp = 1.0e-4; annuity_ = (swap.floatingLegBPS() / bp); int q = (int)swapIndex.fixedLegTenor().frequency(); Schedule schedule = swap.fixedSchedule(); DayCounter dc = swapIndex.dayCounter(); //DayCounter dc = coupon.dayCounter(); double startTime = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate()); double swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1)); double paymentTime = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_); double delta = (paymentTime - startTime) / (swapFirstPaymentTime - startTime); switch (modelOfYieldCurve_) { case GFunctionFactory.YieldCurveModel.Standard: gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length()); break; case GFunctionFactory.YieldCurveModel.ExactYield: gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_); break; case GFunctionFactory.YieldCurveModel.ParallelShifts: { Handle<Quote> nullMeanReversionQuote = new Handle<Quote>(new SimpleQuote(0.0)); gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote); } break; case GFunctionFactory.YieldCurveModel.NonParallelShifts: gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_); break; default: throw new ApplicationException("unknown/illegal gFunction type"); } vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link); } }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as CmsCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); fixingDate_ = coupon_.fixingDate(); paymentDate_ = coupon_.date(); SwapIndex swapIndex = coupon_.swapIndex(); rateCurve_ = swapIndex.forwardingTermStructure().link; Date today = Settings.evaluationDate(); if (paymentDate_ > today) { discount_ = rateCurve_.discount(paymentDate_); } else { discount_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; if (fixingDate_ > today) { swapTenor_ = swapIndex.tenor(); VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_); swapRateValue_ = swap.fairRate(); double bp = 1.0e-4; annuity_ = (swap.floatingLegBPS() / bp); int q = (int)swapIndex.fixedLegTenor().frequency(); Schedule schedule = swap.fixedSchedule(); DayCounter dc = swapIndex.dayCounter(); //DayCounter dc = coupon.dayCounter(); double startTime = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate()); double swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1)); double paymentTime = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_); double delta = (paymentTime - startTime) / (swapFirstPaymentTime - startTime); switch (modelOfYieldCurve_) { case GFunctionFactory.YieldCurveModel.Standard: gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length()); break; case GFunctionFactory.YieldCurveModel.ExactYield: gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_); break; case GFunctionFactory.YieldCurveModel.ParallelShifts: { Handle <Quote> nullMeanReversionQuote = new Handle <Quote>(new SimpleQuote(0.0)); gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote); } break; case GFunctionFactory.YieldCurveModel.NonParallelShifts: gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_); break; default: throw new ApplicationException("unknown/illegal gFunction type"); } vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link); } }
public void visit(FloatingRateCoupon c) { c.setPricer(pricer_); }