Пример #1
0
        public static object CreateConstantHazzardCurve(
            [ExcelArgument(Description = "Object name")] string ObjectName,
            [ExcelArgument(Description = "Hazzard rate")] double HazzardRate,
            [ExcelArgument(Description = "Build date")] DateTime BuildDate,
            [ExcelArgument(Description = "Basis, default Act365F")] object Basis)
        {
            return(ExcelHelper.Execute(_logger, () =>
            {
                var basis = Basis.OptionalExcel("Act365F");
                if (!Enum.TryParse(basis, out DayCountBasis dayCountBasis))
                {
                    throw new Exception($"Could not parse basis type - {basis}");
                }

                var cObj = new HazzardCurve(BuildDate, dayCountBasis, new ConstantHazzardInterpolator(HazzardRate))
                {
                    ConstantPD = HazzardRate
                };
                var cache = ContainerStores.GetObjectCache <HazzardCurve>();
                cache.PutObject(ObjectName, new SessionItem <HazzardCurve> {
                    Name = ObjectName, Value = cObj
                });
                return ObjectName + '¬' + cache.GetObject(ObjectName).Version;
            }));
        }
Пример #2
0
        public double PV_LinearApprox(HazzardCurve hazzardCurve, IIrCurve discountCurve, double recoveryRate, bool payAccruedOnDefault = true)
        {
            var nodeDates = DatePeriodType.M.GenerateDateSchedule(hazzardCurve.OriginDate, FinalSensitivityDate);
            var ts        = nodeDates.Select(d => discountCurve.BuildDate.CalculateYearFraction(d, DayCountBasis.ACT365F)).ToArray();

            var integrandD = new Func <DateTime, double> (d => discountCurve.GetDf(discountCurve.BuildDate, d) * -hazzardCurve.GetSurvivalProbabilitySlope(d));
            var integrandT = new Func <double, double>(t => integrandD(OriginDate.AddYearFraction(t, DayCountBasis.ACT365F)));

            //contingent leg
            var pv = (1.0 - recoveryRate) * Notional * Integration.SimpsonsRuleExtended(integrandT, 0, ts.Last(), 100);

            //fixed leg
            foreach (var f in FixedSchedule.Flows)
            {
                pv -= f.Notional * f.YearFraction * Spread * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate) * hazzardCurve.GetSurvivalProbability(f.SettleDate);
                if (payAccruedOnDefault)
                {
                    pv -= 0.5 * f.Notional * f.YearFraction * Spread
                          * hazzardCurve.GetDefaultProbability(f.AccrualPeriodStart, f.AccrualPeriodEnd)
                          * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate);
                }
            }

            return(pv);
        }
Пример #3
0
        public static (double CVA, double CCR) PvCapital_Split(DateTime originDate, DateTime[] EADDates, IAssetFxModel[] models,
                                                               Portfolio portfolio, HazzardCurve hazzardCurve, Currency reportingCurrency, IIrCurve discountCurve, double LGD, double partyCVAWeight, double riskWeight,
                                                               Dictionary <string, string> assetIdToHedgeMap, Dictionary <string, double> hedgeGroupCCFs, ICurrencyProvider currencyProvider, double[] epeProfile,
                                                               DateTime?B2B3ChangeDate = null, double[] eadProfile = null)
        {
            var pd = hazzardCurve.ConstantPD;

            if (!B2B3ChangeDate.HasValue)
            {
                B2B3ChangeDate = DateTime.MaxValue;
            }

            var eads = eadProfile ?? EAD_Split(originDate, EADDates, epeProfile, models, portfolio, reportingCurrency, assetIdToHedgeMap, hedgeGroupCCFs, B2B3ChangeDate.Value, currencyProvider);

            eads = eads.Select(e => e * riskWeight).ToArray();

            var Ms  = EADDates.Select(d => Max(1.0, portfolio.WeightedMaturity(d))).ToArray();
            var dfs = Ms.Select(m => m == 0 ? 1.0 : (1.0 - Exp(-0.05 * m)) / (0.05 * m)).ToArray();

            var ksCCR = eads.Select((e, ix) => BaselHelper.K(pd, LGD, Ms[ix]) * e).ToArray();
            var ksCVA = eads.Select((e, ix) => XVACalculator.Capital_BaselII_CVA_SM(e * dfs[ix], Ms[ix], partyCVAWeight)).ToArray();

            var pvCapitalCCR = PvProfile(originDate, EADDates, ksCCR, discountCurve);
            var pvCapitalCVA = PvProfile(originDate, EADDates, ksCVA, discountCurve);

            return(pvCapitalCVA, pvCapitalCCR);
        }
