Exemplo n.º 1
0
 public static double pricingVol(IVolSurface volSurf, Date exerciseDate, IOption option, double spot)
 {
     return(option.IsMoneynessOption ?
            //moneyness option , strike i.e. 120% of initialSpot
            volSurf.GetValue(exerciseDate, option.Strike * option.InitialSpotPrice, spot):
            volSurf.GetValue(exerciseDate, option.Strike, spot));
 }
Exemplo n.º 2
0
        public static IInterpolator1D GenerateCDF2(this IVolSurface surface, int numSamples, DateTime expiry, double fwd, bool returnInverse = false, double strikeScale = 1.0, bool logStrikes = false)
        {
            var premInterp = GeneratePremiumInterpolator(surface, numSamples, expiry, fwd, OptionType.P);
            var t          = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);

            var x = new double[numSamples];
            var y = new double[numSamples];

            var deltaKLow = 0.0000000001;
            var deltaKHi  = 0.9999999999;
            var kStepD    = (deltaKHi - deltaKLow) / numSamples;

            for (var i = 0; i < x.Length; i++)
            {
                var deltaKNew    = -deltaKLow - i * kStepD;
                var newStrikeVol = surface.GetVolForDeltaStrike(-deltaKNew, t, fwd);
                var k            = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, deltaKNew, 0, t, newStrikeVol);
                var digital      = premInterp.FirstDerivative(k);
                y[i] = digital;
                x[i] = k * strikeScale;
                if (logStrikes)
                {
                    x[i] = Log(x[i]);
                }
            }

            return(returnInverse ?
                   InterpolatorFactory.GetInterpolator(y, x, Interpolator1DType.MonotoneCubicSpline) :
                   InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.MonotoneCubicSpline));
        }
Exemplo n.º 3
0
        public static IInterpolator1D GenerateCompositeSmileBasic(this IVolSurface surface, IVolSurface fxSurface, int numSamples, DateTime expiry, double fwdAsset, double fwdFx, double correlation, bool deltaStrikeOutput = false)
        {
            var deltaKa  = fwdAsset * 0.00001;
            var deltaKfx = fwdFx * 0.00001;

            var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);

            var atmFx = fxSurface.GetVolForAbsoluteStrike(fwdFx, t, fwdFx);
            var atmA  = surface.GetVolForAbsoluteStrike(fwdAsset, t, fwdAsset);

            var compoFwd = fwdAsset * fwdFx;
            var atmCompo = Sqrt(atmFx * atmFx + atmA * atmA + 2.0 * correlation * atmA * atmFx);
            var lowK     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.0001, 0, t, atmCompo);
            var hiK      = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.9999, 0, t, atmCompo);
            var lowKA    = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwdAsset, -0.0001, 0, t, atmA);
            var hiKA     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwdAsset, -0.9999, 0, t, atmA);

            var x = new double[numSamples];
            var y = new double[numSamples];

            var k = lowK;

            var kStep   = (hiK - lowK) / numSamples;
            var kStepA  = (hiKA - lowKA) / numSamples;
            var kStepFx = (hiK / hiKA - lowK / lowKA) / numSamples;

            for (var i = 0; i < x.Length; i++)
            {
                x[i] = k;
                var kA     = lowKA;
                var totalP = 0.0;
                for (var j = 0; j < numSamples; j++)
                {
                    var kFx            = k / kA;
                    var volFx          = fxSurface.GetVolForAbsoluteStrike(kFx, t, fwdFx);
                    var volA           = surface.GetVolForAbsoluteStrike(kA, t, fwdAsset);
                    var volC           = Sqrt(volFx * volFx + volA * volA + 2.0 * correlation * volA * volFx);
                    var fxBucketLow    = kFx - deltaKfx / 2.0;
                    var fxBucketHi     = kFx + deltaKfx / 2.0;
                    var assetBucketLow = kA - deltaKa / 2.0;
                    var assetBucketHi  = kA + deltaKa / 2.0;
                    var weight         = 1.0;
                    y[i]   += weight * volC;
                    totalP += weight;
                    kA     += kStepA;
                }

                y[i] /= totalP;
                k    += kStep;
            }

            if (deltaStrikeOutput)
            {
                x = x.Select((q, ix) => - BlackFunctions.BlackDelta(compoFwd, q, 0.0, t, y[ix], OptionType.P)).ToArray();
            }

            return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap));
        }
Exemplo n.º 4
0
 public LVSingleAsset(IVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name)
 {
     _surface       = volSurface;
     _startDate     = startDate;
     _expiryDate    = expiryDate;
     _numberOfSteps = nTimeSteps;
     _name          = name;
     _forwardCurve  = forwardCurve;
 }
