Exemplo n.º 1
0
        public void SolveSmileSimple()
        {
            var valDate = new DateTime(2018, 07, 28);
            var expDate = valDate.AddDays(365);
            var fwd     = 1000;

            double[] strikes = { 0.25, 0.5, 0.75 };

            var atmConstraint = new ATMStraddleConstraint
            {
                ATMVolType = AtmVolType.ZeroDeltaStraddle,
                MarketVol  = 0.32
            };

            var smile25d = new RRBFConstraint
            {
                Delta         = 0.25,
                FlyVol        = 0.01,
                RisykVol      = 0.02,
                WingQuoteType = WingQuoteType.Arithmatic
            };

            var s = new AssetSmileSolver();

            if (IsCoverageOnly)
            {
                s.Tollerance = 1;
            }

            var smile = s.Solve(atmConstraint, new[] { smile25d }, valDate, expDate, fwd, strikes, Interpolator1DType.Linear);

            if (!IsCoverageOnly)
            {
                Assert.Equal(atmConstraint.MarketVol, smile[1], 8);
                Assert.Equal(smile25d.RisykVol, smile[2] - smile[0], 8);
                Assert.Equal(smile25d.FlyVol, (smile[2] + smile[0]) / 2 - atmConstraint.MarketVol, 8);
            }
        }
Exemplo n.º 2
0
        public void SolveSmileMarket()
        {
            var valDate = new DateTime(2018, 07, 28);
            var expDate = valDate.AddDays(365);
            var tExp    = (expDate - valDate).TotalDays / 365.0;
            var fwd     = 1000;

            double[] strikes = { 0.25, 0.5, 0.75 };

            var atmConstraint = new ATMStraddleConstraint
            {
                ATMVolType = AtmVolType.ZeroDeltaStraddle,
                MarketVol  = 0.32
            };

            var smile25d = new RRBFConstraint
            {
                Delta         = 0.25,
                FlyVol        = 0.01,
                RisykVol      = 0.02,
                WingQuoteType = WingQuoteType.Market
            };

            var s = new AssetSmileSolver();

            if (IsCoverageOnly)
            {
                s.Tollerance = 1;
            }

            var smile = s.Solve(atmConstraint, new[] { smile25d }, valDate, expDate, fwd, strikes, Interpolator1DType.Linear);

            if (!IsCoverageOnly)
            {
                Assert.Equal(atmConstraint.MarketVol, smile[1], 8);
            }

            var surface = new GridVolSurface(valDate, strikes, new[] { expDate }, new[] { smile }, StrikeType.ForwardDelta, Interpolator1DType.Linear, Interpolator1DType.Linear, DayCountBasis.Act365F);

            //reprice market RR structrure off smile, premium must match
            var marketVolC  = atmConstraint.MarketVol + smile25d.FlyVol + 0.5 * smile25d.RisykVol;
            var marketVolP  = atmConstraint.MarketVol + smile25d.FlyVol - 0.5 * smile25d.RisykVol;
            var marketKC25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.25, 0, tExp, marketVolC);
            var marketKP25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.25, 0, tExp, marketVolP);
            var marketC25FV = BlackFunctions.BlackPV(fwd, marketKC25, 0, tExp, marketVolC, OptionType.C);
            var marketP25FV = BlackFunctions.BlackPV(fwd, marketKP25, 0, tExp, marketVolP, OptionType.P);
            var marketRR    = marketC25FV - marketP25FV;

            var volC25d  = surface.GetVolForAbsoluteStrike(marketKC25, expDate, fwd);
            var volP25d  = surface.GetVolForAbsoluteStrike(marketKP25, expDate, fwd);
            var call25FV = BlackFunctions.BlackPV(fwd, marketKC25, 0, tExp, volC25d, OptionType.C);
            var put25FV  = BlackFunctions.BlackPV(fwd, marketKP25, 0, tExp, volP25d, OptionType.P);
            var smileRR  = call25FV - put25FV;

            if (!IsCoverageOnly)
            {
                Assert.Equal(marketRR, smileRR, 8);
            }

            //reprice market BF structrure off smile, premium must match
            var marketVolBF   = atmConstraint.MarketVol + smile25d.FlyVol;
            var marketKBFC25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, 0.25, 0, tExp, marketVolBF);
            var marketKBFP25  = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.25, 0, tExp, marketVolBF);
            var marketBFC25FV = BlackFunctions.BlackPV(fwd, marketKBFC25, 0, tExp, marketVolBF, OptionType.C);
            var marketBFP25FV = BlackFunctions.BlackPV(fwd, marketKBFP25, 0, tExp, marketVolBF, OptionType.P);
            var marketBF      = marketBFC25FV + marketBFP25FV;

            var volCBF25d  = surface.GetVolForAbsoluteStrike(marketKBFC25, expDate, fwd);
            var volPBF25d  = surface.GetVolForAbsoluteStrike(marketKBFP25, expDate, fwd);
            var callBF25FV = BlackFunctions.BlackPV(fwd, marketKBFC25, 0, tExp, volCBF25d, OptionType.C);
            var putBF25FV  = BlackFunctions.BlackPV(fwd, marketKBFP25, 0, tExp, volPBF25d, OptionType.P);
            var smileBF    = callBF25FV + putBF25FV;

            if (!IsCoverageOnly)
            {
                Assert.Equal(marketBF, smileBF, 8);
            }
        }
