Example #1
0
 private void priceCheck(double[] strikes)
 {
     for (int i = 0; i < N; i++)
     {
         double ivNormalComputed    = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, strikes[i], T, SIGMA_BLACK[i]);
         double priceNormalComputed = NormalFormulaRepository.price(FORWARD, strikes[i], T, ivNormalComputed, PutCall.CALL) * DF;
         double priceBlack          = BlackFormulaRepository.price(FORWARD, strikes[i], T, SIGMA_BLACK[i], true) * DF;
         assertEquals(priceNormalComputed, priceBlack, TOLERANCE_PRICE);
     }
 }
Example #2
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the implied volatility.
        /// <para>
        /// If the volatility data is not zero, it is used as a starting point for the volatility search.
        /// </para>
        /// <para>
        /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller.
        ///
        /// </para>
        /// </summary>
        /// <param name="optionPrice">  the price of the option </param>
        /// <param name="forward">  the forward value of the underlying </param>
        /// <param name="strike">  the strike </param>
        /// <param name="timeToExpiry">  the time to expiry </param>
        /// <param name="initialNormalVol">  the normal volatility used to start the search </param>
        /// <param name="numeraire">  the numeraire </param>
        /// <param name="putCall">  whether it is put or call </param>
        /// <returns> the implied volatility </returns>
        public static double impliedVolatility(double optionPrice, double forward, double strike, double timeToExpiry, double initialNormalVol, double numeraire, PutCall putCall)
        {
            double intrinsicPrice = numeraire * Math.Max(0, (putCall.Call ? 1 : -1) * (forward - strike));

            ArgChecker.isTrue(optionPrice > intrinsicPrice || DoubleMath.fuzzyEquals(optionPrice, intrinsicPrice, 1e-6), "Option price (" + optionPrice + ") less than intrinsic value (" + intrinsicPrice + ")");
            if (System.BitConverter.DoubleToInt64Bits(optionPrice) == Double.doubleToLongBits(intrinsicPrice))
            {
                return(0d);
            }
            double           sigma     = (Math.Abs(initialNormalVol) < 1e-10 ? 0.3 * forward : initialNormalVol);
            double           maxChange = 0.5 * forward;
            ValueDerivatives price     = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall);
            double           vega      = price.getDerivative(1);
            double           change    = (price.Value - optionPrice) / vega;
            double           sign      = Math.Sign(change);

            change = sign * Math.Min(maxChange, Math.Abs(change));
            if (change > 0 && change > sigma)
            {
                change = sigma;
            }
            int count = 0;

            while (Math.Abs(change) > EPS)
            {
                sigma -= change;
                price  = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall);
                vega   = price.getDerivative(1);
                change = (price.Value - optionPrice) / vega;
                sign   = Math.Sign(change);
                change = sign * Math.Min(maxChange, Math.Abs(change));
                if (change > 0 && change > sigma)
                {
                    change = sigma;
                }
                if (count++ > MAX_ITERATIONS)
                {
                    BracketRoot bracketer = new BracketRoot();
                    BisectionSingleRootFinder    rootFinder = new BisectionSingleRootFinder(EPS);
                    System.Func <double, double> func       = (double?volatility) =>
                    {
                        return(numeraire * NormalFormulaRepository.price(forward, strike, timeToExpiry, volatility.Value, putCall) - optionPrice);
                    };
                    double[] range = bracketer.getBracketedPoints(func, 0d, 10d);
                    return(rootFinder.getRoot(func, range[0], range[1]).Value);
                }
            }
            return(sigma);
        }
Example #3
0
        public virtual void implied_volatility_adjoint()
        {
            double shiftFd = 1.0E-6;

            for (int i = 0; i < N; i++)
            {
                double           impliedVol    = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]);
                ValueDerivatives impliedVolAdj = NormalFormulaRepository.impliedVolatilityFromBlackApproximatedAdjoint(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]);
                assertEquals(impliedVolAdj.Value, impliedVol, TOLERANCE_VOL);
                double impliedVolP            = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] + shiftFd);
                double impliedVolM            = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] - shiftFd);
                double derivativeApproximated = (impliedVolP - impliedVolM) / (2 * shiftFd);
                assertEquals(impliedVolAdj.Derivatives.size(), 1);
                assertEquals(impliedVolAdj.getDerivative(0), derivativeApproximated, TOLERANCE_VOL);
            }
        }
 /// <summary>
 /// Computes vega of an option in the normally distributed assets hypothesis (Bachelier model).
 /// </summary>
 /// <param name="option">  the option description </param>
 /// <param name="data">  the model data </param>
 /// <returns> vega </returns>
 public double getVega(EuropeanVanillaOption option, NormalFunctionData data)
 {
     ArgChecker.notNull(option, "option");
     ArgChecker.notNull(data, "data");
     return(data.Numeraire * NormalFormulaRepository.vega(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall));
 }
 /// <summary>
 /// Computes the price of an option in the normally distributed assets hypothesis (Bachelier model).
 /// The first order price derivatives are also provided.
 /// </summary>
 /// <param name="option">  the option description </param>
 /// <param name="data">  the model data </param>
 /// <returns> a <seealso cref="ValueDerivatives"/> with the price in the value and the derivatives with
 ///  respect to [0] the forward, [1] the volatility and [2] the strike </returns>
 public ValueDerivatives getPriceAdjoint(EuropeanVanillaOption option, NormalFunctionData data)
 {
     ArgChecker.notNull(option, "option");
     ArgChecker.notNull(data, "data");
     return(NormalFormulaRepository.priceAdjoint(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall));
 }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("synthetic-access") @Override public System.Nullable<double> apply(NormalFunctionData data)
            public override double?apply(NormalFunctionData data)
            {
                ArgChecker.notNull(data, "data");
                return(data.Numeraire * NormalFormulaRepository.price(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall));
            }
Example #7
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test(expectedExceptions = IllegalArgumentException.class) public void wrong_forward()
        public virtual void wrong_forward()
        {
            NormalFormulaRepository.impliedVolatilityFromBlackApproximated(-1.0d, FORWARD, T, 0.20d);
        }
Example #8
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test(expectedExceptions = IllegalArgumentException.class) public void wrong_strike()
        public virtual void wrong_strike()
        {
            NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, -1.0d, T, 0.20d);
        }
Example #9
0
 private double impliedVolatility(NormalFunctionData data, EuropeanVanillaOption option, double price)
 {
     return(NormalFormulaRepository.impliedVolatility(price, data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall));
 }