Exemplo n.º 5
0
 public void AddVolSurface(string name, IVolSurface surface)
 {
     if (IsFx(name))
     {
         FundingModel.VolSurfaces[name] = surface;
     }
     else
     {
         _assetVols[new VolSurfaceKey(surface.AssetId, surface.Currency)] = surface;
     }
 }
Exemplo n.º 6
0
 public BlackScholesProcessWithQuantoForwardAdjustment(IYieldCurve spotRateCurve, IYieldCurve divCurve, IVolSurface volSurf, double rho, IVolSurface fxVolSurf)
     : base()
 {
     _spotRateCurve  = spotRateCurve;
     _dividendCurve  = divCurve;
     _volSurf        = volSurf;
     _correlation    = rho;
     _fxVolSurf      = fxVolSurf;
     _isConstantRate = false;
     _isConstantVol  = false;
 }
Exemplo n.º 7
0
        public CompositeVolSurface(string name, string assetId, Currency ccy, IVolSurface assetSurface, IFundingModel fundingModel, double correlation, CompositeVolType calculationType)
        {
            AssetSurface    = assetSurface;
            FundingModel    = fundingModel;
            Correlation     = correlation;
            CalculationType = calculationType;
            Name            = name;
            AssetId         = assetId;
            Currency        = ccy;

            _Pair = FundingModel.FxMatrix.GetFxPair(AssetSurface.Currency, Currency);
        }
Exemplo n.º 8
0
        public static double InverseCDFex(this IVolSurface surface, double t, double fwd, double p)
        {
            var deltaK    = fwd * 1e-10;
            var lowGuess  = fwd / 2;
            var highGuess = fwd * 2;

            var targetFunc = new Func <double, double>(k =>
            {
                var volM = surface.GetVolForAbsoluteStrike(k - deltaK, t, fwd);
                var volP = surface.GetVolForAbsoluteStrike(k + deltaK, t, fwd);
                var pvM  = BlackFunctions.BlackPV(fwd, k - deltaK, 0.0, t, volM, OptionType.P);
                var pvP  = BlackFunctions.BlackPV(fwd, k + deltaK, 0.0, t, volP, OptionType.P);
                var digi = (pvP - pvM) / (2 * deltaK);
                //var digi = BlackFunctions.BlackDigitalPV(fwd, k, 0, t, surface.GetVolForAbsoluteStrike(k, t, fwd), OptionType.P);
                return(p - digi);
            });

            var breakCount = 0;

            while (targetFunc(lowGuess) < 0)
            {
                // highGuess = lowGuess*2.0;
                lowGuess /= 2.0;
                breakCount++;
                if (breakCount == 10)
                {
                    return(lowGuess);
                }
            }
            breakCount = 0;
            while (targetFunc(highGuess) > 0)
            {
                //lowGuess = highGuess/2.0;
                highGuess *= 2.0;
                breakCount++;
                if (breakCount == 10)
                {
                    return(highGuess);
                }
            }

            var b = Math.Solvers.Brent.BrentsMethodSolve(targetFunc, lowGuess, highGuess, 1e-8);

            //var b = Math.Solvers.Newton1D.MethodSolve2(targetFunc, fwd, 1e-6, 1000, fwd * 0.00001);
            if (double.IsInfinity(b) || double.IsNaN(b))
            {
                throw new Exception("Invalid strike found");
            }
            //if (b==lowGuess || b==highGuess)
            //    throw new Exception("Strike outside of bounds");

            return(b);
        }
Exemplo n.º 9
0
        public static IInterpolator1D GenerateCDF(this IVolSurface surface, int numSamples, DateTime expiry, double fwd, bool returnInverse = false)
        {
            var deltaKLow  = 0.0000001;
            var deltaKHi   = 0.9999999;
            var kStepD     = (deltaKHi - deltaKLow) / (numSamples + 3);
            var deltaKBump = deltaKLow / 10;

            var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);

            var x = new double[numSamples + 2];
            var y = new double[numSamples + 2];


            for (var i = 0; i < x.Length; i++)
            {
                var deltaKNew = deltaKLow + i * kStepD;
                var mStrike   = deltaKNew - deltaKBump / 2;
                var pStrike   = deltaKNew + deltaKBump / 2;

                var mStrikeVol = surface.GetVolForDeltaStrike(mStrike, t, fwd);
                var mk         = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -mStrike, 0, t, mStrikeVol);
                var pStrikeVol = surface.GetVolForDeltaStrike(pStrike, t, fwd);
                var pk         = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -pStrike, 0, t, pStrikeVol);

                if (i == 0)
                {
                    x[0] = mk / 2.0;
                    y[0] = 0;
                    continue;
                }
                if (i == x.Length - 1)
                {
                    x[i] = pk * 2;
                    y[i] = 1;
                    continue;
                }

                var dkAbs = (pk - mk);

                var pPut = BlackFunctions.BlackPV(fwd, pk, 0, t, pStrikeVol, OptionType.P);
                var mPut = BlackFunctions.BlackPV(fwd, mk, 0, t, mStrikeVol, OptionType.P);


                var digital = (pPut - mPut) / dkAbs;
                y[i] = digital;
                x[i] = (mk + pk) / 2.0;
            }

            return(returnInverse ?
                   InterpolatorFactory.GetInterpolator(y, x, Interpolator1DType.LinearFlatExtrap) :
                   InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap));
        }