Exemplo n.º 3
0
        public RiskyFlySurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                               double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                               Interpolator1DType strikeInterpType, Interpolator1DType timeInterpType, string[] pillarLabels = null)
        {
            if (pillarLabels == null)
            {
                PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray();
            }
            else
            {
                PillarLabels = pillarLabels;
            }

            if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length)
            {
                throw new Exception("Inputs do not have consistent time dimensions");
            }

            if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length)
            {
                throw new Exception("Inputs do not have consistent strike dimensions");
            }

            var strikes = new double[2 * wingDeltas.Length + 1];
            var vols    = new double[expiries.Length][];

            if (riskies.SelectMany(x => x).All(x => x == 0) && flies.SelectMany(x => x).All(x => x == 0))
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[wingDeltas.Length - 1 - s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s];
                }

                for (var t = 0; t < expiries.Length; t++)
                {
                    vols[t] = Enumerable.Repeat(ATMVols[t], strikes.Length).ToArray();
                }
            }
            else
            {
                var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint
                {
                    ATMVolType = atmVolType,
                    MarketVol  = a
                }).ToArray();

                var needsFlip = wingDeltas.First() > wingDeltas.Last();
                if (needsFlip)
                {
                    for (var s = 0; s < wingDeltas.Length; s++)
                    {
                        strikes[s] = wingDeltas[wingDeltas.Length - 1 - s];
                        strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s];
                    }
                }
                else
                {
                    for (var s = 0; s < wingDeltas.Length; s++)
                    {
                        strikes[s] = wingDeltas[s];
                        strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s];
                    }
                }
                strikes[wingDeltas.Length] = 0.5;

                var wingConstraints = new RRBFConstraint[expiries.Length][];
                var f = new AssetSmileSolver();

                if (needsFlip)
                {
                    for (var i = 0; i < wingConstraints.Length; i++)
                    {
                        var offset = wingDeltas.Length - 1;
                        wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                        for (var j = 0; j < wingConstraints[i].Length; j++)
                        {
                            wingConstraints[i][j] = new RRBFConstraint
                            {
                                Delta         = wingDeltas[offset - j],
                                FlyVol        = flies[i][offset - j],
                                RisykVol      = riskies[i][offset - j],
                                WingQuoteType = wingQuoteType,
                            };
                        }
                        vols[i] = f.Solve(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], strikes, strikeInterpType);
                    }
                }
                else
                {
                    for (var i = 0; i < wingConstraints.Length; i++)
                    {
                        wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                        for (var j = 0; j < wingConstraints[i].Length; j++)
                        {
                            wingConstraints[i][j] = new RRBFConstraint
                            {
                                Delta         = wingDeltas[j],
                                FlyVol        = flies[i][j],
                                RisykVol      = riskies[i][j],
                                WingQuoteType = wingQuoteType,
                            };
                        }
                        vols[i] = f.Solve(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], strikes, strikeInterpType);
                    }
                }
            }

            StrikeInterpolatorType = strikeInterpType;
            TimeInterpolatorType   = timeInterpType;
            Expiries       = expiries;
            ExpiriesDouble = expiries.Select(x => x.ToOADate()).ToArray();
            Strikes        = strikes;
            StrikeType     = StrikeType.ForwardDelta;

            ATMs          = ATMVols;
            Riskies       = riskies;
            Flies         = flies;
            WingDeltas    = wingDeltas;
            Forwards      = fwds;
            WingQuoteType = wingQuoteType;
            AtmVolType    = atmVolType;

            base.Build(originDate, strikes, expiries, vols);
        }
