public InterpolatedPiecewiseZeroSpreadedTermStructure(Handle <YieldTermStructure> h, List <Handle <Quote> > spreads, List <Date> dates, Compounding compounding = Compounding.Continuous, Frequency frequency = Frequency.NoFrequency, DayCounter dc = default(DayCounter), Interpolator factory = default(Interpolator)) { originalCurve_ = h; spreads_ = spreads; dates_ = dates; times_ = new InitializedList <double>(dates.Count); spreadValues_ = new InitializedList <double>(dates.Count); compounding_ = compounding; frequency_ = frequency; dc_ = dc ?? new DayCounter(); factory_ = factory ?? FastActivator <Interpolator> .Create(); Utils.QL_REQUIRE(!spreads_.empty(), () => "no spreads given"); Utils.QL_REQUIRE(spreads_.Count == dates_.Count, () => "spread and date vector have different sizes"); originalCurve_.registerWith(update); for (int i = 0; i < spreads_.Count; i++) { spreads_[i].registerWith(update); } if (!originalCurve_.empty()) { updateInterpolation(); } }
public virtual void setCapletVolatility(Handle <YoYOptionletVolatilitySurface> capletVol) { Utils.QL_REQUIRE(!capletVol.empty(), () => "empty capletVol handle"); capletVol_ = capletVol; capletVol_.registerWith(update); }
protected SwaptionVolatilityCube(Handle <SwaptionVolatilityStructure> atmVol, List <Period> optionTenors, List <Period> swapTenors, List <double> strikeSpreads, List <List <Handle <Quote> > > volSpreads, SwapIndex swapIndexBase, SwapIndex shortSwapIndexBase, bool vegaWeightedSmileFit) : base(optionTenors, swapTenors, 0, atmVol.link.calendar(), atmVol.link.businessDayConvention(), atmVol.link.dayCounter()) { atmVol_ = atmVol; nStrikes_ = strikeSpreads.Count; strikeSpreads_ = strikeSpreads; localStrikes_ = new InitializedList <double>(nStrikes_); localSmile_ = new List <double>(nStrikes_); volSpreads_ = volSpreads; swapIndexBase_ = swapIndexBase; shortSwapIndexBase_ = shortSwapIndexBase; vegaWeightedSmileFit_ = vegaWeightedSmileFit; Utils.QL_REQUIRE(!atmVol_.empty(), () => "atm vol handle not linked to anything"); for (int i = 1; i < nStrikes_; ++i) { Utils.QL_REQUIRE(strikeSpreads_[i - 1] < strikeSpreads_[i], () => "non increasing strike spreads: " + i + " is " + strikeSpreads_[i - 1] + ", " + (i + 1) + " is " + strikeSpreads_[i]); } Utils.QL_REQUIRE(!volSpreads_.empty(), () => "empty vol spreads matrix"); Utils.QL_REQUIRE(nOptionTenors_ * nSwapTenors_ == volSpreads_.Count, () => "mismatch between number of option tenors * swap tenors (" + nOptionTenors_ * nSwapTenors_ + ") and number of rows (" + volSpreads_.Count + ")"); for (int i = 0; i < volSpreads_.Count; i++) { Utils.QL_REQUIRE(nStrikes_ == volSpreads_[i].Count, () => "mismatch between number of strikes (" + nStrikes_ + ") and number of columns (" + volSpreads_[i].Count + ") in the " + (i + 1) + " row"); } atmVol_.registerWith(update); atmVol_.link.enableExtrapolation(); swapIndexBase_.registerWith(update); shortSwapIndexBase_.registerWith(update); Utils.QL_REQUIRE(shortSwapIndexBase_.tenor() < swapIndexBase_.tenor(), () => "short index tenor (" + shortSwapIndexBase_.tenor() + ") is not less than index tenor (" + swapIndexBase_.tenor() + ")"); registerWithVolatilitySpread(); Settings.Instance.registerWith(update); evaluationDate_ = Settings.Instance.evaluationDate(); }
public double forecastFixing(Date d1, Date d2, double t) { Utils.QL_REQUIRE(!termStructure_.empty(), () => "null term structure set to this instance of " + name()); double disc1 = termStructure_.link.discount(d1); double disc2 = termStructure_.link.discount(d2); return((disc1 / disc2 - 1.0) / t); }
public SpreadFittingMethod(FittedBondDiscountCurve.FittingMethod method, Handle <YieldTermStructure> discountCurve) : base(method != null ? method.constrainAtZero() : true, method != null ? method.weights() : null, method != null ? method.optimizationMethod() : null) { method_ = method; discountingCurve_ = discountCurve; Utils.QL_REQUIRE(method != null, () => "Fitting method is empty"); Utils.QL_REQUIRE(!discountingCurve_.empty(), () => "Discounting curve cannot be empty"); }
public CPICouponPricer(Handle <CPIVolatilitySurface> capletVol = null) { if (capletVol == null) { capletVol = new Handle <CPIVolatilitySurface>(); } capletVol_ = capletVol; if (!capletVol_.empty()) { capletVol_.registerWith(update); } }
public override void update() { if (!curve1_.empty() && !curve2_.empty()) { base.update(); enableExtrapolation(curve1_.link.allowsExtrapolation() && curve2_.link.allowsExtrapolation()); } else { /* The implementation inherited from YieldTermStructure * asks for our reference date, which we don't have since * the original curve is still not set. Therefore, we skip * over that and just call the base-class behavior. */ base.update(); } }
protected new void update() { if (!originalCurve_.empty()) { updateInterpolation(); base.update(); } else { /* The implementation inherited from YieldTermStructure * asks for our reference date, which we don't have since * the original curve is still not set. Therefore, we skip * over that and just call the base-class behavior. */ base.update(); } }
public LognormalCmsSpreadPricer( CmsCouponPricer cmsPricer1, CmsCouponPricer cmsPricer2, Handle <Quote> correlation, Handle <YieldTermStructure> couponDiscountCurve = null, int integrationPoints = 16, VolatilityType volatilityType = VolatilityType.None, double?shift1 = null, double?shift2 = null) : base(correlation) { correlation_.registerWith(update); cmsPricer1_ = cmsPricer1; cmsPricer2_ = cmsPricer2; couponDiscountCurve_ = couponDiscountCurve; if (couponDiscountCurve_ != null && !couponDiscountCurve_.empty()) { couponDiscountCurve_.registerWith(update); } cmsPricer1_.registerWith(update); cmsPricer2_.registerWith(update); Utils.QL_REQUIRE(integrationPoints >= 4, () => "at least 4 integration points should be used (" + integrationPoints + ")"); integrator_ = new GaussHermiteIntegration(integrationPoints); cnd_ = new CumulativeNormalDistribution(0.0, 1.0); if (volatilityType == VolatilityType.None) { Utils.QL_REQUIRE(shift1 == null && shift2 == null, () => "if volatility type is inherited, no shifts should be specified"); inheritedVolatilityType_ = true; volType_ = cmsPricer1.swaptionVolatility().currentLink().volatilityType(); } else { shift1_ = shift1 == null ? 0.0 : shift1.Value; shift2_ = shift2 == null ? 0.0 : shift2.Value; inheritedVolatilityType_ = false; volType_ = volatilityType; } }
public VannaVolgaDoubleBarrierEngine(Handle <DeltaVolQuote> atmVol, Handle <DeltaVolQuote> vol25Put, Handle <DeltaVolQuote> vol25Call, Handle <Quote> spotFX, Handle <YieldTermStructure> domesticTS, Handle <YieldTermStructure> foreignTS, GetOriginalEngine getEngine, bool adaptVanDelta = false, double bsPriceWithSmile = 0.0, int series = 5) : base() { atmVol_ = atmVol; vol25Put_ = vol25Put; vol25Call_ = vol25Call; T_ = atmVol_.link.maturity(); spotFX_ = spotFX; domesticTS_ = domesticTS; foreignTS_ = foreignTS; adaptVanDelta_ = adaptVanDelta; bsPriceWithSmile_ = bsPriceWithSmile; series_ = series; getOriginalEngine_ = getEngine; Utils.QL_REQUIRE(vol25Put_.link.delta().IsEqual(-0.25), () => "25 delta put is required by vanna volga method"); Utils.QL_REQUIRE(vol25Call_.link.delta().IsEqual(0.25), () => "25 delta call is required by vanna volga method"); Utils.QL_REQUIRE(vol25Put_.link.maturity().IsEqual(vol25Call_.link.maturity()) && vol25Put_.link.maturity().IsEqual(atmVol_.link.maturity()), () => "Maturity of 3 vols are not the same"); Utils.QL_REQUIRE(!domesticTS_.empty(), () => "domestic yield curve is not defined"); Utils.QL_REQUIRE(!foreignTS_.empty(), () => "foreign yield curve is not defined"); atmVol_.registerWith(update); vol25Put_.registerWith(update); vol25Call_.registerWith(update); spotFX_.registerWith(update); domesticTS_.registerWith(update); foreignTS_.registerWith(update); }
public CompositeZeroYieldStructure(Handle <YieldTermStructure> h1, Handle <YieldTermStructure> h2, Func <double, double, double> f, Compounding comp = Compounding.Continuous, Frequency freq = Frequency.NoFrequency) { curve1_ = h1; curve2_ = h2; f_ = f; comp_ = comp; freq_ = freq; if (!curve1_.empty() && !curve2_.empty()) { enableExtrapolation(curve1_.link.allowsExtrapolation() && curve2_.link.allowsExtrapolation()); } curve1_.registerWith(update); curve2_.registerWith(update); }
public override double swapletRate() { OvernightIndex index = coupon_.index() as OvernightIndex; List <Date> fixingDates = coupon_.fixingDates(); List <double> dt = coupon_.dt(); int n = dt.Count; int i = 0; double compoundFactor = 1.0; // already fixed part Date today = Settings.Instance.evaluationDate(); while (fixingDates[i] < today && i < n) { // rate must have been fixed double?pastFixing = IndexManager.Instance.getHistory(index.name())[fixingDates[i]]; Utils.QL_REQUIRE(pastFixing != null, () => "Missing " + index.name() + " fixing for " + fixingDates[i].ToString()); compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]); ++i; } // today is a border case if (fixingDates[i] == today && i < n) { // might have been fixed try { double?pastFixing = IndexManager.Instance.getHistory(index.name())[fixingDates[i]]; if (pastFixing != null) { compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]); ++i; } else { // fall through and forecast } } catch (Exception) { // fall through and forecast } } // forward part using telescopic property in order // to avoid the evaluation of multiple forward fixings if (i < n) { Handle <YieldTermStructure> curve = index.forwardingTermStructure(); Utils.QL_REQUIRE(!curve.empty(), () => "null term structure set to this instance of" + index.name()); List <Date> dates = coupon_.valueDates(); double startDiscount = curve.link.discount(dates[i]); double endDiscount = curve.link.discount(dates[n]); compoundFactor *= startDiscount / endDiscount; } double rate = (compoundFactor - 1.0) / coupon_.accrualPeriod(); return(coupon_.gearing() * rate + coupon_.spread()); }
public OvernightIndexedSwap value() { Date startDate; if (effectiveDate_ != null) { startDate = effectiveDate_; } else { Date refDate = Settings.Instance.evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = calendar_.adjust(refDate); Date spotDate = calendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days)); startDate = spotDate + forwardStart_; if (forwardStart_.length() < 0) { startDate = calendar_.adjust(startDate, BusinessDayConvention.Preceding); } else { startDate = calendar_.adjust(startDate, BusinessDayConvention.Following); } } // OIS end of month default bool usedEndOfMonth = isDefaultEOM_ ? calendar_.isEndOfMonth(startDate) : endOfMonth_; Date endDate = terminationDate_; if (endDate == null) { if (usedEndOfMonth) { endDate = calendar_.advance(startDate, swapTenor_, BusinessDayConvention.ModifiedFollowing, usedEndOfMonth); } else { endDate = startDate + swapTenor_; } } Schedule schedule = new Schedule(startDate, endDate, new Period(paymentFrequency_), calendar_, BusinessDayConvention.ModifiedFollowing, BusinessDayConvention.ModifiedFollowing, rule_, usedEndOfMonth); double?usedFixedRate = fixedRate_; if (fixedRate_ == null) { OvernightIndexedSwap temp = new OvernightIndexedSwap(type_, nominal_, schedule, 0.0, // fixed rate fixedDayCount_, overnightIndex_, overnightSpread_); if (engine_ == null) { Handle <YieldTermStructure> disc = overnightIndex_.forwardingTermStructure(); Utils.QL_REQUIRE(!disc.empty(), () => "null term structure set to this instance of " + overnightIndex_.name()); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); temp.setPricingEngine(engine); } else { temp.setPricingEngine(engine_); } usedFixedRate = temp.fairRate(); } OvernightIndexedSwap ois = new OvernightIndexedSwap(type_, nominal_, schedule, usedFixedRate.Value, fixedDayCount_, overnightIndex_, overnightSpread_); if (engine_ == null) { Handle <YieldTermStructure> disc = overnightIndex_.forwardingTermStructure(); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); ois.setPricingEngine(engine); } else { ois.setPricingEngine(engine_); } return(ois); }
//! set up the interpolations for capPrice_ and floorPrice_ //! since we know ATM, and we have single flows, //! we can use put/call parity to extend the surfaces //! across all strikes protected override void performCalculations() { allStrikes_ = new List <double>(); int nMat = cfMaturities_.Count, ncK = cStrikes_.Count, nfK = fStrikes_.Count, nK = ncK + nfK; Matrix cP = new Matrix(nK, nMat), fP = new Matrix(nK, nMat); Handle <ZeroInflationTermStructure> zts = zii_.link.zeroInflationTermStructure(); Handle <YieldTermStructure> yts = this.nominalTermStructure(); Utils.QL_REQUIRE(!zts.empty(), () => "Zts is empty!!!"); Utils.QL_REQUIRE(!yts.empty(), () => "Yts is empty!!!"); for (int i = 0; i < nfK; i++) { allStrikes_.Add(fStrikes_[i]); for (int j = 0; j < nMat; j++) { Period mat = cfMaturities_[j]; double df = yts.link.discount(cpiOptionDateFromTenor(mat)); double atm_quote = zts.link.zeroRate(cpiOptionDateFromTenor(mat)); double atm = Math.Pow(1.0 + atm_quote, mat.length()); double S = atm * df; double K_quote = fStrikes_[i] / 100.0; double K = Math.Pow(1.0 + K_quote, mat.length()); cP[i, j] = fPrice_[i, j] + S - K * df; fP[i, j] = fPrice_[i, j]; } } for (int i = 0; i < ncK; i++) { allStrikes_.Add(cStrikes_[i]); for (int j = 0; j < nMat; j++) { Period mat = cfMaturities_[j]; double df = yts.link.discount(cpiOptionDateFromTenor(mat)); double atm_quote = zts.link.zeroRate(cpiOptionDateFromTenor(mat)); double atm = Math.Pow(1.0 + atm_quote, mat.length()); double S = atm * df; double K_quote = cStrikes_[i] / 100.0; double K = Math.Pow(1.0 + K_quote, mat.length()); cP[i + nfK, j] = cPrice_[i, j]; fP[i + nfK, j] = cPrice_[i, j] + K * df - S; } } // copy to store cPriceB_ = cP; fPriceB_ = fP; cfMaturityTimes_ = new List <double>(); for (int i = 0; i < cfMaturities_.Count; i++) { cfMaturityTimes_.Add(timeFromReference(cpiOptionDateFromTenor(cfMaturities_[i]))); } capPrice_ = interpolator2d_.interpolate(cfMaturityTimes_, cfMaturityTimes_.Count, allStrikes_, allStrikes_.Count, cPriceB_); capPrice_.enableExtrapolation(); floorPrice_ = interpolator2d_.interpolate(cfMaturityTimes_, cfMaturityTimes_.Count, allStrikes_, allStrikes_.Count, fPriceB_); floorPrice_.enableExtrapolation(); }
// Instrument interface public override void calculate() { Utils.QL_REQUIRE(!discountCurve_.empty(), () => "discounting term structure handle is empty"); results_.value = results_.cash = 0; results_.errorEstimate = null; Date refDate = discountCurve_.link.referenceDate(); Date settlementDate = settlementDate_; if (settlementDate_ == null) { settlementDate = refDate; } else { Utils.QL_REQUIRE(settlementDate >= refDate, () => "settlement date (" + settlementDate + ") before " + "discount curve reference date (" + refDate + ")"); } results_.valuationDate = npvDate_; if (npvDate_ == null) { results_.valuationDate = refDate; } else { Utils.QL_REQUIRE(npvDate_ >= refDate, () => "npv date (" + npvDate_ + ") before " + "discount curve reference date (" + refDate + ")"); } results_.npvDateDiscount = discountCurve_.link.discount(results_.valuationDate); int n = arguments_.legs.Count; results_.legNPV = new InitializedList <double?>(n); results_.legBPS = new InitializedList <double?>(n); results_.startDiscounts = new InitializedList <double?>(n); results_.endDiscounts = new InitializedList <double?>(n); bool includeRefDateFlows = includeSettlementDateFlows_.HasValue ? includeSettlementDateFlows_.Value : Settings.Instance.includeReferenceDateEvents; for (int i = 0; i < n; ++i) { try { YieldTermStructure discount_ref = discountCurve_.currentLink(); double npv = 0, bps = 0; CashFlows.npvbps(arguments_.legs[i], discount_ref, includeRefDateFlows, settlementDate, results_.valuationDate, out npv, out bps); results_.legNPV[i] = npv * arguments_.payer[i]; results_.legBPS[i] = bps * arguments_.payer[i]; if (!arguments_.legs[i].empty()) { Date d1 = CashFlows.startDate(arguments_.legs[i]); if (d1 >= refDate) { results_.startDiscounts[i] = discountCurve_.link.discount(d1); } else { results_.startDiscounts[i] = null; } Date d2 = CashFlows.maturityDate(arguments_.legs[i]); if (d2 >= refDate) { results_.endDiscounts[i] = discountCurve_.link.discount(d2); } else { results_.endDiscounts[i] = null; } } else { results_.startDiscounts[i] = null; results_.endDiscounts[i] = null; } } catch (Exception e) { Utils.QL_FAIL((i + 1) + " leg: " + e.Message); } results_.value += results_.legNPV[i]; } }
protected override void performCalculations() { Utils.QL_REQUIRE(!quote_.empty(), () => "null quote set"); NPV_ = quote_.link.value(); }