Exemplo n.º 10
0
        public LVSingleAsset(IVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name, Dictionary <DateTime, double> pastFixings = null, IATMVolSurface fxAdjustSurface = null, double fxAssetCorrelation = 0.0)
        {
            _surface       = volSurface;
            _startDate     = startDate;
            _expiryDate    = expiryDate;
            _numberOfSteps = nTimeSteps;
            _name          = name;
            _pastFixings   = pastFixings ?? (new Dictionary <DateTime, double>());
            _forwardCurve  = forwardCurve;

            _adjSurface  = fxAdjustSurface;
            _correlation = fxAssetCorrelation;
        }
Exemplo n.º 11
0
        public static IInterpolator1D GeneratePDF(this IVolSurface surface, int numSamples, DateTime expiry, double fwd)
        {
            var deltaK = fwd * 0.0001;

            var t            = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);
            var lowStrikeVol = surface.GetVolForDeltaStrike(0.0001, t, fwd);
            var lowStrike    = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.0001, 0, t, lowStrikeVol);
            var hiStrikeVol  = surface.GetVolForDeltaStrike(0.9999, t, fwd);
            var hiStrike     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.9999, 0, t, hiStrikeVol);

            var x = new double[numSamples + 2];
            var y = new double[numSamples + 2];

            var k = lowStrike;

            var kStep = (hiStrike - lowStrike) / numSamples;

            for (var i = 0; i < x.Length; i++)
            {
                if (i == 0)
                {
                    x[0] = lowStrike / 2.0;
                    y[0] = 0;
                    continue;
                }
                if (i == x.Length - 1)
                {
                    x[i] = k * 2;
                    y[i] = 0;
                    continue;
                }

                var volLow    = surface.GetVolForAbsoluteStrike(k - deltaK, t, fwd);
                var callLow   = BlackFunctions.BlackPV(fwd, k - deltaK, 0, t, volLow, OptionType.C);
                var volMid    = surface.GetVolForAbsoluteStrike(k, t, fwd);
                var callMid   = BlackFunctions.BlackPV(fwd, k, 0, t, volMid, OptionType.C);
                var volHi     = surface.GetVolForAbsoluteStrike(k + deltaK, t, fwd);
                var callHi    = BlackFunctions.BlackPV(fwd, k + deltaK, 0, t, volHi, OptionType.C);
                var digitalLo = (callLow - callMid) / deltaK;
                var digitalHi = (callMid - callHi) / deltaK;
                y[i] = (digitalLo - digitalHi) / deltaK;
                x[i] = k;
                k   += kStep;
            }

            var firstPass = InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap);
            var totalY    = ((IIntegrableInterpolator)firstPass).DefiniteIntegral(x.First(), x.Last());

            y = y.Select(v => v / totalY).ToArray();
            return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap));
        }
Exemplo n.º 12
0
        public static double[][] ComputeLocalVarianceOnGridFromCalls(this IVolSurface VanillaSurface, double[][] strikes, double[] timeSteps, Func <double, double> forwardFunc)
        {
            var numberOfTimesteps = timeSteps.Length;
            var deltaK            = 0.001 * forwardFunc(timeSteps[0]);
            var lvGrid            = new double[numberOfTimesteps - 1][];

            var fwds = timeSteps.Select(t => forwardFunc(t)).ToArray();

            //ParallelUtils.Instance.For(1, numberOfTimesteps, 1, it =>
            for (var it = 1; it < numberOfTimesteps; it++)
            {
                var T               = timeSteps[it];
                var T1              = timeSteps[it - 1];
                var fwd             = fwds[it];
                var fwdtm1          = fwds[it - 1];
                var rmq             = Log(fwd / fwdtm1) / (T - T1);
                var numberOfStrikes = strikes[it - 1].Length;
                var cInterp         = VanillaSurface.GeneratePremiumInterpolator(numberOfStrikes * 2, T, fwd, OptionType.C);

                lvGrid[it - 1] = new double[numberOfStrikes];

                if (numberOfStrikes > 1)
                {
                    for (var ik = 0; ik < numberOfStrikes; ik++)
                    {
                        var K    = strikes[it][ik];
                        var V    = VanillaSurface.GetVolForAbsoluteStrike(K, T, fwd);
                        var C    = BlackFunctions.BlackPV(fwd, K, 0.0, T, V, OptionType.C);
                        var Vtm1 = VanillaSurface.GetVolForAbsoluteStrike(K, T1, fwdtm1);

                        //var dcdt = -BlackFunctions.BlackTheta(fwd, K, 0.0, T, V, OptionType.C);
                        var dcdt   = -(BlackFunctions.BlackPV(fwdtm1, K, 0.0, T1, Vtm1, OptionType.C) - C) / (T - T1);
                        var dcdk   = cInterp.FirstDerivative(K);
                        var d2cdk2 = cInterp.SecondDerivative(K);

                        var localVariance = d2cdk2 == 0 ? V * V : (dcdt - rmq * (C - K * dcdk)) / (0.5 * K * K * d2cdk2);
                        lvGrid[it - 1][ik] = localVariance;
                    }
                }
                else
                {
                    var K = strikes[it][0];
                    var V = VanillaSurface.GetVolForAbsoluteStrike(K, T, fwd);
                    lvGrid[it - 1][0] = V * V;
                }
            }//, false).Wait();

            return(lvGrid);
        }
