//------------------------------------------------------------------------- public virtual void coverage() { BlackFxOptionSmileVolatilities test1 = BlackFxOptionSmileVolatilities.of(NAME, CURRENCY_PAIR, VAL_DATE_TIME, SMILE_TERM); coverImmutableBean(test1); BlackFxOptionSmileVolatilities test2 = BlackFxOptionSmileVolatilities.of(FxOptionVolatilitiesName.of("Boo"), CURRENCY_PAIR.inverse(), ZonedDateTime.of(2015, 12, 21, 11, 15, 0, 0, ZoneId.of("Z")), SMILE_TERM); coverBeanEquals(test1, test2); }
/// <summary> /// Creates volatility provider with term structure of smile parameters. /// <para> /// The number of time slices are 6, and the day count convention is ACT/365F. /// /// </para> /// </summary> /// <param name="dateTime"> the valuation date time </param> /// <returns> the volatility provider </returns> public static BlackFxOptionSmileVolatilities createVolatilitySmileProvider6(ZonedDateTime dateTime) { return(BlackFxOptionSmileVolatilities.of(NAME, CURRENCY_PAIR, dateTime, SMILE_TERM_6)); }
//------------------------------------------------------------------------- // bumping a node point at (nodeExpiry, nodeDelta) private double nodeSensitivity(BlackFxOptionSmileVolatilities provider, CurrencyPair pair, ZonedDateTime expiry, double strike, double forward, double nodeExpiry, double nodeDelta) { double strikeMod = provider.CurrencyPair.Equals(pair) ? strike : 1.0 / strike; double forwardMod = provider.CurrencyPair.Equals(pair) ? forward : 1.0 / forward; InterpolatedStrikeSmileDeltaTermStructure smileTerm = (InterpolatedStrikeSmileDeltaTermStructure)provider.Smile; double[] times = smileTerm.Expiries.toArray(); int nTimes = times.Length; SmileDeltaParameters[] volTermUp = new SmileDeltaParameters[nTimes]; SmileDeltaParameters[] volTermDw = new SmileDeltaParameters[nTimes]; int deltaIndex = -1; for (int i = 0; i < nTimes; ++i) { DoubleArray deltas = smileTerm.VolatilityTerm.get(i).Delta; int nDeltas = deltas.size(); int nDeltasTotal = 2 * nDeltas + 1; double[] deltasTotal = new double[nDeltasTotal]; deltasTotal[nDeltas] = 0.5d; for (int j = 0; j < nDeltas; ++j) { deltasTotal[j] = 1d - deltas.get(j); deltasTotal[2 * nDeltas - j] = deltas.get(j); } double[] volsUp = smileTerm.VolatilityTerm.get(i).Volatility.toArray(); double[] volsDw = smileTerm.VolatilityTerm.get(i).Volatility.toArray(); if (Math.Abs(times[i] - nodeExpiry) < TOLERANCE) { for (int j = 0; j < nDeltasTotal; ++j) { if (Math.Abs(deltasTotal[j] - nodeDelta) < TOLERANCE) { deltaIndex = j; volsUp[j] += EPS; volsDw[j] -= EPS; } } } volTermUp[i] = SmileDeltaParameters.of(times[i], deltas, DoubleArray.copyOf(volsUp)); volTermDw[i] = SmileDeltaParameters.of(times[i], deltas, DoubleArray.copyOf(volsDw)); } InterpolatedStrikeSmileDeltaTermStructure smileTermUp = InterpolatedStrikeSmileDeltaTermStructure.of(ImmutableList.copyOf(volTermUp), ACT_365F); InterpolatedStrikeSmileDeltaTermStructure smileTermDw = InterpolatedStrikeSmileDeltaTermStructure.of(ImmutableList.copyOf(volTermDw), ACT_365F); BlackFxOptionSmileVolatilities provUp = BlackFxOptionSmileVolatilities.of(NAME, CURRENCY_PAIR, VAL_DATE_TIME, smileTermUp); BlackFxOptionSmileVolatilities provDw = BlackFxOptionSmileVolatilities.of(NAME, CURRENCY_PAIR, VAL_DATE_TIME, smileTermDw); double volUp = provUp.volatility(pair, expiry, strike, forward); double volDw = provDw.volatility(pair, expiry, strike, forward); double totalSensi = 0.5 * (volUp - volDw) / EPS; double expiryTime = provider.relativeTime(expiry); SmileDeltaParameters singleSmile = smileTerm.smileForExpiry(expiryTime); double[] strikesUp = singleSmile.strike(forwardMod).toArray(); double[] strikesDw = strikesUp.Clone(); double[] vols = singleSmile.Volatility.toArray(); strikesUp[deltaIndex] += EPS; strikesDw[deltaIndex] -= EPS; double volStrikeUp = LINEAR.bind(DoubleArray.ofUnsafe(strikesUp), DoubleArray.ofUnsafe(vols), FLAT, FLAT).interpolate(strikeMod); double volStrikeDw = LINEAR.bind(DoubleArray.ofUnsafe(strikesDw), DoubleArray.ofUnsafe(vols), FLAT, FLAT).interpolate(strikeMod); double sensiStrike = 0.5 * (volStrikeUp - volStrikeDw) / EPS; SmileDeltaParameters singleSmileUp = smileTermUp.smileForExpiry(expiryTime); double strikeUp = singleSmileUp.strike(forwardMod).get(deltaIndex); SmileDeltaParameters singleSmileDw = smileTermDw.smileForExpiry(expiryTime); double strikeDw = singleSmileDw.strike(forwardMod).get(deltaIndex); double sensiVol = 0.5 * (strikeUp - strikeDw) / EPS; return(totalSensi - sensiStrike * sensiVol); }