示例#1
0
        public void TestEval()
        {
            var          abs        = new[] { 0.0, 0.5, 0.99, 2.5 };
            var          vals       = new[] { 5.0, 5.4, 3.1, 1.0 };
            const double leftSlope  = 0.0;
            const double rightSlope = 0.98181;

            var stepFunc = RrFunctions.LinearInterpolation(abs, vals, leftSlope, rightSlope);

            foreach (var i in Enumerable.Range(0, abs.Length))
            {
                Assert.AreEqual(stepFunc.Eval(abs[i]), vals[i]);
                if (i < abs.Length - 1)
                {
                    var midPoint = 0.5 * (abs[i] + abs[i + 1]);
                    Assert.AreEqual(stepFunc.Eval(midPoint), 0.5 * (vals[i] + vals[i + 1]));
                }
            }

            double leftExtrapolPoint = abs[0] - 10.0;

            Assert.AreEqual(stepFunc.Eval(leftExtrapolPoint), vals[0] + leftSlope * (leftExtrapolPoint - abs[0]));

            double rightExtrapolPoint = abs[abs.Length - 1] + 10.0;

            Assert.AreEqual(stepFunc.Eval(rightExtrapolPoint), vals[abs.Length - 1] + rightSlope * (rightExtrapolPoint - abs[abs.Length - 1]));
        }
示例#2
0
        public static DiscountCurve LinearRateInterpol(FinancingId financing, DateTime[] pillars, double[] zcs, ITimeMeasure time)
        {
            if (pillars.Length != zcs.Length)
                throw new Exception("LinearRateDiscountProvider : Incompatible size");
            var dates = time[pillars];

            var zcRates = new double[pillars.Length];

            if (DoubleUtils.EqualZero(dates[0]))
            {
                if (!DoubleUtils.MachineEquality(1.0, zcs[0]))
                    throw new Exception("LinearRateInterpol : Discount for refDate must equal to 1.0 ");
                zcRates[0] = 0.0;
            }
            else
            {
                zcRates[0] = -Math.Log(zcs[0]) / dates[0];
            }

            for (int i = 1; i < zcs.Length; i++)
            {
                zcRates[i] = -Math.Log(zcs[i]) / dates[i];
            }

            return new DiscountCurveFromRate(financing, time, RrFunctions.LinearInterpolation(dates, zcRates));
        }
示例#3
0
        private static RrFunction BuildXi(MapRawDatas <DateOrDuration, double> sigma, ITimeMeasure time)
        {
            var matVars = EnumerableUtils.For(0, sigma.Pillars.Length, i =>
            {
                var mat      = time[sigma.Pillars[i].ToDate(time.RefDate)];
                var variance = sigma.Values[i] * sigma.Values[i] * mat;
                return(new { Mat = mat, Variance = variance });
            }).OrderBy(t => t.Mat).ToArray();

            if (!DoubleUtils.EqualZero(matVars.First().Mat))
            {
                matVars = matVars.Concat(new[] { new { Mat = 0.0, Variance = 0.0 } })
                          .OrderBy(t => t.Mat).ToArray();
            }

            var varianceFunc = RrFunctions.LinearInterpolation(matVars.Map(t => t.Mat),
                                                               matVars.Map(t => t.Variance),
                                                               0.0, double.NaN);

            return(varianceFunc.Derivative());
        }
        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);
        }