Exemplo n.º 13
0
        public bool TryGetVolSurface(string name, out IVolSurface volSurface)
        {
            if (VolSurfaces.TryGetValue(name, out volSurface))
            {
                return(true);
            }

            if (TryGetInverseSurface(name, out volSurface))
            {
                return(true);
            }

            volSurface = null;
            return(false);
        }
Exemplo n.º 14
0
        public bool TryGetVolSurface(string name, out IVolSurface surface, Currency currency = null)
        {
            surface = null;
            if (IsFx(name))
            {
                return(FundingModel.TryGetVolSurface(name, out surface));
            }

            if (currency != null)
            {
                return(_assetVols.TryGetValue(new VolSurfaceKey(name, currency), out surface));
            }

            surface = _assetVols.Where(x => name.Contains("~") ? x.Key.ToString() == name : x.Key.AssetId == name).FirstOrDefault().Value;
            return(surface != default(IVolSurface));
        }
Exemplo n.º 15
0
        public static TO_VolSurface GetTransportObject(this IVolSurface volSurface)
        {
            switch (volSurface)
            {
            case RiskyFlySurface rf:
                return(new TO_VolSurface {
                    RiskyFlySurface = rf.GetTransportObject()
                });

            case GridVolSurface gs:
                return(new TO_VolSurface {
                    GridVolSurface = gs.GetTransportObject()
                });

            case ConstantVolSurface cs:
                return(new TO_VolSurface {
                    ConstantVolSurface = cs.GetTransportObject()
                });

            default:
                throw new Exception("Unable to serialize volsurface");
            }
        }
Exemplo n.º 16
0
        public LVSingleAsset(IVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name, Dictionary <DateTime, double> pastFixings = null, IATMVolSurface fxAdjustSurface = null, double fxAssetCorrelation = 0.0)
        {
            _surface       = volSurface;
            _startDate     = startDate;
            _expiryDate    = expiryDate;
            _numberOfSteps = nTimeSteps;
            _name          = name;
            _pastFixings   = pastFixings ?? (new Dictionary <DateTime, double>());
            _forwardCurve  = forwardCurve;

            _adjSurface  = fxAdjustSurface;
            _correlation = fxAssetCorrelation;

            if (volSurface is InverseFxSurface || (_adjSurface != null && _adjSurface?.AssetId == volSurface.AssetId))
            {
                _siegelInvert = true;
            }

            if (_adjSurface != null && _adjSurface?.AssetId == volSurface.AssetId)
            {
                _adjSurface = null;
            }
        }
Exemplo n.º 17
0
        public static IInterpolator1D GeneratePremiumInterpolator(this IVolSurface surface, int numSamples, double t, double fwd, OptionType cp)
        {
            var lowStrikeVol = surface.GetVolForDeltaStrike(0.001, t, fwd);
            var lowStrike    = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.001, 0, t, lowStrikeVol);
            var hiStrikeVol  = surface.GetVolForDeltaStrike(0.999, t, fwd);
            var hiStrike     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.999, 0, t, hiStrikeVol);

            var x = new double[numSamples + 2];
            var y = new double[numSamples + 2];

            var k = lowStrike;

            var kStep = (hiStrike - lowStrike) / (numSamples + 1.0);

            var vol  = surface.GetVolForAbsoluteStrike(k / 10, t, fwd);
            var call = BlackFunctions.BlackPV(fwd, k / 10, 0, t, vol, cp);

            y[0] = call;
            x[0] = k / 10;

            for (var i = 0; i < x.Length - 1; i++)
            {
                vol      = surface.GetVolForAbsoluteStrike(k, t, fwd);
                call     = BlackFunctions.BlackPV(fwd, k, 0, t, vol, cp);
                y[i + 1] = call;
                x[i + 1] = k;
                k       += kStep;
            }

            vol             = surface.GetVolForAbsoluteStrike(k * 10, t, fwd);
            call            = BlackFunctions.BlackPV(fwd, k * 10, 0, t, vol, cp);
            y[x.Length - 1] = call;
            x[x.Length - 1] = k * 10;

            return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.MonotoneCubicSpline));
        }
