private IborCapletFloorletVolatilityCalibrationResult(IborCapletFloorletVolatilities volatilities, double chiSquare) { JodaBeanUtils.notNull(volatilities, "volatilities"); JodaBeanUtils.notNull(chiSquare, "chiSquare"); this.volatilities = volatilities; this.chiSquare = chiSquare; }
//------------------------------------------------------------------------- // print for debugging protected internal virtual void print(IborCapletFloorletVolatilityCalibrationResult res, DoubleArray strikes, double maxTime) { Console.WriteLine("Print in CapletStrippingSetup \n"); Console.WriteLine("Chi-square: " + res.ChiSquare); IborCapletFloorletVolatilities vols = res.Volatilities; const int nSamples = 51; const int nStrikeSamples = 51; Console.Write("\n"); for (int i = 0; i < nStrikeSamples; i++) { Console.Write("\t" + (strikes.get(0) + (strikes.get(strikes.size() - 1) - strikes.get(0)) * i) / (nStrikeSamples - 1)); } Console.Write("\n"); for (int index = 0; index < nSamples; index++) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final double t = 0.25 + index * maxTime / (nSamples - 1); double t = 0.25 + index * maxTime / (nSamples - 1); double forward = FWD_CURVE.yValue(t); Console.Write(t); for (int i = 0; i < nStrikeSamples; i++) { double strike = (strikes.get(0) + (strikes.get(strikes.size() - 1) - strikes.get(0)) * i) / (nStrikeSamples - 1); Console.Write("\t" + vols.volatility(t, strike, forward)); } Console.Write("\n"); } }
// sum of caplet prices which are not fixed private DoubleArray adjustedPrices(RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, int[] startIndex, int timeIndex, int nCaplets) { if (timeIndex == 0) { return(DoubleArray.filled(nCaplets, 1d)); } int currentStart = startIndex[timeIndex]; return(DoubleArray.of(nCaplets, n => (priceList[currentStart + n] - capList[currentStart + n].CapletFloorletPeriods.Where(p => !p.FixingDateTime.isAfter(prevExpiry)).Select(p => sabrPeriodPricer.presentValue(p, ratesProvider, vols).Amount).Sum()) / priceList[currentStart + n])); }
private System.Func <DoubleArray, DoubleArray> getPriceFunction(IList <ResolvedIborCapFloorLeg> capList, RatesProvider ratesProvider, System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction, InterpolatedNodalSurface baseSurface) { int nCaps = capList.Count; System.Func <DoubleArray, DoubleArray> priceFunction = (DoubleArray capletVols) => { IborCapletFloorletVolatilities newVols = volatilitiesFunction(baseSurface.withZValues(capletVols)); return(DoubleArray.of(nCaps, n => LegPricer.presentValue(capList[n], ratesProvider, newVols).Amount)); }; return(priceFunction); }
private System.Func <DoubleArray, DoubleMatrix> getJacobianFunction(IList <ResolvedIborCapFloorLeg> capList, RatesProvider ratesProvider, System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction, InterpolatedNodalSurface baseSurface) { int nCaps = capList.Count; int nNodes = baseSurface.ParameterCount; System.Func <DoubleArray, DoubleMatrix> jacobianFunction = (DoubleArray capletVols) => { IborCapletFloorletVolatilities newVols = volatilitiesFunction(baseSurface.withZValues(capletVols)); return(DoubleMatrix.ofArrayObjects(nCaps, nNodes, n => newVols.parameterSensitivity(LegPricer.presentValueSensitivityModelParamsVolatility(capList[n], ratesProvider, newVols).build()).Sensitivities.get(0).Sensitivity)); }; return(jacobianFunction); }
//------------------------------------------------------------------------- // price and vega function private System.Func <double, double[]> getValueVegaFunction(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry, int nodeIndex) { VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer; System.Func <double, double[]> priceAndVegaFunction = (double?x) => { IborCapletFloorletVolatilities newVols = vols.withParameter(nodeIndex, x.Value); double price = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, newVols).Amount).Sum(); PointSensitivities point = cap.CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValueSensitivityModelParamsVolatility(p, ratesProvider, newVols)).Aggregate((c1, c2) => c1.combinedWith(c2)).get().build(); CurrencyParameterSensitivities sensi = newVols.parameterSensitivity(point); double vega = sensi.Sensitivities.get(0).Sensitivity.get(nodeIndex); return(new double[] { price, vega }); }; return(priceAndVegaFunction); }
public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case -625639549: // volatilities this.volatilities = (IborCapletFloorletVolatilities)newValue; break; case -797918495: // chiSquare this.chiSquare = (double?)newValue.Value; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
//------------------------------------------------------------------------- // create complete lists of caps, volatilities, strikes, expiries protected internal virtual void reduceRawData(IborCapletFloorletVolatilityDefinition definition, RatesProvider ratesProvider, DoubleArray strikes, DoubleArray volatilityData, DoubleArray errors, LocalDate startDate, LocalDate endDate, SurfaceMetadata metadata, System.Func <Surface, IborCapletFloorletVolatilities> volatilityFunction, IList <double> timeList, IList <double> strikeList, IList <double> volList, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, IList <double> errorList) { int nStrikes = strikes.size(); for (int i = 0; i < nStrikes; ++i) { if (Double.isFinite(volatilityData.get(i))) { ResolvedIborCapFloorLeg capFloor = definition.createCap(startDate, endDate, strikes.get(i)).resolve(referenceData); capList.Add(capFloor); strikeList.Add(strikes.get(i)); volList.Add(volatilityData.get(i)); ConstantSurface constVolSurface = ConstantSurface.of(metadata, volatilityData.get(i)); IborCapletFloorletVolatilities vols = volatilityFunction(constVolSurface); timeList.Add(vols.relativeTime(capFloor.FinalFixingDateTime)); priceList.Add(pricer.presentValue(capFloor, ratesProvider, vols).Amount); errorList.Add(errors.get(i)); } } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value theta of the Ibor cap/floor product. /// <para> /// The present value of the product is the sensitivity value on the valuation date. /// </para> /// <para> /// The cap/floor leg and pay leg are typically in the same currency, thus the /// present value gamma is expressed as a single currency amount in most cases. /// /// </para> /// </summary> /// <param name="capFloor"> the Ibor cap/floor product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value theta </returns> public virtual MultiCurrencyAmount presentValueTheta(ResolvedIborCapFloor capFloor, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { CurrencyAmount pvCapFloorLeg = capFloorLegPricer.presentValueTheta(capFloor.CapFloorLeg, ratesProvider, volatilities); return(MultiCurrencyAmount.of(pvCapFloorLeg)); }
protected internal override void validate(IborCapletFloorletVolatilities volatilities) { ArgChecker.isTrue(volatilities is NormalIborCapletFloorletVolatilities, "volatilities must be normal volatilities"); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value theta of the Ibor caplet/floorlet period. /// <para> /// The present value theta is given by the minus of the present value sensitivity to the {@code timeToExpiry} /// parameter of the model. /// /// </para> /// </summary> /// <param name="period"> the Ibor caplet/floorlet period </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value theta </returns> public virtual CurrencyAmount presentValueTheta(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(volatilities); double expiry = volatilities.relativeTime(period.FixingDateTime); Currency currency = period.Currency; if (expiry < 0d) { // Option has expired already return(CurrencyAmount.of(currency, 0d)); } double forward = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation); double strike = period.Strike; double volatility = volatilities.volatility(expiry, strike, forward); PutCall putCall = period.PutCall; double df = ratesProvider.discountFactor(currency, period.PaymentDate); double priceTheta = df * period.YearFraction * volatilities.priceTheta(expiry, putCall, strike, forward, volatility); return(CurrencyAmount.of(currency, priceTheta * period.Notional)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the implied volatility of the Ibor caplet/floorlet. /// </summary> /// <param name="period"> the Ibor caplet/floorlet period </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the implied volatility </returns> public virtual double impliedVolatility(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(volatilities); double expiry = volatilities.relativeTime(period.FixingDateTime); ArgChecker.isTrue(expiry >= 0d, "Option must be before expiry to compute an implied volatility"); double forward = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation); double strike = period.Strike; return(volatilities.volatility(expiry, strike, forward)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the Ibor cap/floor trade. /// <para> /// The present value of the trade is the value on the valuation date. /// </para> /// <para> /// The cap/floor leg and pay leg are typically in the same currency, thus the /// present value gamma is expressed as a single currency amount in most cases. /// /// </para> /// </summary> /// <param name="trade"> the Ibor cap/floor trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value </returns> public virtual MultiCurrencyAmount presentValue(ResolvedIborCapFloorTrade trade, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { MultiCurrencyAmount pvProduct = productPricer.presentValue(trade.Product, ratesProvider, volatilities); if (!trade.Premium.Present) { return(pvProduct); } CurrencyAmount pvPremium = paymentPricer.presentValue(trade.Premium.get(), ratesProvider); return(pvProduct.plus(pvPremium)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value volatility sensitivity of the Ibor cap/floor product. /// <para> /// The present value volatility sensitivity of the product is the sensitivity /// of the present value to the volatility values. /// /// </para> /// </summary> /// <param name="trade"> the Ibor cap/floor trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(ResolvedIborCapFloorTrade trade, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { return(productPricer.presentValueSensitivityModelParamsVolatility(trade.Product, ratesProvider, volatilities)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the Ibor cap/floor product. /// <para> /// The present value of the product is the value on the valuation date. /// </para> /// <para> /// The cap/floor leg and pay leg are typically in the same currency, thus the /// present value gamma is expressed as a single currency amount in most cases. /// /// </para> /// </summary> /// <param name="capFloor"> the Ibor cap/floor product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value </returns> public virtual MultiCurrencyAmount presentValue(ResolvedIborCapFloor capFloor, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { CurrencyAmount pvCapFloorLeg = capFloorLegPricer.presentValue(capFloor.CapFloorLeg, ratesProvider, volatilities); if (!capFloor.PayLeg.Present) { return(MultiCurrencyAmount.of(pvCapFloorLeg)); } CurrencyAmount pvPayLeg = payLegPricer.presentValue(capFloor.PayLeg.get(), ratesProvider); return(MultiCurrencyAmount.of(pvCapFloorLeg).plus(pvPayLeg)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the current cash of the Ibor cap/floor leg. /// </summary> /// <param name="capFloorLeg"> the Ibor cap/floor leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the current cash </returns> public virtual CurrencyAmount currentCash(ResolvedIborCapFloorLeg capFloorLeg, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(ratesProvider, volatilities); return(capFloorLeg.CapletFloorletPeriods.Where(period => period.PaymentDate.Equals(ratesProvider.ValuationDate)).Select(period => periodPricer.presentValue(period, ratesProvider, volatilities)).Aggregate((c1, c2) => c1.plus(c2)).orElse(CurrencyAmount.zero(capFloorLeg.Currency))); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value volatility sensitivity of the Ibor cap/floor leg. /// <para> /// The present value volatility sensitivity of the leg is the sensitivity /// of the present value to the volatility values. /// /// </para> /// </summary> /// <param name="capFloorLeg"> the Ibor cap/floor leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value volatility sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(ResolvedIborCapFloorLeg capFloorLeg, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(ratesProvider, volatilities); return(capFloorLeg.CapletFloorletPeriods.Select(period => periodPricer.presentValueSensitivityModelParamsVolatility(period, ratesProvider, volatilities)).Aggregate((c1, c2) => c1.combinedWith(c2)).get()); }
/// <summary> /// Validate the volatilities provider. /// <para> /// This validate method should be overridden such that a correct implementation of /// {@code IborCapletFloorletVolatilities} is used for pricing. /// /// </para> /// </summary> /// <param name="volatilities"> the volatilities </param> protected internal virtual void validate(IborCapletFloorletVolatilities volatilities) { }
/// <summary> /// Obtains an instance of root-finding result. /// </summary> /// <param name="volatilities"> the caplet volatilities </param> /// <returns> the instance </returns> public static IborCapletFloorletVolatilityCalibrationResult ofRootFind(IborCapletFloorletVolatilities volatilities) { return(new IborCapletFloorletVolatilityCalibrationResult(volatilities, 0d)); }
//------------------------------------------------------------------------- /// <summary> /// Obtains an instance of least square result. /// </summary> /// <param name="volatilities"> the caplet volatilities </param> /// <param name="chiSquare"> the chi-square value </param> /// <returns> the instance </returns> public static IborCapletFloorletVolatilityCalibrationResult ofLeastSquare(IborCapletFloorletVolatilities volatilities, double chiSquare) { return(new IborCapletFloorletVolatilityCalibrationResult(volatilities, chiSquare)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value rates sensitivity of the Ibor cap/floor product. /// <para> /// The present value rates sensitivity of the product is the sensitivity /// of the present value to the underlying curves. /// /// </para> /// </summary> /// <param name="capFloor"> the Ibor cap/floor product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityRates(ResolvedIborCapFloor capFloor, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { PointSensitivityBuilder pvSensiCapFloorLeg = capFloorLegPricer.presentValueSensitivityRates(capFloor.CapFloorLeg, ratesProvider, volatilities); if (!capFloor.PayLeg.Present) { return(pvSensiCapFloorLeg); } PointSensitivityBuilder pvSensiPayLeg = payLegPricer.presentValueSensitivity(capFloor.PayLeg.get(), ratesProvider); return(pvSensiCapFloorLeg.combinedWith(pvSensiPayLeg)); }
// sum of caplet prices which are already fixed private double priceFixed(ResolvedIborCapFloorLeg cap, RatesProvider ratesProvider, IborCapletFloorletVolatilities vols, ZonedDateTime prevExpiry) { VolatilityIborCapletFloorletPeriodPricer periodPricer = LegPricer.PeriodPricer; return(cap.CapletFloorletPeriods.Where(p => !p.FixingDateTime.isAfter(prevExpiry)).Select(p => periodPricer.presentValue(p, ratesProvider, vols).Amount).Sum()); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value volatility sensitivity of the Ibor cap/floor product. /// <para> /// The present value volatility sensitivity of the product is the sensitivity /// of the present value to the volatility values. /// /// </para> /// </summary> /// <param name="capFloor"> the Ibor cap/floor product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(ResolvedIborCapFloor capFloor, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { return(capFloorLegPricer.presentValueSensitivityModelParamsVolatility(capFloor.CapFloorLeg, ratesProvider, volatilities)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value delta of the Ibor cap/floor leg. /// <para> /// The present value delta of the leg is the sensitivity value on the valuation date. /// The result is returned using the payment currency of the leg. /// /// </para> /// </summary> /// <param name="capFloorLeg"> the Ibor cap/floor leg </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value delta </returns> public virtual CurrencyAmount presentValueDelta(ResolvedIborCapFloorLeg capFloorLeg, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(ratesProvider, volatilities); return(capFloorLeg.CapletFloorletPeriods.Select(period => periodPricer.presentValueDelta(period, ratesProvider, volatilities)).Aggregate((c1, c2) => c1.plus(c2)).get()); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value rates sensitivity of the Ibor cap/floor trade. /// <para> /// The present value rates sensitivity of the trade is the sensitivity /// of the present value to the underlying curves. /// /// </para> /// </summary> /// <param name="trade"> the Ibor cap/floor trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivities presentValueSensitivityRates(ResolvedIborCapFloorTrade trade, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { PointSensitivityBuilder pvSensiProduct = productPricer.presentValueSensitivityRates(trade.Product, ratesProvider, volatilities); if (!trade.Premium.Present) { return(pvSensiProduct.build()); } PointSensitivityBuilder pvSensiPremium = paymentPricer.presentValueSensitivity(trade.Premium.get(), ratesProvider); return(pvSensiProduct.combinedWith(pvSensiPremium).build()); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value volatility sensitivity of the Ibor caplet/floorlet. /// <para> /// The present value volatility sensitivity of the caplet/floorlet is the sensitivity /// of the present value to the implied volatility. /// </para> /// <para> /// The sensitivity to the implied volatility is also called vega. /// /// </para> /// </summary> /// <param name="period"> the Ibor caplet/floorlet period </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the point sensitivity to the volatility </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(volatilities); double expiry = volatilities.relativeTime(period.FixingDateTime); double strike = period.Strike; Currency currency = period.Currency; if (expiry <= 0d) { // Option has expired already or at expiry return(PointSensitivityBuilder.none()); } double forward = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation); double volatility = volatilities.volatility(expiry, strike, forward); PutCall putCall = period.PutCall; double df = ratesProvider.discountFactor(currency, period.PaymentDate); double vega = df * period.YearFraction * volatilities.priceVega(expiry, putCall, strike, forward, volatility); return(IborCapletFloorletSensitivity.of(volatilities.Name, expiry, strike, forward, currency, vega * period.Notional)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the current cash of the Ibor cap/floor trade. /// </summary> /// <param name="trade"> the Ibor cap/floor trade </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the current cash </returns> public virtual MultiCurrencyAmount currentCash(ResolvedIborCapFloorTrade trade, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { MultiCurrencyAmount ccProduct = productPricer.currentCash(trade.Product, ratesProvider, volatilities); if (!trade.Premium.Present) { return(ccProduct); } Payment premium = trade.Premium.get(); if (premium.Date.Equals(ratesProvider.ValuationDate)) { ccProduct = ccProduct.plus(premium.Currency, premium.Amount); } return(ccProduct); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value rates sensitivity of the Ibor caplet/floorlet. /// <para> /// The present value rates sensitivity of the caplet/floorlet is the sensitivity /// of the present value to the underlying curves. /// /// </para> /// </summary> /// <param name="period"> the Ibor caplet/floorlet period </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value curve sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityRates(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(volatilities); Currency currency = period.Currency; if (ratesProvider.ValuationDate.isAfter(period.PaymentDate)) { return(PointSensitivityBuilder.none()); } double expiry = volatilities.relativeTime(period.FixingDateTime); PutCall putCall = period.PutCall; double strike = period.Strike; double indexRate = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation); PointSensitivityBuilder dfSensi = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(period.PaymentDate); if (expiry < 0d) { // Option has expired already double sign = putCall.Call ? 1d : -1d; double payoff = Math.Max(sign * (indexRate - strike), 0d); return(dfSensi.multipliedBy(payoff * period.YearFraction * period.Notional)); } PointSensitivityBuilder indexRateSensiSensi = ratesProvider.iborIndexRates(period.Index).ratePointSensitivity(period.IborRate.Observation); double volatility = volatilities.volatility(expiry, strike, indexRate); double df = ratesProvider.discountFactor(currency, period.PaymentDate); double factor = period.Notional * period.YearFraction; double fwdPv = factor * volatilities.price(expiry, putCall, strike, indexRate, volatility); double fwdDelta = factor * volatilities.priceDelta(expiry, putCall, strike, indexRate, volatility); return(dfSensi.multipliedBy(fwdPv).combinedWith(indexRateSensiSensi.multipliedBy(fwdDelta * df))); }
//------------------------------------------------------------------------- protected internal virtual void validate(RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { ArgChecker.isTrue(volatilities.ValuationDate.Equals(ratesProvider.ValuationDate), "volatility and rate data must be for the same date"); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the Ibor caplet/floorlet period. /// <para> /// The result is expressed using the currency of the period. /// /// </para> /// </summary> /// <param name="period"> the Ibor caplet/floorlet period </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the volatilities </param> /// <returns> the present value </returns> public virtual CurrencyAmount presentValue(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { validate(volatilities); Currency currency = period.Currency; if (ratesProvider.ValuationDate.isAfter(period.PaymentDate)) { return(CurrencyAmount.of(currency, 0d)); } double expiry = volatilities.relativeTime(period.FixingDateTime); double df = ratesProvider.discountFactor(currency, period.PaymentDate); PutCall putCall = period.PutCall; double strike = period.Strike; double indexRate = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation); if (expiry < 0d) { // Option has expired already double sign = putCall.Call ? 1d : -1d; double payoff = Math.Max(sign * (indexRate - strike), 0d); return(CurrencyAmount.of(currency, df * payoff * period.YearFraction * period.Notional)); } double volatility = volatilities.volatility(expiry, strike, indexRate); double price = df * period.YearFraction * volatilities.price(expiry, putCall, strike, indexRate, volatility); return(CurrencyAmount.of(currency, price * period.Notional)); }