Пример #4
0
        public double PV_SmallSteps(HazzardCurve hazzardCurve, IIrCurve discountCurve, double recoveryRate, bool payAccruedOnDefault = true)
        {
            var nodeDates = DatePeriodType.M.GenerateDateSchedule(hazzardCurve.OriginDate, FinalSensitivityDate);

            //contingent leg
            var pv = 0.0;

            for (var i = 1; i < nodeDates.Length; i++)
            {
                pv += discountCurve.GetDf(discountCurve.BuildDate, nodeDates[i])
                      * hazzardCurve.GetDefaultProbability(nodeDates[i - 1], nodeDates[i]);
            }

            pv *= (1.0 - recoveryRate) * Notional;

            //fixed leg
            foreach (var f in FixedSchedule.Flows)
            {
                pv -= f.Notional * f.YearFraction * Spread * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate) * hazzardCurve.GetSurvivalProbability(f.SettleDate);
                if (payAccruedOnDefault)
                {
                    pv -= 0.5 * f.Notional * f.YearFraction * Spread
                          * hazzardCurve.GetDefaultProbability(f.AccrualPeriodStart, f.AccrualPeriodEnd)
                          * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate);
                }
            }


            return(pv);
        }
        private double[] ComputePVs()
        {
            var o       = new double[_numberOfInstruments];
            var hzCurve = new HazzardCurve(_buildDate, _basis, _currentCurve);

            for (var i = 0; i < o.Length; i++)
            {
                o[i] = UseSmallSteps ?
                       _curveInstruments[i].PV_SmallSteps(hzCurve, _discountCurve, _recoveryRate, true) :
                       _curveInstruments[i].PV_PiecewiseFlat(hzCurve, _discountCurve, _recoveryRate, true);
            }
            return(o);
        }
Пример #6
0
        public static double PvCcrCapital_BII_SM(DateTime originDate, DateTime[] EADDates, IAssetFxModel[] models, Portfolio portfolio,
                                                 HazzardCurve hazzardCurve, Currency reportingCurrency, IIrCurve discountCurve, double LGD, Dictionary <string, string> assetIdToHedgeMap,
                                                 Dictionary <string, double> hedgeGroupCCFs, ICurrencyProvider currencyProvider, double[] epeProfile, double[] eadProfile = null)
        {
            var pd   = hazzardCurve.ConstantPD;
            var eads = eadProfile ?? EAD_BII_SM(originDate, EADDates, epeProfile, models, portfolio, reportingCurrency, assetIdToHedgeMap, hedgeGroupCCFs, currencyProvider);

            var Ms = EADDates.Select(d => Max(1.0, portfolio.WeightedMaturity(d))).ToArray();
            var ks = eads.Select((e, ix) => BaselHelper.K(pd, LGD, Ms[ix]) * e).ToArray();

            var pvCapital = PvProfile(originDate, EADDates, ks, discountCurve);

            return(pvCapital);
        }
