Exemplo n.º 1
0
 //-------------------------------------------------------------------------
 public virtual void test_volatility()
 {
     for (int i = 0; i < NB_EXPIRY; i++)
     {
         double expiryTime = VOLS.relativeTime(TEST_EXPIRY[i]);
         for (int j = 0; j < NB_STRIKE; ++j)
         {
             double volExpected = SMILE_TERM.volatility(expiryTime, TEST_STRIKE[j], FORWARD[i]);
             double volComputed = VOLS.volatility(CURRENCY_PAIR, TEST_EXPIRY[i], TEST_STRIKE[j], FORWARD[i]);
             assertEquals(volComputed, volExpected, TOLERANCE);
         }
     }
 }
Exemplo n.º 2
0
        public virtual void test_recoverVolatility()
        {
            int    nSteps       = TREE_DATA.NumberOfSteps;
            double spot         = TREE_DATA.Spot;
            double timeToExpiry = TREE_DATA.getTime(nSteps);
            double dfDom        = RATE_PROVIDER.discountFactors(USD).discountFactor(timeToExpiry);
            double dfFor        = RATE_PROVIDER.discountFactors(EUR).discountFactor(timeToExpiry);
            double forward      = spot * dfFor / dfDom;

            for (int i = 0; i < 100; ++i)
            {
                double         strike     = spot * (0.8 + 0.004 * i);
                OptionFunction func       = EuropeanVanillaOptionFunction.of(strike, timeToExpiry, PutCall.CALL, nSteps);
                double         price      = TREE.optionPrice(func, TREE_DATA);
                double         impliedVol = BlackFormulaRepository.impliedVolatility(price / dfDom, forward, strike, timeToExpiry, true);
                double         orgVol     = VOLS.volatility(FX_PRODUCT.CurrencyPair, timeToExpiry, strike, forward);
                assertEquals(impliedVol, orgVol, orgVol * 0.1);   // large tol
                double priceMrkt      = TREE.optionPrice(func, TREE_DATA_MRKT);
                double impliedVolMrkt = BlackFormulaRepository.impliedVolatility(priceMrkt / dfDom, forward, strike, timeToExpiry, true);
                double orgVolMrkt     = VOLS_MRKT.volatility(FX_PRODUCT.CurrencyPair, timeToExpiry, strike, forward);
                assertEquals(impliedVolMrkt, orgVolMrkt, orgVolMrkt * 0.1);   // large tol
            }
        }
Exemplo n.º 3
0
        //-------------------------------------------------------------------------
        // 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);
        }