Exemplo n.º 18
0
        public BlackScholesProcess(IYieldCurve spotRateCurve, IYieldCurve divCurve, IVolSurface volSurf, double[] times = null)
        {
            _spotRateCurve = spotRateCurve;
            _dividendCurve = divCurve;
            _volSurf       = volSurf;
            _isConst       = false;

            if (times == null)
            {
                return;
            }

            //cache forward rate
            _spotRateCurveForwardrateDict = new Dictionary <double, double>();
            _dividendCurveForwardrateDict = new Dictionary <double, double>();
            for (var i = 0; i < times.Length - 1; ++i)
            {
                var t0 = times[i];
                var dt = times[i + 1] - times[i];
                _spotRateCurveForwardrateDict[Math.Round(t0, Precision)] = _spotRateCurve.GetForwardRate(t0, dt, _spotRateCurve.Compound);
                _dividendCurveForwardrateDict[Math.Round(t0, Precision)] = _dividendCurve.GetForwardRate(t0, dt, _dividendCurve.Compound);
            }
            _isCached = true;
        }
Exemplo n.º 19
0
 public void AddVolSurface(VolSurfaceKey key, IVolSurface surface) => _assetVols[key] = surface;
Exemplo n.º 20
0
 public static IInterpolator1D GeneratePremiumInterpolator(this IVolSurface surface, int numSamples, DateTime expiry, double fwd, OptionType cp)
 => GeneratePremiumInterpolator(surface, numSamples, surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F), fwd, cp);
Exemplo n.º 21
0
 public void AddVolSurface(string name, IVolSurface surface) => _assetVols[new VolSurfaceKey(surface.AssetId, surface.Currency)] = surface;