Пример #7
0
        public void HazzardCurveFact()
        {
            var hzi    = new Math.Interpolation.ConstantHazzardInterpolator(0.1);
            var origin = new DateTime(2019, 05, 28);
            var hz     = new HazzardCurve(origin, Dates.DayCountBasis.Act365F, hzi);

            Assert.Equal(1.0, hz.GetSurvivalProbability(origin, origin));
            Assert.Equal(1.0, hz.GetSurvivalProbability(origin));
            Assert.Equal(hzi.Interpolate(1.0 / 365.0), hz.GetSurvivalProbability(origin, origin.AddDays(1)));

            var dfCurve = new ConstantRateIrCurve(0.05, origin, "zzz", TestProviderHelper.CurrencyProvider.GetCurrency("USD"));

            var df = dfCurve.GetDf(origin, origin.AddDays(100));

            Assert.Equal(df, hz.RiskyDiscountFactor(origin, origin.AddDays(100), dfCurve, 0.0));
            Assert.Equal(df * (1.0 - (1.0 - hzi.Interpolate(100.0 / 365)) * 0.5), hz.RiskyDiscountFactor(origin, origin.AddDays(100), dfCurve, 0.5));
        }
Пример #8
0
        public static double SolveStrikeForGrossRoC(this Portfolio portfolio, IAssetFxModel model, double targetRoC, Currency reportingCurrency,
                                                    HazzardCurve hazzardCurve, double LGD, double xVA_LGD, double partyRiskWeight, double cvaCapitalWeight, IIrCurve discountCurve,
                                                    ICurrencyProvider currencyProvider, Dictionary <string, string> assetIdToHedgeMap, Dictionary <string, double> hedgeGroupCCFs)
        {
            var insList = portfolio.Instruments.Select(x => x as IAssetInstrument).ToList();

            if (insList.Any(x => x == null))
            {
                throw new Exception("Not all instruments in the portfolio implement IAssetInstrument");
            }

            var rolledModels = new Dictionary <DateTime, IAssetFxModel>();
            var d            = model.BuildDate;
            var lastModel    = model;

            while (d <= portfolio.LastSensitivityDate)
            {
                rolledModels.Add(d, lastModel);
                d         = d.AddDays(1);
                lastModel = lastModel.RollModel(d, currencyProvider);
            }

            var targetFunc = new Func <double, double>(k =>
            {
                var newPf = new Portfolio()
                {
                    Instruments = insList.Select(i => (IInstrument)i.SetStrike(k)).ToList()
                };
                var roc = newPf.GrossRoC(model, reportingCurrency, hazzardCurve, LGD, xVA_LGD, cvaCapitalWeight, partyRiskWeight, discountCurve, currencyProvider, rolledModels, assetIdToHedgeMap, hedgeGroupCCFs);
                return(roc - targetRoC);
            });

            var firstGuess = insList.Average(i => i.ParRate(model));

            var solvedStrike = Math.Solvers.Newton1D.MethodSolve(targetFunc, firstGuess, 1e-8, 1000, 1e-9);

            if (System.Math.Abs(targetFunc(solvedStrike)) < 1e-8)
            {
                return(solvedStrike);
            }
            else
            {
                throw new Exception("Failed to find solution after 1000 itterations");
            }
        }
Пример #9
0
        public static double CVA(DateTime originDate, ICube EPE, HazzardCurve hazzardCurve, IIrCurve discountCurve, double LGD)
        {
            if (!EPE.DataTypes.TryGetValue("ExposureDate", out var type) || type != typeof(DateTime))
            {
                throw new Exception("EPE cube input not valid");
            }

            var rows      = EPE.GetAllRows();
            var dateIx    = EPE.GetColumnIndex("ExposureDate");
            var epeDates  = new DateTime[rows.Length];
            var epeValues = new double[rows.Length];

            for (var i = 0; i < rows.Length; i++)
            {
                epeDates[i]  = (DateTime)rows[i].MetaData[dateIx];
                epeValues[i] = rows[i].Value;
            }
            return(CVA(originDate, epeDates, epeValues, hazzardCurve, discountCurve, LGD));
        }
