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; })); }
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); }
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); }
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); }
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); }
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)); }
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"); } }
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)); }
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); })); }
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)); }
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); }
//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); }
//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;
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)); }
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)); }
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); }
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)); }
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); }
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)); }
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); }