Exemplo n.º 22
0
        public static IInterpolator1D GenerateCompositeSmileB(this IVolSurface surface, IVolSurface fxSurface, int numSamples, DateTime expiry, double fwdAsset, double fwdFx, double correlation, bool strikesInDeltaSpace = false)
        {
            var t     = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);
            var fxInv = new InverseFxSurface("fxInv", fxSurface as IATMVolSurface, null);

            var atmFx = fxSurface.GetVolForDeltaStrike(0.5, t, fwdFx);
            var atmA  = surface.GetVolForDeltaStrike(0.5, t, fwdAsset);

            var compoFwd = fwdAsset * fwdFx;
            var atmCompo = Sqrt(atmFx * atmFx + atmA * atmA + 2.0 * correlation * atmA * atmFx);
            var lowK     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.01, 0, t, atmCompo);
            var hiK      = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.99, 0, t, atmCompo);

            //var cdfInvFx = fxSurface.GenerateCDF2(numSamples * 10, expiry, fwdFx, true);
            //var cdfInvAsset = surface.GenerateCDF2(numSamples * 10, expiry, fwdAsset, true);
            //var yFx = new Func<double, double>(z => cdfInvFx.Interpolate(Statistics.NormSDist(z)));
            //var yAsset = new Func<double, double>(z => cdfInvAsset.Interpolate(Statistics.NormSDist(z)));

            var fxCDFCache    = new Dictionary <double, double>();
            var assetCDFCache = new Dictionary <double, double>();
            var yFx           = new Func <double, double>(z =>
            {
                if (fxCDFCache.TryGetValue(z, out var K))
                {
                    return(K);
                }
                K = fxInv.InverseCDF(expiry, 1.0 / fwdFx, Statistics.NormSDist(z));
                fxCDFCache.Add(z, K);
                return(K);
            });
            var yAsset = new Func <double, double>(z =>
            {
                if (assetCDFCache.TryGetValue(z, out var K))
                {
                    return(K);
                }
                K = surface.InverseCDF(expiry, fwdAsset, Statistics.NormSDist(z));
                assetCDFCache.Add(z, K);
                return(K);
            });

            //var fxCDFCache = new Dictionary<double, double>();
            //var assetCDFCache = new Dictionary<double, double>();
            //var putFx = fxInv.GeneratePremiumInterpolator(numSamples * 10, expiry, 1.0/fwdFx, OptionType.P);
            //var putAsset = surface.GeneratePremiumInterpolator(numSamples * 10, expiry, fwdAsset, OptionType.P);
            //var yFx = new Func<double, double>(z =>
            //{
            //    if (fxCDFCache.TryGetValue(z, out var K)) return K;
            //    K = InverseCDF(putFx, t, 1.0/fwdFx, Statistics.NormSDist(z));
            //    fxCDFCache.Add(z, K);
            //    return K;
            //});
            //var yAsset = new Func<double, double>(z =>
            //{
            //    if (assetCDFCache.TryGetValue(z, out var K)) return K;
            //    K = InverseCDF(putAsset, t, fwdAsset, Statistics.NormSDist(z));
            //    var kl = assetCDFCache.Keys.ToList();
            //    var closerIx = kl.BinarySearch(z);
            //    var keyIx = ~closerIx;
            //    if (closerIx < 0 && z < 0 && kl.Count > keyIx)
            //    {
            //        if (assetCDFCache[kl[keyIx]] < K)
            //            K = assetCDFCache[kl[keyIx]];
            //    }
            //    assetCDFCache.Add(z, K);
            //    return K;
            //});

            var payoff    = new Func <double, double, double, double>((z1, z2, kQ) => Max(kQ * yFx(z2) - yAsset(z1), 0));
            var integrand = new Func <double, double, double, double>((z1, z2, kQ) => payoff(z1, z2, kQ) * BivariateNormal.PDF(z1, z2, -correlation));

            var kStep    = (hiK - lowK) / numSamples;
            var ks       = Enumerable.Range(0, numSamples).Select(kk => lowK + kk * kStep).ToArray();
            var premiums = new double[ks.Length];
            var vols     = new double[ks.Length];

            for (var i = 0; i < ks.Length; i++)
            {
                var ik = new Func <double, double, double>((z1, z2) => integrand(z1, z2, ks[i]));
                var pk = Integration.TwoDimensionalGaussLegendre(ik, -5, 5, -5, 5, 16);
                //var pk = Integration.TwoDimensionalSimpsons(ik, -5, 5, -5, 5, 100);
                pk *= fwdFx;
                var volK = BlackFunctions.BlackImpliedVol(compoFwd, ks[i], 0.0, t, pk, OptionType.P);
                vols[i]     = volK;
                premiums[i] = pk;
            }


            if (strikesInDeltaSpace)
            {
                ks = ks.Select((ak, ix) => - BlackFunctions.BlackDelta(compoFwd, ak, 0.0, t, vols[ix], OptionType.P)).ToArray();
            }

            return(InterpolatorFactory.GetInterpolator(ks, vols, Interpolator1DType.CubicSpline));
        }