Пример #10
0
        public static object CreateConstantHazzardCurve(
            [ExcelArgument(Description = "Object name")] string ObjectName,
            [ExcelArgument(Description = "Hazzard rate")] double HazzardRate,
            [ExcelArgument(Description = "Build date")] DateTime BuildDate,
            [ExcelArgument(Description = "Basis, default Act365F")] object Basis)
        {
            return(ExcelHelper.Execute(_logger, () =>
            {
                var basis = Basis.OptionalExcel("Act365F");
                if (!Enum.TryParse(basis, out DayCountBasis dayCountBasis))
                {
                    throw new Exception($"Could not parse basis type - {basis}");
                }

                var cObj = new HazzardCurve(BuildDate, dayCountBasis, new ConstantHazzardInterpolator(HazzardRate))
                {
                    ConstantPD = HazzardRate
                };

                return ExcelHelper.PushToCache(cObj, ObjectName);
            }));
        }
Пример #11
0
        public void ComputeCVAFacts()
        {
            var hz    = new HazzardCurve(DateTime.Today, DayCountBasis.Act365F, new DummyPointInterpolator(0.0));
            var disco = new FlatIrCurve(0.0, ContainerStores.CurrencyProvider.GetCurrency("ZAR"), "disco");

            ContainerStores.GetObjectCache <HazzardCurve>().PutObject("hz", new SessionItem <HazzardCurve>()
            {
                Name = "hz", Value = hz
            });
            ContainerStores.GetObjectCache <IIrCurve>().PutObject("disco", new SessionItem <IIrCurve>()
            {
                Name = "disco", Value = disco
            });

            Assert.Equal("Hazzard curve blash not found", CapitalFunctions.ComputeCVA("blash", DateTime.Today, "woo", null, 0.0));
            Assert.Equal("Discount curve woo not found", CapitalFunctions.ComputeCVA("hz", DateTime.Today, "woo", null, 0.0));
            Assert.Equal("Expected Nx2 array for EPE", CapitalFunctions.ComputeCVA("hz", DateTime.Today, "disco", new object[1, 1], 0.0));
            Assert.Equal("EPE profile must be cube reference or Nx2 array", CapitalFunctions.ComputeCVA("hz", DateTime.Today, "disco", 7, 0.0));

            Assert.Equal(0.0, CapitalFunctions.ComputeCVA("hz", DateTime.Today, "disco", new object[1, 2] {
                { DateTime.Today, 0.0 }
            }, 0.0));
        }
Пример #12
0
        public void CDSBasicFacts_LinearApprox()
        {
            var origin = new DateTime(2020, 06, 15);
            var hzi    = new ConstantHazzardInterpolator(0.0);
            var hz     = new HazzardCurve(origin, DayCountBasis.ACT365F, hzi);
            var usd    = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var df     = new ConstantRateIrCurve(0.00, origin, "LIBOR", usd);

            var sut = new CDS()
            {
                Basis      = DayCountBasis.ACT365F,
                Currency   = usd,
                OriginDate = origin,
                Tenor      = new Frequency("1y"),
                Spread     = 0.01,
                Notional   = 1e6
            };

            sut.Init();

            var pv = sut.PV_LinearApprox(hz, df, 0.4, false);

            Assert.Equal(-sut.Notional * sut.Spread, pv);
        }