Exemplo n.º 4
0
        public SVIVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                             double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                             Interpolator1DType timeInterpType, SviType sviType = SviType.Raw, string[] pillarLabels = null) : base()
        {
            if (pillarLabels == null)
            {
                PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray();
            }
            else
            {
                PillarLabels = pillarLabels;
            }

            if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length)
            {
                throw new Exception("Inputs do not have consistent time dimensions");
            }

            if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length)
            {
                throw new Exception("Inputs do not have consistent strike dimensions");
            }

            var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint
            {
                ATMVolType = atmVolType,
                MarketVol  = a
            }).ToArray();

            var needsFlip = wingDeltas.First() > wingDeltas.Last();
            var strikes   = new double[2 * wingDeltas.Length + 1];

            if (needsFlip)
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[wingDeltas.Length - 1 - s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s];
                }
            }
            else
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s];
                }
            }
            strikes[wingDeltas.Length] = 0.5;

            var wingConstraints = new RRBFConstraint[expiries.Length][];

            RawParams = new SviRawParameters[expiries.Length];
            var f = new AssetSmileSolver();

            if (needsFlip)
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    var offset = wingDeltas.Length - 1;
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[offset - j],
                            FlyVol        = flies[i][offset - j],
                            RisykVol      = riskies[i][offset - j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true);
                }
            }
            else
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[j],
                            FlyVol        = flies[i][j],
                            RisykVol      = riskies[i][j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true);
                }
            }

            OriginDate           = originDate;
            TimeInterpolatorType = timeInterpType;
            Expiries             = expiries;
            ExpiriesDouble       = expiries.Select(x => originDate.CalculateYearFraction(x, TimeBasis)).ToArray();

            _interps    = new IInterpolator1D[5];
            _interps[0] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.A).ToArray(), TimeInterpolatorType);
            _interps[1] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.B).ToArray(), TimeInterpolatorType);
            _interps[2] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.M).ToArray(), TimeInterpolatorType);
            _interps[3] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Rho).ToArray(), TimeInterpolatorType);
            _interps[4] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Sigma).ToArray(), TimeInterpolatorType);
            _fwdsInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, Interpolator1DType.Linear);
        }
Exemplo n.º 5
0
        public SabrVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas,
                              double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType,
                              Interpolator1DType timeInterpType, string[] pillarLabels = null)
        {
            if (pillarLabels == null)
            {
                PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray();
            }
            else
            {
                PillarLabels = pillarLabels;
            }

            if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length)
            {
                throw new Exception("Inputs do not have consistent time dimensions");
            }

            if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length)
            {
                throw new Exception("Inputs do not have consistent strike dimensions");
            }

            var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint
            {
                ATMVolType = atmVolType,
                MarketVol  = a
            }).ToArray();

            var needsFlip = wingDeltas.First() > wingDeltas.Last();
            var strikes   = new double[2 * wingDeltas.Length + 1];

            if (needsFlip)
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[wingDeltas.Length - 1 - s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s];
                }
            }
            else
            {
                for (var s = 0; s < wingDeltas.Length; s++)
                {
                    strikes[s] = wingDeltas[s];
                    strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s];
                }
            }
            strikes[wingDeltas.Length] = 0.5;

            var wingConstraints = new RRBFConstraint[expiries.Length][];
            var parameters      = new SABRParameters[expiries.Length];
            var f = new AssetSmileSolver();

            if (needsFlip)
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    var offset = wingDeltas.Length - 1;
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[offset - j],
                            FlyVol        = flies[i][offset - j],
                            RisykVol      = riskies[i][offset - j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0);
                }
            }
            else
            {
                for (var i = 0; i < wingConstraints.Length; i++)
                {
                    wingConstraints[i] = new RRBFConstraint[wingDeltas.Length];
                    for (var j = 0; j < wingConstraints[i].Length; j++)
                    {
                        wingConstraints[i][j] = new RRBFConstraint
                        {
                            Delta         = wingDeltas[j],
                            FlyVol        = flies[i][j],
                            RisykVol      = riskies[i][j],
                            WingQuoteType = wingQuoteType,
                        };
                    }
                    parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0);
                }
            }

            OriginDate           = originDate;
            TimeInterpolatorType = timeInterpType;
            Expiries             = expiries;
            ExpiriesDouble       = expiries.Select(x => originDate.CalculateYearFraction(x, TimeBasis)).ToArray();

            Alphas = parameters.Select(x => x.Alpha).ToArray();
            Betas  = parameters.Select(x => x.Beta).ToArray();
            Nus    = parameters.Select(x => x.Nu).ToArray();
            Rhos   = parameters.Select(x => x.Rho).ToArray();

            _alphaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Alphas, TimeInterpolatorType);
            _betaInterp  = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Betas, TimeInterpolatorType);
            _rhoInterp   = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Rhos, TimeInterpolatorType);
            _nuInterp    = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Nus, TimeInterpolatorType);
            _fwdsInterp  = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, TimeInterpolatorType);
        }