Exemplo n.º 23
0
        public static IInterpolator1D GenerateCompositeSmile(this IVolSurface surface, IVolSurface fxSurface, int numSamples, DateTime expiry, double fwdAsset, double fwdFx, double rho, bool strikesInDeltaSpace = false)
        {
            var t = surface.OriginDate.CalculateYearFraction(expiry, DayCountBasis.Act365F);

            var atmFx = fxSurface.GetVolForDeltaStrike(0.5, t, fwdFx);
            var atmA  = surface.GetVolForDeltaStrike(0.5, t, fwdAsset);

            var compoFwd = fwdAsset / fwdFx;
            var atmCompo = Sqrt(atmFx * atmFx + atmA * atmA + 2.0 * rho * atmA * atmFx);
            var lowK     = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.01, 0, t, atmCompo);
            var hiK      = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(compoFwd, -0.99, 0, t, atmCompo);

            var nuA  = Sqrt(t) * atmA;
            var nuFx = Sqrt(t) * atmFx;

            var cdfFx = new Func <double, double>(k => fxSurface.CDF(expiry, fwdFx, Exp(k)));
            var cdfA  = new Func <double, double>(k => surface.CDF(expiry, fwdAsset, Exp(k)));

            var fxCDFCache    = new Dictionary <double, double>();
            var assetCDFCache = new Dictionary <double, double>();
            var yFx           = new Func <double, double>(z =>
            {
                if (fxCDFCache.TryGetValue(z, out var K))
                {
                    return(K);
                }
                K = Log(fxSurface.InverseCDF(expiry, fwdFx, Statistics.NormSDist(z)));
                fxCDFCache.Add(z, K);
                return(K);
            });
            var yA = new Func <double, double>(z =>
            {
                if (assetCDFCache.TryGetValue(z, out var K))
                {
                    return(K);
                }
                K = Log(surface.InverseCDF(expiry, fwdAsset, Statistics.NormSDist(z)));
                assetCDFCache.Add(z, K);
                return(K);
            });

            //var zfxS = new Func<double, double, double>((zA, K) => Statistics.NormInv(Max(1e-18, Min(1.0 - 1e-18, cdfFx(yA(zA) - Log(K))))));
            //var zAs = new Func<double, double, double>((zFx, K) => Statistics.NormInv(Max(1e-18, Min(1.0 - 1e-18, cdfA(yFx(zFx) + Log(K))))));
            var zfxS = new Func <double, double, double>((zA, K) => Statistics.NormInv(cdfFx(yA(zA) - Log(K))));
            var zAs  = new Func <double, double, double>((zFx, K) => Statistics.NormInv(cdfA(yFx(zFx) + Log(K))));

            var d  = -1.0;
            var p2 = 1.0 / Sqrt(2.0 * PI);
            //var I1 = new Func<double, double, double>((zA, K) =>
            //p2*Exp(yA(zA) - (nuA * zA - nuA * nuA / 2)) * Statistics.NormSDist(d * (zfxS(zA, K) - rho * zA) / Sqrt(1 - rho * rho)) * Exp(-(zA - nuA) * (zA - nuA) / 2.0)
            //    );
            //var I2 = new Func<double, double, double>((zFx, K) =>
            //p2*Exp(yFx(zFx) - (nuFx * zFx - nuFx * nuFx / 2)) * Statistics.NormSDist(-d * (zAs(zFx, K) - rho * zFx) / Sqrt(1 - rho * rho)) * Exp(-(zFx - nuFx) * (zFx - nuFx) / 2.0)
            //    );
            var I1 = new Func <double, double, double>((zA, K) =>
                                                       p2 * Exp(yA(zA)) * Statistics.NormSDist(d * (zfxS(zA, K) - rho * zA) / Sqrt(1 - rho * rho)) * Exp(-(zA * zA) / 2.0)
                                                       );
            var I2 = new Func <double, double, double>((zFx, K) =>
                                                       p2 * Exp(yFx(zFx)) * Statistics.NormSDist(-d * (zAs(zFx, K) - rho * zFx) / Sqrt(1 - rho * rho)) * Exp(-(zFx * zFx) / 2.0)
                                                       );


            var kStep    = (hiK - lowK) / numSamples;
            var ks       = Enumerable.Range(0, numSamples).Select(kk => lowK + kk * kStep).ToArray();
            var premiums = new double[ks.Length];
            var vols     = new double[ks.Length];

            for (var i = 0; i < ks.Length; i++)
            {
                var I1k = new Func <double, double>(z => I1(z, ks[i]));
                var I2k = new Func <double, double>(z => I2(z, ks[i]));

                //var i1 = Integration.GaussLegendre(I1k, -5, 5, 16);
                //var i2 = Integration.GaussLegendre(I2k, -5, 5, 16);
                var i1 = Integration.SimpsonsRule(I1k, -5, 5, numSamples);
                var i2 = Integration.SimpsonsRule(I2k, -5, 5, numSamples);
                var pk = d * (i1 - ks[i] * i2);
                pk /= fwdFx;
                var volK = BlackFunctions.BlackImpliedVol(compoFwd, ks[i], 0.0, t, pk, OptionType.P);
                vols[i]     = volK;
                premiums[i] = pk;
            }


            if (strikesInDeltaSpace)
            {
                ks = ks.Select((ak, ix) => - BlackFunctions.BlackDelta(compoFwd, ak, 0.0, t, vols[ix], OptionType.P)).ToArray();
            }

            return(InterpolatorFactory.GetInterpolator(ks, vols, Interpolator1DType.CubicSpline));
        }