Пример #13
0
        //http://www.bnikolic.co.uk/cds/cdsvaluation.html
        //var contingentLeg = (1.0 - recoveryRate) *
        public double PV_PiecewiseFlat(HazzardCurve hazzardCurve, IIrCurve discountCurve, double recoveryRate, bool payAccruedOnDefault = true)
        {
            var nodeDates = FixedSchedule.Flows.Select(f => f.AccrualPeriodEnd).ToArray();
            var pv        = 0.0;

            //contingent leg
            var d = hazzardCurve.OriginDate;

            foreach (var nd in nodeDates)
            {
                var deltaT = d.CalculateYearFraction(nd, hazzardCurve.Basis);
                var s      = hazzardCurve.GetSurvivalProbability(d);
                var dd     = discountCurve.GetDf(discountCurve.BuildDate, d);
                var lambda = System.Math.Log(s / hazzardCurve.GetSurvivalProbability(nd)) / deltaT;
                var f      = System.Math.Log(dd / discountCurve.GetDf(discountCurve.BuildDate, nd)) / deltaT;
                var term1  = (lambda == 0 && f == 0) ? 1.0 : lambda / (lambda + f);
                pv += term1 * (1.0 - System.Math.Exp(-deltaT * (lambda + f))) * s * dd;
                d   = nd;
            }

            pv *= (1.0 - recoveryRate) * Notional;

            //fixed leg
            foreach (var f in FixedSchedule.Flows)
            {
                pv -= f.Notional * f.YearFraction * Spread * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate) * hazzardCurve.GetSurvivalProbability(f.SettleDate);
                if (payAccruedOnDefault)
                {
                    pv -= 0.5 * f.Notional * f.YearFraction * Spread
                          * hazzardCurve.GetDefaultProbability(f.AccrualPeriodStart, f.AccrualPeriodEnd)
                          * discountCurve.GetDf(discountCurve.BuildDate, f.SettleDate);
                }
            }

            return(pv);
        }
Пример #14
0
 //http://www.bnikolic.co.uk/cds/cdsvaluation.html
 //var contingentLeg = (1.0 - recoveryRate) *
 public double PV(HazzardCurve hazzardCurve, ICurve discountCurve, double recoveryRate, bool payAccruedOnDefault = true) => 0;
Пример #15
0
 public static double CVA(DateTime originDate, ICube EPE, HazzardCurve hazzardCurve, IIrCurve discountCurve, double LGD)
 {
     (var epeDates, var epeValues) = CubeToExposures(EPE);
     return(CVA(originDate, epeDates, epeValues, hazzardCurve, discountCurve, LGD));
 }
Пример #16
0
        public static double CVA_Approx(DateTime[] exposureDates, Portfolio portfolio, HazzardCurve hazzardCurve, IAssetFxModel model, IIrCurve discountCurve, double LGD, Currency reportingCurrency, ICurrencyProvider currencyProvider, Dictionary <DateTime, IAssetFxModel> models = null)
        {
            var exposures = EPE_Approx(exposureDates, portfolio, model, reportingCurrency, currencyProvider, models);

            return(CVA(model.BuildDate, exposureDates, exposures, hazzardCurve, discountCurve, LGD));
        }
Пример #17
0
        public static double CVA(DateTime originDate, DateTime[] EPEDates, double[] EPEExposures, HazzardCurve hazzardCurve, IIrCurve discountCurve, double LGD)
        {
            if (EPEDates.Length != EPEExposures.Length)
            {
                throw new Exception("Number of EPE dates and EPE values must be equal");
            }

            var lastDate = originDate;
            var cva      = 0.0;

            for (var i = 0; i < EPEDates.Length; i++)
            {
                if (EPEDates[i] < originDate)
                {
                    continue;
                }

                var pDefault = hazzardCurve.GetDefaultProbability(lastDate, EPEDates[i]);
                var df       = discountCurve.GetDf(originDate, EPEDates[i]);
                cva += EPEExposures[i] * pDefault * df * LGD;

                lastDate = EPEDates[i];
            }

            return(-cva);
        }
