public virtual void sabrParameterByExpiryTenor_surfaceName() { SurfaceMetadata test = Surfaces.sabrParameterByExpiryTenor(SURFACE_NAME, ACT_360, ValueType.SABR_BETA); SurfaceMetadata expected = DefaultSurfaceMetadata.builder().surfaceName(SURFACE_NAME).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.YEAR_FRACTION).zValueType(ValueType.SABR_BETA).dayCount(ACT_360).build(); assertEquals(test, expected); }
public virtual InterpolatedNodalSurface localVolatilityFromPrice(Surface callPriceSurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate) { double[][] stateValue = new double[nSteps + 1][]; double[] df = new double[nSteps]; IList <DoubleMatrix> probability = new List <DoubleMatrix>(nSteps); int nTotal = (nSteps - 1) * (nSteps - 1) + 1; double[] timeRes = new double[nTotal]; double[] spotRes = new double[nTotal]; double[] volRes = new double[nTotal]; // uniform grid based on TrigeorgisLatticeSpecification, using reference values double refPrice = callPriceSurface.zValue(maxTime, spot) * Math.Exp(interestRate(maxTime) * maxTime); double refForward = spot * Math.Exp((interestRate(maxTime) - dividendRate(maxTime)) * maxTime); double refVolatility = BlackFormulaRepository.impliedVolatility(refPrice, refForward, spot, maxTime, true); double dt = maxTime / nSteps; double dx = refVolatility * Math.Sqrt(3d * dt); double upFactor = Math.Exp(dx); double downFactor = Math.Exp(-dx); double[] adSec = new double[2 * nSteps + 1]; double[] assetPrice = new double[2 * nSteps + 1]; for (int i = nSteps; i > -1; --i) { if (i == 0) { resolveFirstLayer(interestRate, dividendRate, nTotal, dt, spot, adSec, assetPrice, timeRes, spotRes, volRes, df, stateValue, probability); } else { double time = dt * i; double zeroRate = interestRate(time); double zeroDividendRate = dividendRate(time); int nNodes = 2 * i + 1; double[] assetPriceLocal = new double[nNodes]; double[] callOptionPrice = new double[nNodes]; double[] putOptionPrice = new double[nNodes]; int position = i - 1; double assetTmp = spot * Math.Pow(upFactor, i); // call options for upper half nodes for (int j = nNodes - 1; j > position - 1; --j) { assetPriceLocal[j] = assetTmp; callOptionPrice[j] = callPriceSurface.zValue(time, assetPriceLocal[j]); assetTmp *= downFactor; } // put options for lower half nodes assetTmp = spot * Math.Pow(downFactor, i); for (int j = 0; j < position + 2; ++j) { assetPriceLocal[j] = assetTmp; putOptionPrice[j] = callPriceSurface.zValue(time, assetPriceLocal[j]) - spot * Math.Exp(-zeroDividendRate * time) + Math.Exp(-zeroRate * time) * assetPriceLocal[j]; assetTmp *= upFactor; } resolveLayer(interestRate, dividendRate, i, nTotal, position, dt, zeroRate, zeroDividendRate, callOptionPrice, putOptionPrice, adSec, assetPrice, assetPriceLocal, timeRes, spotRes, volRes, df, stateValue, probability); } } SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + callPriceSurface.Name)).build(); return(InterpolatedNodalSurface.ofUnsorted(metadata, DoubleArray.ofUnsafe(timeRes), DoubleArray.ofUnsafe(spotRes), DoubleArray.ofUnsafe(volRes), interpolator)); }
public virtual void blackVolatilityByExpiryLogMoneyness_surfaceName() { SurfaceMetadata test = Surfaces.blackVolatilityByExpiryLogMoneyness(SURFACE_NAME, ACT_360); SurfaceMetadata expected = DefaultSurfaceMetadata.builder().surfaceName(SURFACE_NAME).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.LOG_MONEYNESS).zValueType(ValueType.BLACK_VOLATILITY).dayCount(ACT_360).build(); assertEquals(test, expected); }
//------------------------------------------------------------------------- public virtual void normalVolatilityByExpiryStrike_string() { SurfaceMetadata test = Surfaces.normalVolatilityByExpiryStrike(NAME, ACT_360); SurfaceMetadata expected = DefaultSurfaceMetadata.builder().surfaceName(SURFACE_NAME).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.NORMAL_VOLATILITY).dayCount(ACT_360).build(); assertEquals(test, expected); }
public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case -450004177: // metadata this.metadata_Renamed = (SurfaceMetadata)newValue; break; case 1681280954: // xValues this.xValues_Renamed = (DoubleArray)newValue; break; case -1726182661: // yValues this.yValues_Renamed = (DoubleArray)newValue; break; case -838678980: // zValues this.zValues_Renamed = (DoubleArray)newValue; break; case 2096253127: // interpolator this.interpolator_Renamed = (SurfaceInterpolator)newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
// basic validation private void validateInputs(SurfaceMetadata metadata, DoubleArray xValues, DoubleArray yValues, DoubleArray zValues, SurfaceInterpolator interpolator) { ArgChecker.notNull(metadata, "metadata"); ArgChecker.notNull(xValues, "times"); ArgChecker.notNull(yValues, "values"); ArgChecker.notNull(interpolator, "interpolator"); if (xValues.size() < 2) { throw new System.ArgumentException("Length of x-values must be at least 2"); } if (xValues.size() != yValues.size()) { throw new System.ArgumentException("Length of x-values and y-values must match"); } if (xValues.size() != zValues.size()) { throw new System.ArgumentException("Length of x-values and z-values must match"); } metadata.ParameterMetadata.ifPresent(@params => { if (xValues.size() != @params.size()) { throw new System.ArgumentException("Length of x-values and parameter metadata must match when metadata present"); } }); }
public virtual void normalVolatilityByExpirySimpleMoneyness_surfaceName() { SurfaceMetadata test = Surfaces.normalVolatilityByExpirySimpleMoneyness(SURFACE_NAME, ACT_360, MoneynessType.PRICE); SurfaceMetadata expected = DefaultSurfaceMetadata.builder().surfaceName(SURFACE_NAME).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.SIMPLE_MONEYNESS).zValueType(ValueType.NORMAL_VOLATILITY).dayCount(ACT_360).addInfo(SurfaceInfoType.MONEYNESS_TYPE, MoneynessType.PRICE).build(); assertEquals(test, expected); }
public virtual DeformedSurface localVolatilityFromPrice(Surface callPriceSurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate) { System.Func <DoublesPair, ValueDerivatives> func = (DoublesPair x) => { double t = x.First; double k = x.Second; double r = interestRate(t); double q = dividendRate(t); double price = callPriceSurface.zValue(t, k); DoubleArray priceSensi = callPriceSurface.zValueParameterSensitivity(t, k).Sensitivity; double divT = FIRST_DERIV.differentiate(u => callPriceSurface.zValue(u, k)).apply(t); DoubleArray divTSensi = FIRST_DERIV_SENSI.differentiate(u => callPriceSurface.zValueParameterSensitivity(u.get(0), k).Sensitivity).apply(DoubleArray.of(t)).column(0); double divK = FIRST_DERIV.differentiate(l => callPriceSurface.zValue(t, l)).apply(k); DoubleArray divKSensi = FIRST_DERIV_SENSI.differentiate(l => callPriceSurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0); double divK2 = SECOND_DERIV.differentiate(l => callPriceSurface.zValue(t, l)).apply(k); DoubleArray divK2Sensi = SECOND_DERIV_SENSI.differentiateNoCross(l => callPriceSurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0); double var = 2d * (divT + q * price + (r - q) * k * divK) / (k * k * divK2); if (var < 0d) { throw new System.ArgumentException("Negative variance"); } double localVol = Math.Sqrt(var); double factor = 1d / (localVol * k * k * divK2); DoubleArray localVolSensi = divTSensi.multipliedBy(factor).plus(divKSensi.multipliedBy((r - q) * k * factor)).plus(priceSensi.multipliedBy(q * factor)).plus(divK2Sensi.multipliedBy(-0.5 * localVol / divK2)); return(ValueDerivatives.of(localVol, localVolSensi)); }; SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + callPriceSurface.Name)).build(); return(DeformedSurface.of(metadata, callPriceSurface, func)); }
/// <summary> /// Restricted copy constructor. </summary> /// <param name="beanToCopy"> the bean to copy from, not null </param> internal Builder(InterpolatedNodalSurface beanToCopy) { this.metadata_Renamed = beanToCopy.Metadata; this.xValues_Renamed = beanToCopy.XValues; this.yValues_Renamed = beanToCopy.YValues; this.zValues_Renamed = beanToCopy.ZValues; this.interpolator_Renamed = beanToCopy.Interpolator; }
private DeformedSurface(SurfaceMetadata metadata, Surface originalSurface, System.Func <DoublesPair, ValueDerivatives> deformationFunction) { JodaBeanUtils.notNull(metadata, "metadata"); JodaBeanUtils.notNull(originalSurface, "originalSurface"); JodaBeanUtils.notNull(deformationFunction, "deformationFunction"); this.metadata = metadata; this.originalSurface = originalSurface; this.deformationFunction = deformationFunction; }
//------------------------------------------------------------------------- public virtual InterpolatedNodalSurface localVolatilityFromImpliedVolatility(Surface impliedVolatilitySurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate) { System.Func <DoublesPair, double> surface = (DoublesPair tk) => { return(impliedVolatilitySurface.zValue(tk)); }; ImmutableList <double[]> localVolData = calibrate(surface, spot, interestRate, dividendRate).First; SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.Name)).build(); return(InterpolatedNodalSurface.ofUnsorted(metadata, DoubleArray.ofUnsafe(localVolData.get(0)), DoubleArray.ofUnsafe(localVolData.get(1)), DoubleArray.ofUnsafe(localVolData.get(2)), interpolator)); }
static BlackSwaptionExpiryTenorVolatilitiesTest() { IList<SwaptionSurfaceExpiryTenorParameterMetadata> list = new List<SwaptionSurfaceExpiryTenorParameterMetadata>(); int nData = TIME.size(); for (int i = 0; i < nData; ++i) { SwaptionSurfaceExpiryTenorParameterMetadata parameterMetadata = SwaptionSurfaceExpiryTenorParameterMetadata.of(TIME.get(i), TENOR.get(i)); list.Add(parameterMetadata); } METADATA = Surfaces.blackVolatilityByExpiryTenor("GOVT1-SWAPTION-VOL", ACT_365F).withParameterMetadata(list); }
//------------------------------------------------------------------------- public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider) { ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime"); ArgChecker.isTrue(definition is SabrIborCapletFloorletVolatilityCalibrationDefinition, "definition should be SabrIborCapletFloorletVolatilityCalibrationDefinition"); SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition = (SabrIborCapletFloorletVolatilityCalibrationDefinition)definition; // unpack cap data, create node caps IborIndex index = sabrDefinition.Index; LocalDate calibrationDate = calibrationDateTime.toLocalDate(); LocalDate baseDate = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData); LocalDate startDate = baseDate.plus(index.Tenor); System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(sabrDefinition, calibrationDateTime, capFloorData); SurfaceMetadata metadata = sabrDefinition.createMetadata(capFloorData); IList <Period> expiries = capFloorData.Expiries; DoubleArray strikes = capFloorData.Strikes; int nExpiries = expiries.Count; IList <double> timeList = new List <double>(); IList <double> strikeList = new List <double>(); IList <double> volList = new List <double>(); IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>(); IList <double> priceList = new List <double>(); IList <double> errorList = new List <double>(); DoubleMatrix errorMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d)); int[] startIndex = new int[nExpiries + 1]; for (int i = 0; i < nExpiries; ++i) { LocalDate endDate = baseDate.plus(expiries[i]); DoubleArray volatilityForTime = capFloorData.Data.row(i); DoubleArray errorForTime = errorMatrix.row(i); reduceRawData(sabrDefinition, ratesProvider, capFloorData.Strikes, volatilityForTime, errorForTime, startDate, endDate, metadata, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList); startIndex[i + 1] = volList.Count; ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]); } // create initial caplet vol surface IList <CurveMetadata> metadataList = sabrDefinition.createSabrParameterMetadata(); DoubleArray initialValues = sabrDefinition.createFullInitialValues(); IList <Curve> curveList = sabrDefinition.createSabrParameterCurve(metadataList, initialValues); SabrParameters sabrParamsInitial = SabrParameters.of(curveList[0], curveList[1], curveList[2], curveList[3], sabrDefinition.ShiftCurve, sabrDefinition.SabrVolatilityFormula); SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(sabrDefinition.Name, index, calibrationDateTime, sabrParamsInitial); // solve least square UncoupledParameterTransforms transform = new UncoupledParameterTransforms(initialValues, sabrDefinition.createFullTransform(TRANSFORMS), new BitArray()); System.Func <DoubleArray, DoubleArray> valueFunction = createPriceFunction(sabrDefinition, ratesProvider, vols, capList, priceList); System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(sabrDefinition, ratesProvider, vols, capList, priceList, index.Currency); NonLinearTransformFunction transFunc = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform); LeastSquareResults res = solver.solve(DoubleArray.filled(priceList.Count, 1d), DoubleArray.copyOf(errorList), transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(initialValues)); LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform); vols = updateParameters(sabrDefinition, vols, resTransform.ModelParameters); return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, res.ChiSq)); }
static NormalSwaptionExpirySimpleMoneynessVolatilitiesTest() { IList <SwaptionSurfaceExpirySimpleMoneynessParameterMetadata> list = new List <SwaptionSurfaceExpirySimpleMoneynessParameterMetadata>(); int nData = TIME.size(); for (int i = 0; i < nData; ++i) { SwaptionSurfaceExpirySimpleMoneynessParameterMetadata parameterMetadata = SwaptionSurfaceExpirySimpleMoneynessParameterMetadata.of(TIME.get(i), SIMPLE_MONEYNESS.get(i)); list.Add(parameterMetadata); } METADATA = Surfaces.normalVolatilityByExpirySimpleMoneyness("GOVT1-SWAPTION-VOL", ACT_365F, MoneynessType.RATES).withParameterMetadata(list); }
static ShiftedBlackIborCapletFloorletExpiryStrikeVolatilitiesTest() { IList <GenericVolatilitySurfaceYearFractionParameterMetadata> list = new List <GenericVolatilitySurfaceYearFractionParameterMetadata>(); int nData = TIME.size(); for (int i = 0; i < nData; ++i) { GenericVolatilitySurfaceYearFractionParameterMetadata parameterMetadata = GenericVolatilitySurfaceYearFractionParameterMetadata.of(TIME.get(i), SimpleStrike.of(STRIKE.get(i))); list.Add(parameterMetadata); } METADATA = Surfaces.blackVolatilityByExpiryStrike("CAP_VOL", ACT_365F).withParameterMetadata(list); }
static BlackBondFutureOptionMarginedProductPricerTest() { IList <GenericVolatilitySurfaceYearFractionParameterMetadata> list = new List <GenericVolatilitySurfaceYearFractionParameterMetadata>(); int nData = TIME.size(); for (int i = 0; i < nData; ++i) { GenericVolatilitySurfaceYearFractionParameterMetadata parameterMetadata = GenericVolatilitySurfaceYearFractionParameterMetadata.of(TIME.get(i), LogMoneynessStrike.of(MONEYNESS.get(i))); list.Add(parameterMetadata); } METADATA = DefaultSurfaceMetadata.builder().surfaceName(SurfaceName.of("GOVT1-BOND-FUT-VOL")).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.LOG_MONEYNESS).zValueType(ValueType.BLACK_VOLATILITY).parameterMetadata(list).dayCount(ACT_365F).build(); }
static NormalSwaptionExpiryStrikeVolatilitiesTest() { IList <SwaptionSurfaceExpiryStrikeParameterMetadata> list = new List <SwaptionSurfaceExpiryStrikeParameterMetadata>(); int nData = TIME.size(); for (int i = 0; i < nData; ++i) { SwaptionSurfaceExpiryStrikeParameterMetadata parameterMetadata = SwaptionSurfaceExpiryStrikeParameterMetadata.of(TIME.get(i), STRIKE.get(i)); list.Add(parameterMetadata); } METADATA = Surfaces.normalVolatilityByExpiryStrike("GOVT1-SWAPTION-VOL", ACT_365F).withParameterMetadata(list); }
public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case -450004177: // metadata this.metadata = (SurfaceMetadata)newValue; break; case -719790825: // zValue this.zValue = (double?)newValue.Value; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
public virtual void test_presentValueSensitivityRatesStickyModel_stickyStrike() { SwaptionVolatilities volSabr = SwaptionSabrRateVolatilityDataSet.getVolatilitiesUsd(VAL_DATE, false); double impliedVol = SWAPTION_PRICER.impliedVolatility(SWAPTION_REC_LONG, RATE_PROVIDER, volSabr); SurfaceMetadata blackMeta = Surfaces.blackVolatilityByExpiryTenor("CST", VOLS.DayCount); SwaptionVolatilities volCst = BlackSwaptionExpiryTenorVolatilities.of(VOLS.Convention, VOLS.ValuationDateTime, ConstantSurface.of(blackMeta, impliedVol)); // To obtain a constant volatility surface which create a sticky strike sensitivity PointSensitivityBuilder pointRec = SWAPTION_PRICER.presentValueSensitivityRatesStickyStrike(SWAPTION_REC_LONG, RATE_PROVIDER, volSabr); CurrencyParameterSensitivities computedRec = RATE_PROVIDER.parameterSensitivity(pointRec.build()); CurrencyParameterSensitivities expectedRec = FD_CAL.sensitivity(RATE_PROVIDER, (p) => SWAPTION_PRICER.presentValue(SWAPTION_REC_LONG, (p), volCst)); assertTrue(computedRec.equalWithTolerance(expectedRec, NOTIONAL * FD_EPS * 100d)); PointSensitivityBuilder pointPay = SWAPTION_PRICER.presentValueSensitivityRatesStickyStrike(SWAPTION_PAY_SHORT, RATE_PROVIDER, volSabr); CurrencyParameterSensitivities computedPay = RATE_PROVIDER.parameterSensitivity(pointPay.build()); CurrencyParameterSensitivities expectedPay = FD_CAL.sensitivity(RATE_PROVIDER, (p) => SWAPTION_PRICER.presentValue(SWAPTION_PAY_SHORT, (p), volCst)); assertTrue(computedPay.equalWithTolerance(expectedPay, NOTIONAL * FD_EPS * 100d)); }
public virtual DeformedSurface localVolatilityFromImpliedVolatility(Surface impliedVolatilitySurface, double spot, System.Func <double, double> interestRate, System.Func <double, double> dividendRate) { System.Func <DoublesPair, ValueDerivatives> func = (DoublesPair x) => { double t = x.First; double k = x.Second; double r = interestRate(t); double q = dividendRate(t); double vol = impliedVolatilitySurface.zValue(t, k); DoubleArray volSensi = impliedVolatilitySurface.zValueParameterSensitivity(t, k).Sensitivity; double divT = FIRST_DERIV.differentiate(u => impliedVolatilitySurface.zValue(u, k)).apply(t); DoubleArray divTSensi = FIRST_DERIV_SENSI.differentiate(u => impliedVolatilitySurface.zValueParameterSensitivity(u.get(0), k).Sensitivity).apply(DoubleArray.of(t)).column(0); double localVol; DoubleArray localVolSensi = DoubleArray.of(); if (k < SMALL) { localVol = Math.Sqrt(vol * vol + 2 * vol * t * (divT)); localVolSensi = volSensi.multipliedBy((vol + t * divT) / localVol).plus(divTSensi.multipliedBy(vol * t / localVol)); } else { double divK = FIRST_DERIV.differentiate(l => impliedVolatilitySurface.zValue(t, l)).apply(k); DoubleArray divKSensi = FIRST_DERIV_SENSI.differentiate(l => impliedVolatilitySurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0); double divK2 = SECOND_DERIV.differentiate(l => impliedVolatilitySurface.zValue(t, l)).apply(k); DoubleArray divK2Sensi = SECOND_DERIV_SENSI.differentiateNoCross(l => impliedVolatilitySurface.zValueParameterSensitivity(t, l.get(0)).Sensitivity).apply(DoubleArray.of(k)).column(0); double rq = r - q; double h1 = (Math.Log(spot / k) + (rq + 0.5 * vol * vol) * t) / vol; double h2 = h1 - vol * t; double den = 1d + 2d * h1 * k * divK + k * k * (h1 * h2 * divK * divK + t * vol * divK2); double var = (vol * vol + 2d * vol * t * (divT + k * rq * divK)) / den; if (var < 0d) { throw new System.ArgumentException("Negative variance"); } localVol = Math.Sqrt(var); localVolSensi = volSensi.multipliedBy(localVol * k * h2 * divK * (1d + 0.5 * k * h2 * divK) / vol / den + 0.5 * localVol * Math.Pow(k * h1 * divK, 2) / vol / den + (vol + divT * t + rq * t * k * divK) / (localVol * den) - 0.5 * divK2 * localVol * k * k * t / den).plus(divKSensi.multipliedBy((vol * t * rq * k / localVol - localVol * k * h1 * (1d + k * h2 * divK)) / den)).plus(divTSensi.multipliedBy(vol * t / (localVol * den))).plus(divK2Sensi.multipliedBy(-0.5 * vol * localVol * k * k * t / den)); } return(ValueDerivatives.of(localVol, localVolSensi)); }; SurfaceMetadata metadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.STRIKE).zValueType(ValueType.LOCAL_VOLATILITY).surfaceName(SurfaceName.of("localVol_" + impliedVolatilitySurface.Name)).build(); return(DeformedSurface.of(metadata, impliedVolatilitySurface, func)); }
// constructor that sorts (artificial boolean flag) private InterpolatedNodalSurface(SurfaceMetadata metadata, DoubleArray xValues, DoubleArray yValues, DoubleArray zValues, SurfaceInterpolator interpolator, bool sort) { validateInputs(metadata, xValues, yValues, zValues, interpolator); // sort inputs IDictionary <DoublesPair, ObjDoublePair <ParameterMetadata> > sorted = new SortedDictionary <DoublesPair, ObjDoublePair <ParameterMetadata> >(); for (int i = 0; i < xValues.size(); i++) { ParameterMetadata pm = metadata.getParameterMetadata(i); sorted[DoublesPair.of(xValues.get(i), yValues.get(i))] = ObjDoublePair.of(pm, zValues.get(i)); } double[] sortedX = new double[sorted.Count]; double[] sortedY = new double[sorted.Count]; double[] sortedZ = new double[sorted.Count]; ParameterMetadata[] sortedPm = new ParameterMetadata[sorted.Count]; int pos = 0; foreach (KeyValuePair <DoublesPair, ObjDoublePair <ParameterMetadata> > entry in sorted.SetOfKeyValuePairs()) { sortedX[pos] = entry.Key.First; sortedY[pos] = entry.Key.Second; sortedZ[pos] = entry.Value.Second; sortedPm[pos] = entry.Value.First; pos++; } // assign SurfaceMetadata sortedMetadata = metadata.withParameterMetadata(Arrays.asList(sortedPm)); this.metadata = sortedMetadata; this.xValues = DoubleArray.ofUnsafe(sortedX); this.yValues = DoubleArray.ofUnsafe(sortedY); this.zValues = DoubleArray.ofUnsafe(sortedZ); IDictionary <DoublesPair, double> pairs = new Dictionary <DoublesPair, double>(); for (int i = 0; i < xValues.size(); i++) { pairs[DoublesPair.of(xValues.get(i), yValues.get(i))] = zValues.get(i); } this.interpolator = interpolator; this.boundInterpolator = interpolator.bind(this.xValues, this.yValues, this.zValues); this.parameterMetadata = IntStream.range(0, ParameterCount).mapToObj(i => sortedMetadata.getParameterMetadata(i)).collect(toImmutableList()); }
public virtual void test_createMetadata_normal() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition @base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of(ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] { new double[] { 0.15, 0.12, 0.13 }, new double[] { 0.1, Double.NaN, 0.09 } }), ValueType.NORMAL_VOLATILITY); IList <GenericVolatilitySurfacePeriodParameterMetadata> list = new List <GenericVolatilitySurfacePeriodParameterMetadata>(); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.005))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.01))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.015))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.005))); list.Add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.015))); SurfaceMetadata expected = Surfaces.normalVolatilityByExpiryStrike(NAME.Name, ACT_ACT_ISDA).withParameterMetadata(list); SurfaceMetadata computed = @base.createMetadata(capData); assertEquals(computed, expected); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case -450004177: // metadata this.metadata_Renamed = (SurfaceMetadata)newValue; break; case 1982430620: // originalSurface this.originalSurface_Renamed = (Surface)newValue; break; case -360086200: // deformationFunction this.deformationFunction_Renamed = (System.Func <DoublesPair, ValueDerivatives>)newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
//------------------------------------------------------------------------- // restricted constructor //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @ImmutableConstructor private InterpolatedNodalSurface(SurfaceMetadata metadata, com.opengamma.strata.collect.array.DoubleArray xValues, com.opengamma.strata.collect.array.DoubleArray yValues, com.opengamma.strata.collect.array.DoubleArray zValues, com.opengamma.strata.market.surface.interpolator.SurfaceInterpolator interpolator) private InterpolatedNodalSurface(SurfaceMetadata metadata, DoubleArray xValues, DoubleArray yValues, DoubleArray zValues, SurfaceInterpolator interpolator) { validateInputs(metadata, xValues, yValues, zValues, interpolator); for (int i = 1; i < xValues.size(); i++) { if (xValues.get(i) < xValues.get(i - 1)) { throw new System.ArgumentException("Array of x-values must be sorted"); } if (xValues.get(i) == xValues.get(i - 1) && yValues.get(i) <= yValues.get(i - 1)) { throw new System.ArgumentException("Array of y-values must be sorted and unique within x-values"); } } this.metadata = metadata; this.xValues = xValues; this.yValues = yValues; this.zValues = zValues; this.interpolator = interpolator; this.boundInterpolator = interpolator.bind(xValues, yValues, zValues); this.parameterMetadata = IntStream.range(0, ParameterCount).mapToObj(i => metadata.getParameterMetadata(i)).collect(toImmutableList()); }
public virtual Surface withMetadata(SurfaceMetadata metadata) { return(this); }
//------------------------------------------------------------------------- public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider) { ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime"); ArgChecker.isTrue(definition is SabrIborCapletFloorletVolatilityBootstrapDefinition, "definition should be SabrIborCapletFloorletVolatilityBootstrapDefinition"); SabrIborCapletFloorletVolatilityBootstrapDefinition bsDefinition = (SabrIborCapletFloorletVolatilityBootstrapDefinition)definition; IborIndex index = bsDefinition.Index; LocalDate calibrationDate = calibrationDateTime.toLocalDate(); LocalDate baseDate = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData); LocalDate startDate = baseDate.plus(index.Tenor); System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(bsDefinition, calibrationDateTime, capFloorData); SurfaceMetadata metaData = bsDefinition.createMetadata(capFloorData); IList <Period> expiries = capFloorData.Expiries; int nExpiries = expiries.Count; DoubleArray strikes = capFloorData.Strikes; DoubleMatrix errorsMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d)); IList <double> timeList = new List <double>(); IList <double> strikeList = new List <double>(); IList <double> volList = new List <double>(); IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>(); IList <double> priceList = new List <double>(); IList <double> errorList = new List <double>(); int[] startIndex = new int[nExpiries + 1]; for (int i = 0; i < nExpiries; ++i) { LocalDate endDate = baseDate.plus(expiries[i]); DoubleArray volatilityData = capFloorData.Data.row(i); DoubleArray errors = errorsMatrix.row(i); reduceRawData(bsDefinition, ratesProvider, strikes, volatilityData, errors, startDate, endDate, metaData, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList); startIndex[i + 1] = volList.Count; ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]); } IList <CurveMetadata> metadataList = bsDefinition.createSabrParameterMetadata(); DoubleArray timeToExpiries = DoubleArray.of(nExpiries, i => timeList[startIndex[i]]); BitArray @fixed = new BitArray(); bool betaFix = false; Curve betaCurve; Curve rhoCurve; if (bsDefinition.BetaCurve.Present) { betaFix = true; @fixed.Set(1, true); betaCurve = bsDefinition.BetaCurve.get(); rhoCurve = InterpolatedNodalCurve.of(metadataList[2], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight); } else { @fixed.Set(2, true); betaCurve = InterpolatedNodalCurve.of(metadataList[1], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight); rhoCurve = bsDefinition.RhoCurve.get(); } InterpolatedNodalCurve alphaCurve = InterpolatedNodalCurve.of(metadataList[0], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight); InterpolatedNodalCurve nuCurve = InterpolatedNodalCurve.of(metadataList[3], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight); Curve shiftCurve = bsDefinition.ShiftCurve; SabrParameters sabrParams = SabrParameters.of(alphaCurve, betaCurve, rhoCurve, nuCurve, shiftCurve, bsDefinition.SabrVolatilityFormula); SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(bsDefinition.Name, index, calibrationDateTime, sabrParams); double totalChiSq = 0d; ZonedDateTime prevExpiry = calibrationDateTime.minusDays(1L); // included if calibrationDateTime == fixingDateTime for (int i = 0; i < nExpiries; ++i) { DoubleArray start = computeInitialValues(ratesProvider, betaCurve, shiftCurve, timeList, volList, capList, startIndex, i, betaFix, capFloorData.DataType); UncoupledParameterTransforms transform = new UncoupledParameterTransforms(start, TRANSFORMS, @fixed); int nCaplets = startIndex[i + 1] - startIndex[i]; int currentStart = startIndex[i]; System.Func <DoubleArray, DoubleArray> valueFunction = createPriceFunction(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, nExpiries, i, nCaplets, betaFix); System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(ratesProvider, vols, prevExpiry, capList, priceList, index.Currency, startIndex, nExpiries, i, nCaplets, betaFix); NonLinearTransformFunction transFunc = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform); DoubleArray adjustedPrices = this.adjustedPrices(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, i, nCaplets); DoubleArray errors = DoubleArray.of(nCaplets, n => errorList[currentStart + n]); LeastSquareResults res = solver.solve(adjustedPrices, errors, transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(start)); LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform); vols = updateParameters(vols, nExpiries, i, betaFix, resTransform.ModelParameters); totalChiSq += res.ChiSq; prevExpiry = capList[startIndex[i + 1] - 1].FinalFixingDateTime; } return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, totalChiSq)); }
/// <summary> /// Creates a constant surface with a specific value. /// </summary> /// <param name="metadata"> the surface metadata </param> /// <param name="zValue"> the constant z-value </param> /// <returns> the surface </returns> public static ConstantSurface of(SurfaceMetadata metadata, double zValue) { return(new ConstantSurface(metadata, zValue)); }
private ConstantSurface(SurfaceMetadata metadata, double zValue) { JodaBeanUtils.notNull(metadata, "metadata"); this.metadata = metadata; this.zValue_Renamed = zValue; }
//------------------------------------------------------------------------- public ConstantSurface withMetadata(SurfaceMetadata metadata) { return(new ConstantSurface(metadata.withParameterMetadata(null), zValue_Renamed)); }
//------------------------------------------------------------------------- /// <summary> /// Runs the calibration of swaptions and print the calibrated smile results on the console. /// </summary> /// <param name="args"> -s to use the sparse data, i.e. a cube with missing data points </param> public static void Main(string[] args) { // select data TenorRawOptionData data = DATA_FULL; if (args.Length > 0) { if (args[0].Equals("-s")) { data = DATA_SPARSE; } } Console.WriteLine("Start calibration"); double beta = 0.50; SurfaceMetadata betaMetadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.YEAR_FRACTION).zValueType(ValueType.SABR_BETA).surfaceName("Beta").build(); Surface betaSurface = ConstantSurface.of(betaMetadata, beta); double shift = 0.0300; Surface shiftSurface = ConstantSurface.of("Shift", shift); SabrParametersSwaptionVolatilities calibrated = SABR_CALIBRATION.calibrateWithFixedBetaAndShift(DEFINITION, CALIBRATION_TIME, data, MULTICURVE, betaSurface, shiftSurface); Console.WriteLine("End calibration"); /* Graph calibration */ int nbStrikesGraph = 50; double moneyMin = -0.0250; double moneyMax = +0.0300; double[] moneyGraph = new double[nbStrikesGraph + 1]; for (int i = 0; i < nbStrikesGraph + 1; i++) { moneyGraph[i] = moneyMin + i * (moneyMax - moneyMin) / nbStrikesGraph; } //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][][] strikesGraph = new double[NB_TENORS][NB_EXPIRIES][nbStrikesGraph + 1]; double[][][] strikesGraph = RectangularArrays.ReturnRectangularDoubleArray(NB_TENORS, NB_EXPIRIES, nbStrikesGraph + 1); //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][][] volLNGraph = new double[NB_TENORS][NB_EXPIRIES][nbStrikesGraph + 1]; double[][][] volLNGraph = RectangularArrays.ReturnRectangularDoubleArray(NB_TENORS, NB_EXPIRIES, nbStrikesGraph + 1); //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][][] volNGraph = new double[NB_TENORS][NB_EXPIRIES][nbStrikesGraph + 1]; double[][][] volNGraph = RectangularArrays.ReturnRectangularDoubleArray(NB_TENORS, NB_EXPIRIES, nbStrikesGraph + 1); //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] parRate = new double[NB_TENORS][NB_EXPIRIES]; double[][] parRate = RectangularArrays.ReturnRectangularDoubleArray(NB_TENORS, NB_EXPIRIES); for (int looptenor = 0; looptenor < TENORS.size(); looptenor++) { double tenor = TENORS.get(looptenor).get(ChronoUnit.YEARS); for (int loopexpiry = 0; loopexpiry < EXPIRIES.size(); loopexpiry++) { LocalDate expiry = EUR_FIXED_1Y_EURIBOR_6M.FloatingLeg.StartDateBusinessDayAdjustment.adjust(CALIBRATION_DATE.plus(EXPIRIES.get(loopexpiry)), REF_DATA); LocalDate effectiveDate = EUR_FIXED_1Y_EURIBOR_6M.calculateSpotDateFromTradeDate(expiry, REF_DATA); LocalDate endDate = effectiveDate.plus(TENORS.get(looptenor)); SwapTrade swap = EUR_FIXED_1Y_EURIBOR_6M.toTrade(CALIBRATION_DATE, effectiveDate, endDate, BuySell.BUY, 1.0, 0.0); parRate[looptenor][loopexpiry] = SWAP_PRICER.parRate(swap.resolve(REF_DATA).Product, MULTICURVE); ZonedDateTime expiryDateTime = expiry.atTime(11, 0).atZone(ZoneId.of("Europe/Berlin")); double time = calibrated.relativeTime(expiryDateTime); for (int i = 0; i < nbStrikesGraph + 1; i++) { strikesGraph[looptenor][loopexpiry][i] = parRate[looptenor][loopexpiry] + moneyGraph[i]; volLNGraph[looptenor][loopexpiry][i] = calibrated.volatility(expiryDateTime, tenor, strikesGraph[looptenor][loopexpiry][i], parRate[looptenor][loopexpiry]); volNGraph[looptenor][loopexpiry][i] = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(parRate[looptenor][loopexpiry] + shift, strikesGraph[looptenor][loopexpiry][i] + shift, time, volLNGraph[looptenor][loopexpiry][i]); } } } /* Graph export */ string svn = "Moneyness"; for (int looptenor = 0; looptenor < TENORS.size(); looptenor++) { for (int loopexpiry = 0; loopexpiry < EXPIRIES.size(); loopexpiry++) { svn = svn + ", Strike_" + EXPIRIES.get(loopexpiry).ToString() + "x" + TENORS.get(looptenor).ToString() + ", NormalVol_" + EXPIRIES.get(loopexpiry).ToString() + "x" + TENORS.get(looptenor).ToString(); } } svn = svn + "\n"; for (int i = 0; i < nbStrikesGraph + 1; i++) { svn = svn + moneyGraph[i]; for (int looptenor = 0; looptenor < TENORS.size(); looptenor++) { for (int loopexpiry = 0; loopexpiry < EXPIRIES.size(); loopexpiry++) { svn = svn + ", " + strikesGraph[looptenor][loopexpiry][i]; svn = svn + ", " + volNGraph[looptenor][loopexpiry][i]; } } svn = svn + "\n"; } Console.WriteLine(svn); }