Exemplo n.º 24
0
        public static double[][] ComputeLocalVarianceOnGrid(this IVolSurface VanillaSurface, double[][] strikes, double[] timeSteps, Func <double, double> forwardFunc)
        {
            var numberOfTimesteps = timeSteps.Length;
            var deltaK            = 0.001 * forwardFunc(timeSteps[0]);
            var lvGrid            = new double[numberOfTimesteps - 1][];

            var Ss = new double[numberOfTimesteps];

            for (var i = 0; i < Ss.Length; i++)
            {
                Ss[i] = forwardFunc(timeSteps[i]);
            }


            for (var it = 1; it < numberOfTimesteps; it++)
            {
                var numberOfStrikes = strikes[it - 1].Length;
                lvGrid[it - 1] = new double[numberOfStrikes];

                double K, V, S, Td, dwdT, localVariance, TdSq, T, T1;
                double V_t1, V_Kp2, V_Km2, K_tm1, St;
                double y, yPlus, yPlus2, yMinus, yMinus2, dwdY, dwdY_p, dwdY_m, d2wd2Y, w, w_t1, w_kPlus2, w_kMinus2; //, Y1, Y2;

                T    = timeSteps[it];
                T1   = timeSteps[it - 1];
                Td   = T - T1;
                TdSq = Sqrt(Td);
                S    = Ss[it];
                St   = Ss[it - 1];
                var fwd = forwardFunc(T);

                for (var ik = 0; ik < numberOfStrikes; ik++)
                {
                    K       = strikes[it][ik];
                    K_tm1   = K * St / S;
                    y       = Log(K / S);
                    yPlus   = Log((K + deltaK) / S);
                    yPlus2  = Log((K + deltaK * 2) / S);
                    yMinus  = Log((K - deltaK) / S);
                    yMinus2 = Log((K - deltaK * 2) / S);
                    //Y1 = Log(Sqrt(K * K + 2 * deltaK * K) / S);
                    //Y2 = Log(Sqrt(K * K - 2 * deltaK * K) / S);
                    V         = VanillaSurface.GetVolForAbsoluteStrike(K, T, fwd);
                    w         = V * V * T;
                    V_t1      = VanillaSurface.GetVolForAbsoluteStrike(K_tm1, T1, fwd);
                    w_t1      = V_t1 * V_t1 * T1;
                    V_Kp2     = VanillaSurface.GetVolForAbsoluteStrike(K + deltaK * 2, T, fwd);
                    w_kPlus2  = V_Kp2 * V_Kp2 * T;
                    V_Km2     = VanillaSurface.GetVolForAbsoluteStrike(K - deltaK * 2, T, fwd);
                    w_kMinus2 = V_Km2 * V_Km2 * T;


                    dwdT   = (w - w_t1) / Td;
                    dwdY_m = (w - w_kMinus2) / (y - yMinus2);
                    dwdY_p = (w_kPlus2 - w) / (yPlus2 - y);
                    dwdY   = (dwdY_m + dwdY_p) / 2;

                    //d2wd2Y = (dwdY_p - dwdY_m) / (Y1 - Y2);
                    d2wd2Y = (dwdY_p - dwdY_m) / (yPlus - yMinus);

                    localVariance = dwdT / (1 - y / w * dwdY + 0.25 * (-0.25 - 1 / w + (y * y / (w))) * dwdY * dwdY + 0.5 * d2wd2Y);

                    lvGrid[it - 1][ik] = localVariance;
                }
            }

            return(lvGrid);
        }
Exemplo n.º 25
0
        public void RemoveVolSurface(IVolSurface surface)
        {
            var key = new VolSurfaceKey(surface.AssetId, surface.Currency);

            _assetVols.Remove(key);
        }
Exemplo n.º 26
0
        public static double StrikeForPV(double targetPV, double forward, double knownAverage, IVolSurface volSurface, DateTime evalDate, DateTime avgStartDate, DateTime avgEndDate, double riskFree, OptionType callPut)
        {
            var minStrike = forward / 100.0;
            var maxStrike = forward * 100.0;

            var volDate = avgStartDate.Average(avgEndDate);

            Func <double, double> testFunc = (absK =>
            {
                var vol = volSurface.GetVolForAbsoluteStrike(absK, volDate, forward);
                var pv = PV(forward, knownAverage, vol, absK, evalDate, avgStartDate, avgEndDate, riskFree, callPut);
                return(targetPV - pv);
            });

            var solvedStrike = Math.Solvers.Brent.BrentsMethodSolve(testFunc, minStrike, maxStrike, 1e-8);

            return(solvedStrike);
        }
Exemplo n.º 27
0
        private bool TryGetInverseSurface(string name, out IVolSurface volSurface)
        {
            var inverseName = name.Substring(name.Length - 3, 3) + "/" + name.Substring(0, 3);

            return(VolSurfaces.TryGetValue(inverseName, out volSurface));
        }
Exemplo n.º 28
0
        public static double StrikeForPV(double targetPV, double[] forwards, DateTime[] fixingDates, IVolSurface volSurface, DateTime evalDate, DateTime payDate, double riskFree, OptionType callPut)
        {
            var minStrike = forwards.Min() / 100.0;
            var maxStrike = forwards.Max() * 100.0;

            var ixMin = Array.BinarySearch(fixingDates, evalDate);

            if (ixMin < 0)
            {
                ixMin = ~ixMin;
            }

            Func <double, double> testFunc = (absK =>
            {
                var vols = fixingDates.Select((d, ix) => ix >= ixMin ? volSurface.GetVolForAbsoluteStrike(absK, d, forwards[ix]) : 0.0).ToArray();
                var pv = PV(forwards, fixingDates, evalDate, payDate, vols, absK, riskFree, callPut);
                return(targetPV - pv);
            });

            var solvedStrike = Math.Solvers.Brent.BrentsMethodSolve(testFunc, minStrike, maxStrike, 1e-8);

            return(solvedStrike);
        }