Пример #18
0
        public static (double FBA, double FCA) FVA(DateTime originDate, ICube EPE, ICube ENE, HazzardCurve hazzardCurve, IIrCurve discountCurve, IIrCurve fundingCurve)
        {
            if (!EPE.DataTypes.TryGetValue("ExposureDate", out var type) || type != typeof(DateTime))
            {
                throw new Exception("EPE cube input not valid");
            }

            if (!ENE.DataTypes.TryGetValue("ExposureDate", out var type2) || type2 != typeof(DateTime))
            {
                throw new Exception("ENE cube input not valid");
            }

            var rowsEPE = EPE.GetAllRows();
            var rowsENE = ENE.GetAllRows();

            if (rowsEPE.Length != rowsENE.Length)
            {
                throw new Exception("EPE and ENE curves not of same size");
            }

            var dateIx    = EPE.GetColumnIndex("ExposureDate");
            var epeDates  = new DateTime[rowsEPE.Length];
            var epeValues = new double[rowsEPE.Length];
            var eneValues = new double[rowsENE.Length];

            for (var i = 0; i < rowsENE.Length; i++)
            {
                epeDates[i]  = (DateTime)rowsEPE[i].MetaData[dateIx];
                epeValues[i] = rowsEPE[i].Value;
                eneValues[i] = rowsENE[i].Value;
            }
            return(FVA(originDate, epeDates, epeValues, eneValues, hazzardCurve, discountCurve, fundingCurve));
        }
Пример #19
0
        public static (double FBA, double FCA) FVA(DateTime originDate, DateTime[] ExEDates, double[] EPEExposures, double[] ENEExposures, HazzardCurve hazzardCurve, IIrCurve discountCurve, IIrCurve fundingCurve)
        {
            if (ExEDates.Length != EPEExposures.Length)
            {
                throw new Exception("Number of EPE dates and EPE values must be equal");
            }

            if (ExEDates.Length != ENEExposures.Length)
            {
                throw new Exception("Number of ENE dates and ENE values must be equal");
            }


            var lastDate = originDate;
            var fba      = 0.0;
            var fca      = 0.0;

            for (var i = 0; i < ExEDates.Length; i++)
            {
                if (ExEDates[i] < originDate)
                {
                    continue;
                }

                var pSurvival = hazzardCurve.GetSurvivalProbability(lastDate, ExEDates[i]);
                var fwdDf     = fundingCurve.GetDf(lastDate, ExEDates[i]) / discountCurve.GetDf(lastDate, ExEDates[i]);
                var df        = fundingCurve.GetDf(originDate, ExEDates[i]);
                fba += ENEExposures[i] * pSurvival / fwdDf * df;
                fca += EPEExposures[i] * pSurvival / fwdDf * df;

                lastDate = ExEDates[i];
            }
            return(fba, fca);
        }
Пример #20
0
 public static double PVCapital_BII_IMM(DateTime originDate, ICube expectedEAD, HazzardCurve hazzardCurve, IIrCurve discountCurve, double LGD, Portfolio portfolio)
 {
     (var eadDates, var eadValues) = XVACalculator.CubeToExposures(expectedEAD);
     return(PVCapital_BII_IMM(originDate, eadDates, eadValues, hazzardCurve, discountCurve, LGD, portfolio));
 }
Пример #21
0
        public static double PVCapital_BII_IMM(DateTime originDate, DateTime[] EADDates, double[] EADs, HazzardCurve hazzardCurve,
                                               IIrCurve discountCurve, double LGD, Portfolio portfolio)
        {
            if (EADDates.Length != EADs.Length)
            {
                throw new Exception("Number of EPE dates and EPE values must be equal");
            }

            var pd    = hazzardCurve.ConstantPD;
            var epees = EADs.Select((d, ix) => EADs.Skip(ix).Max()).ToArray();
            var Ms    = EADDates.Select(d => Max(1.0, portfolio.WeightedMaturity(d))).ToArray();
            var ks    = epees.Select((e, ix) => BaselHelper.K(pd, LGD, Ms[ix]) * e * 1.4).ToArray();

            var pvCapital = PvProfile(originDate, EADDates, ks, discountCurve);

            return(pvCapital);
        }