Exemplo n.º 1
0
        public void CallNaiveImplemXCheck()
        {
            var maturities     = GridUtils.RegularGrid(0.1, 5.0, 100);
            var vols           = GridUtils.RegularGrid(0.01, 1.0, 10);
            var volMoneynesses = GridUtils.RegularGrid(-3, 3, 100);

            foreach (var mat in maturities)
            {
                foreach (var vol in vols)
                {
                    var sigma = Math.Sqrt(mat) * vol;
                    foreach (var vm in volMoneynesses)
                    {
                        var strike = Math.Exp(vm * sigma);
                        var call   = BlackScholesOption.Price(1.0, strike, vol, mat, 1);

                        //Naive implementation of black-scholes formulae
                        var d_plus      = -(vm * sigma) / sigma + 0.5 * sigma;
                        var d_minus     = d_plus - sigma;
                        var call_xcheck = NormalDistribution.Cumulative(d_plus) - strike * NormalDistribution.Cumulative(d_minus);

                        if (DoubleUtils.EqualZero(call))
                        {
                            Assert.IsTrue(DoubleUtils.EqualZero(call_xcheck));
                        }
                        else
                        {
                            var errRelative = (call - call_xcheck) / call_xcheck;
                            Assert.IsTrue(Math.Abs(errRelative) < 1.0e-11);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Price option using Lehman Brother proxy.
        /// </summary>
        /// <param name="maturity">option maturity</param>
        /// <param name="strike">option strike</param>
        /// <param name="vol">volatility</param>
        /// <param name="q">option type : 1 for call, -1 for put</param>
        /// <returns></returns>
        public double PriceLehman(double maturity, double strike, double vol, double q)
        {
            double effectiveForward, strikeShift;

            affineDivUtils.LehmanProxy(maturity, spot, out effectiveForward, out strikeShift);
            return(BlackScholesOption.Price(effectiveForward, strike + strikeShift, vol, maturity, q));
        }
Exemplo n.º 3
0
        public static object BlackGreek(double fwd, double strike, double maturity, double vol, string request)
        {
            return(FunctionRunnerUtils.Run("BlackGreek", () =>
            {
                double gamma, theta, vega, vanna, vomma;
                BlackScholesOption.Greeks(fwd, strike, maturity, vol,
                                          out gamma, out theta, out vega, out vanna, out vomma);
                switch (request.Trim().ToLower())
                {
                case "gamma":
                    return gamma;

                case "theta":
                    return theta;

                case "vega":
                    return vega;

                case "vanna":
                    return vanna;

                case "vomma":
                    return vomma;

                default:
                    throw new Exception(string.Format("Unknow greek : {0}", request));
                }
            }));
        }
Exemplo n.º 4
0
        public static double Cumulative(double forward, double maturity, Func <double, double> vol, double strike)
        {
            var v    = vol(strike);
            var dk   = strike * 1e-5;
            var skew = (vol(strike + dk) - vol(strike - dk)) / (2.0 * dk);

            return(BlackScholesOption.PriceDigit(forward, strike, v, maturity, -1.0, skew));
        }
Exemplo n.º 5
0
        public void Implied_VolSample_Test()
        {
            const double mat    = 1.0;
            const double strike = 1.50;
            var          vols   = GridUtils.RegularGrid(0.015, 2.0, 100);

            foreach (double vol in vols)
            {
                var option     = BlackScholesOption.Price(1.0, strike, vol, mat, 1);
                var impliedVol = BlackScholesOption.ImpliedVol(option, 1.0, strike, mat, 1);

                var errRelative = (impliedVol - vol) / vol;
                Assert.IsTrue(Math.Abs(errRelative) < 6 * DoubleUtils.MachineEpsilon);
            }
        }
            private double Price(double volBeforeMidT, double volAfterMidT, double q)
            {
                double aCvx = a * Math.Exp(-0.5 * volBeforeMidT * volBeforeMidT * midT);

                var price = 0.0;

                for (int i = 0; i < z.Length; i++)
                {
                    double x         = aCvx * Math.Exp(volBeforeMidT * z[i]) + b;
                    double midTprice = (x > 0.0) ? BlackScholesOption.Price(x, k, volAfterMidT, dT, q)
                        : (q > 0.0) ? 0.0 : k - x;
                    price += quadWeights[i] * midTprice;
                }
                return(price);
            }
        public double PriceProxy(double maturity, double strike, double vol, double q)
        {
            var    growth          = affineDivUtils.AssetGrowth(maturity);
            double cashBpv         = affineDivUtils.CashDivBpv(maturity);
            double cashBpvTimeWAvg = affineDivUtils.CashBpvTimeWeightedAverage(maturity);
            double cashBpbAvg      = affineDivUtils.CashBpvAverage(0.0, maturity);
            double volAdj          = 1.0 + (cashBpvTimeWAvg - cashBpbAvg) / spot;

            double displacement   = cashBpvTimeWAvg / volAdj;
            double formulaForward = growth * (spot - displacement);
            double formulaStrike  = strike + growth * (cashBpv - displacement);
            double formulaVol     = vol * volAdj;

            return(BlackScholesOption.Price(formulaForward, formulaStrike, formulaVol, maturity, q));
        }
Exemplo n.º 8
0
        public void ImpliedVol_MoneynessSample_Test()
        {
            const double mat         = 0.5;
            const double vol         = 0.253251;
            var          moneynesses = GridUtils.RegularGrid(-5.0, 5.0, 100);

            foreach (double m in moneynesses)
            {
                var strike     = Math.Exp(m);
                var option     = BlackScholesOption.Price(1.0, strike, vol, mat, m > 0 ? 1 : -1);
                var impliedVol = BlackScholesOption.ImpliedVol(option, 1.0, strike, mat, m > 0 ? 1 : -1);

                var errRelative = (impliedVol - vol) / vol;
                Assert.IsTrue(Math.Abs(errRelative) < 6 * DoubleUtils.MachineEpsilon);
            }
        }
Exemplo n.º 9
0
        public static object BlackImpliedVol(double forward, double strike, double maturity, double price, string optionType)
        {
            return(FunctionRunnerUtils.Run("BlackImpliedVol", () =>
            {
                double q;
                switch (optionType.Trim().ToLower())
                {
                case "call":
                    q = 1.0;
                    break;

                case "put":
                    q = -1.0;
                    break;

                default:
                    throw new Exception(string.Format("Unknow option type : {0}", optionType));
                }
                return BlackScholesOption.ImpliedVol(price, forward, strike, maturity, q);
            }));
        }
        /// <summary>
        /// Implied volatility from option price. (Inversion of the two step quadrature formula.)
        /// </summary>
        /// <param name="maturity">option maturity</param>
        /// <param name="strike">option strike</param>
        /// <param name="price">option price </param>
        /// <param name="q">option type : 1 for call, -1 for put</param>
        /// <returns></returns>
        public double ImpliedVol(double maturity, double strike, double price, double q)
        {
            //Proxy using Lehman Formula
            double proxyFwd, proxyDk;

            affineDivUtils.LehmanProxy(maturity, spot, out proxyFwd, out proxyDk);
            double lehmanTargetVol = BlackScholesOption.ImpliedVol(price, proxyFwd, strike + proxyDk, maturity, q);

            var pricer = new BsDivPrice(maturity, strike, spot, affineDivUtils, quadPoints, quadWeights);
            Func <double, double> volToLehmanVolErr =
                v => BlackScholesOption.ImpliedVol(pricer.Price(v, q), proxyFwd, strike + proxyDk, maturity, q) - lehmanTargetVol;

            //Solve
            double v1   = lehmanTargetVol;
            double err1 = volToLehmanVolErr(v1);

            double v2   = lehmanTargetVol - err1;
            double err2 = volToLehmanVolErr(v2);
            double v3   = v1 - err1 * (v2 - v1) / (err2 - err1);

            if (Math.Abs(v3 - v2) < v2 * 1.0e-13)
            {
                return(v3);
            }
            double err3 = volToLehmanVolErr(v3);
            double v4   = RootUtils.TrinomRoot(v1, v2, v3, err1, err2, err3);

            if (Math.Abs(v4 - v3) < v3 * 1.0e-13)
            {
                return(v4);
            }
            double err4 = volToLehmanVolErr(v4);
            double v5   = RootUtils.TrinomRoot(v2, v3, v4, err2, err3, err4);

            return(v5);
        }
        public double[] CalibrateVol(double[] maturities, double[] targetPrices, double[] strikes, double[] optionTypes)
        {
            Contract.Requires(EnumerableUtils.IsSorted(maturities));
            Contract.Requires(maturities.Length == strikes.Length &&
                              strikes.Length == targetPrices.Length &&
                              targetPrices.Length == optionTypes.Length);

            double[] variances = new double[maturities.Length + 1];
            double[] varPillars = new[] { 0.0 }.Concat(maturities).ToArray();

            double[] calibVols = new double[maturities.Length];
            for (int step = 0; step < maturities.Length; step++)
            {
                var maturity    = maturities[step];
                var strike      = strikes[step];
                var targetPrice = targetPrices[step];
                var q           = optionTypes[step];

                //Proxy using Lehman Formula
                double proxyFwd, proxyDk;
                affineDivUtils.LehmanProxy(maturity, spot, out proxyFwd, out proxyDk);
                double lehmanTargetVol = BlackScholesOption.ImpliedVol(targetPrice, proxyFwd, strike + proxyDk, maturity, q);

                var pricer = new BsDivPrice(maturities[step], strikes[step], spot, affineDivUtils, quadPoints, quadWeights);
                Func <double, double> volToLehmanVolErr = v =>
                {
                    variances[1 + step] = v * v * maturity;
                    var varFunc = RrFunctions.LinearInterpolation(varPillars, variances);

                    Func <double, double> volFunc = t => Math.Sqrt(varFunc.Eval(t) / t);
                    var price = pricer.Price(volFunc, q);
                    return(BlackScholesOption.ImpliedVol(price, proxyFwd, strike + proxyDk, maturity, q) - lehmanTargetVol);
                };//TODO use a cache


                //Bracket & Solve
                double v1 = lehmanTargetVol;
                double v2;
                if (step == 0)
                {
                    v2 = lehmanTargetVol - volToLehmanVolErr(lehmanTargetVol);
                }
                else
                {
                    var volIfZeroVolOnStep = Math.Sqrt(calibVols[step - 1] * calibVols[step - 1] * maturities[step - 1] / maturities[step]);
                    var minError           = volToLehmanVolErr(volIfZeroVolOnStep);
                    if (minError > 0.0) //saturation case
                    {
                        calibVols[step]     = volIfZeroVolOnStep;
                        variances[1 + step] = volIfZeroVolOnStep * volIfZeroVolOnStep * maturity;
                        continue;
                    }
                    v2 = volIfZeroVolOnStep;
                }

                if (!RootUtils.Bracket(volToLehmanVolErr, v1, v2, out v1, out v2))
                {
                    throw new Exception("Failed to inverse vol");
                }
                var impliedVol = RootUtils.Brenth(volToLehmanVolErr, v1, v2, 1.0e-10, 2.0 * DoubleUtils.MachineEpsilon, 10);

                calibVols[step]     = impliedVol;
                variances[1 + step] = impliedVol * impliedVol * maturity;
            }

            return(calibVols);
        }