public static object CreateDiscountCurveFromCCRates( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Curve name")] object CurveName, [ExcelArgument(Description = "Build date")] DateTime BuildDate, [ExcelArgument(Description = "Array of pillar dates")] double[] Pillars, [ExcelArgument(Description = "Array of CC zero rates")] double[] ZeroRates, [ExcelArgument(Description = "Type of interpolation")] object InterpolationType, [ExcelArgument(Description = "Currency - default USD")] object Currency, [ExcelArgument(Description = "Collateral Spec - default LIBOR.3M")] object CollateralSpec) { return(ExcelHelper.Execute(_logger, () => { var curveName = CurveName.OptionalExcel(ObjectName); var curveTypeStr = InterpolationType.OptionalExcel("Linear"); var ccyStr = Currency.OptionalExcel("USD"); var colSpecStr = CollateralSpec.OptionalExcel("LIBOR.3M"); if (!Enum.TryParse(curveTypeStr, out Interpolator1DType iType)) { return $"Could not parse interpolator type - {curveTypeStr}"; } var pDates = Pillars.ToDateTimeArray(); ContainerStores.SessionContainer.GetService <ICalendarProvider>().Collection.TryGetCalendar(ccyStr, out var ccyCal); var ccy = ContainerStores.GlobalContainer.GetRequiredService <ICurrencyProvider>()[ccyStr]; var cObj = new IrCurve(pDates, ZeroRates, BuildDate, curveName, iType, ccy, colSpecStr); var cache = ContainerStores.GetObjectCache <IIrCurve>(); cache.PutObject(ObjectName, new SessionItem <IIrCurve> { Name = ObjectName, Value = cObj }); return ObjectName + '¬' + cache.GetObject(ObjectName).Version; })); }
public static object CreateDiscountCurveFromRates( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Curve name")] object CurveName, [ExcelArgument(Description = "Build date")] DateTime BuildDate, [ExcelArgument(Description = "Array of pillar dates")] double[] Pillars, [ExcelArgument(Description = "Array of rates")] double[] ZeroRates, [ExcelArgument(Description = "Rate type, e.g. CC or Linear")] object RateType, [ExcelArgument(Description = "Type of interpolation, e.g. CubicSpline or Linear")] object InterpolationType, [ExcelArgument(Description = "Currency - default USD")] object Currency, [ExcelArgument(Description = "Collateral Spec - default LIBOR.3M")] object CollateralSpec) { return(ExcelHelper.Execute(_logger, () => { var curveName = CurveName.OptionalExcel(ObjectName); var ccyStr = Currency.OptionalExcel("USD"); var colSpecStr = CollateralSpec.OptionalExcel("LIBOR.3M"); if (!Enum.TryParse(InterpolationType.OptionalExcel("Linear"), out Interpolator1DType iType)) { return $"Could not parse interpolator type - {InterpolationType}"; } if (!Enum.TryParse(RateType.OptionalExcel("CC"), out RateType rType)) { return $"Could not parse rate type - {RateType}"; } var pDates = Pillars.ToDateTimeArray(); ContainerStores.SessionContainer.GetService <ICalendarProvider>().Collection.TryGetCalendar(ccyStr, out var ccyCal); var ccy = ContainerStores.GlobalContainer.GetRequiredService <ICurrencyProvider>().GetCurrency(ccyStr); var cObj = new IrCurve(pDates, ZeroRates, BuildDate, curveName, iType, ccy, colSpecStr, rType); return ExcelHelper.PushToCache <IIrCurve>(cObj, ObjectName); })); }
public void StripCrackedCurveSimple() { var buildDate = new DateTime(2018, 07, 28); string[] periods = { "AUG18" }; double[] strikes = { -10 }; var cal = TestProviderHelper.CalendarProvider.Collection["LON"]; var usd = TestProviderHelper.CurrencyProvider["USD"]; var bPillars = new[] { buildDate, buildDate.AddDays(100) }; var brentCurve = new PriceCurve(buildDate, bPillars, new[] { 100.0, 100.0 }, PriceCurveType.Linear, TestProviderHelper.CurrencyProvider) { AssetId = "Brent" }; var instruments = periods.Select((p, ix) => (IAssetInstrument)AssetProductFactory.CreateTermAsianBasisSwap(p, strikes[ix], "Brent", "Sing180", cal, cal, cal, 0.Bd(), usd, 0.Bd(), 0.Bd(), 1000, 1000 / 6.35)) .ToList(); var pillars = instruments.Select(x => ((AsianBasisSwap)x).RecSwaplets.Max(sq => sq.AverageEndDate)).ToList(); DateTime[] dPillars = { buildDate, buildDate.AddDays(1000) }; double[] dRates = { 0, 0 }; var discountCurve = new IrCurve(dPillars, dRates, buildDate, "zeroDiscount", Interpolator1DType.LinearFlatExtrap, usd); var s = new Calibrators.NewtonRaphsonAssetBasisCurveSolver(TestProviderHelper.CurrencyProvider); var curve = s.SolveCurve(instruments, pillars, discountCurve, brentCurve, buildDate, PriceCurveType.Linear); Assert.Equal((100.0 - 10.0) * 6.35, curve.GetPriceForDate(buildDate)); Assert.Equal((100.0 - 10.0) * 6.35, curve.GetPriceForDate(buildDate.AddDays(50))); }
public Dictionary <string, IrCurve> ImplyContainedCurves(DateTime buildDate, Interpolator1DType interpType) { var o = new Dictionary <string, IrCurve>(); foreach (var curveName in SolveCurves) { var pillars = this.Where(x => x.SolveCurve == curveName) .Select(x => x.PillarDate) .OrderBy(x => x) .ToArray(); if (pillars.Distinct().Count() != pillars.Count()) { throw new Exception($"More than one instrument has the same solve pillar on curve {curveName}"); } var dummyRates = pillars.Select(x => 0.05).ToArray(); var ccy = _currencyProvider.GetCurrency(curveName.Split('.')[0]); var colSpec = (curveName.Contains("[")) ? curveName.Split('[').Last().Trim("[]".ToCharArray()) : curveName.Split('.').Last(); if (o.Values.Any(v => v.CollateralSpec == colSpec)) { colSpec = colSpec + "_" + curveName; } var irCurve = new IrCurve(pillars, dummyRates, buildDate, curveName, interpType, ccy, colSpec); o.Add(curveName, irCurve); } return(o); }
public void LessComplexCurve() { var startDate = new DateTime(2016, 05, 20); var depoTenors = new Frequency[] { 3.Months() }; var OISdepoTenors = new Frequency[] { 1.Bd() }; double[] depoPricesZAR = { 0.06 }; string[] FRATenors = { "3x6", "6x9", "9x12", "12x15", "15x18", "18x21", "21x24" }; double[] FRAPricesZAR = { 0.065, 0.07, 0.075, 0.077, 0.08, 0.081, 0.082 }; var ZARpillarDatesDepo = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, _jhb, x)).ToArray(); var ZARpillarDatesFRA = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, _jhb, new Frequency(x.Split('x')[1] + "M"))).ToArray(); var ZARpillarDates3m = ZARpillarDatesDepo.Union(ZARpillarDatesFRA).Distinct().OrderBy(x => x).ToArray(); var ZARdepos = new IrSwap[depoTenors.Length]; var ZARFRAs = new ForwardRateAgreement[FRATenors.Length]; var FIC = new FundingInstrumentCollection(); for (var i = 0; i < FRATenors.Length; i++) { ZARFRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPricesZAR[i], _zar3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "ZAR.JIBAR.3M", "ZAR.JIBAR.3M") { SolveCurve = "ZAR.JIBAR.3M" }; FIC.Add(ZARFRAs[i]); } for (var i = 0; i < depoTenors.Length; i++) { ZARdepos[i] = new IrSwap(startDate, depoTenors[i], _zar3m, depoPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.JIBAR.3M") { SolveCurve = "ZAR.JIBAR.3M" }; FIC.Add(ZARdepos[i]); } var ZARcurve3m = new IrCurve(ZARpillarDates3m, new double[ZARpillarDates3m.Length], startDate, "ZAR.JIBAR.3M", Interpolator1DType.LinearFlatExtrap) { SolveStage = 0 }; var engine = new FundingModel(startDate, new IrCurve[] { ZARcurve3m }); var S = new NewtonRaphsonMultiCurveSolverStagedWithAnalyticJacobian(); //var S = new NewtonRaphsonMultiCurveSolverStaged(); S.Solve(engine, FIC); foreach (var ins in FIC) { var pv = ins.Pv(engine, false); Assert.Equal(0.0, pv, 7); } }
private AssetFxMCModel GetSut() { var buildDate = DateTime.Parse("2018-10-04"); var usd = TestProviderHelper.CurrencyProvider["USD"]; TestProviderHelper.CalendarProvider.Collection.TryGetCalendar("NYC", out var usdCal); var dfCurve = new IrCurve(new[] { buildDate, buildDate.AddDays(1000) }, new[] { 0.0, 0.0 }, buildDate, "disco", Interpolator1DType.Linear, usd, "DISCO"); var comCurve = new BasicPriceCurve(buildDate, new[] { buildDate, buildDate.AddDays(15), buildDate.AddDays(100) }, new[] { 100.0, 100.0, 100.0 }, PriceCurveType.NYMEX, TestProviderHelper.CurrencyProvider) { Name = "CL", AssetId = "CL" }; var comSurface = new ConstantVolSurface(buildDate, 0.32) { AssetId = "CL" }; var fModel = new FundingModel(buildDate, new Dictionary <string, IrCurve> { { "DISCO", dfCurve } }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var fxM = new FxMatrix(TestProviderHelper.CurrencyProvider); fxM.Init(usd, buildDate, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> { { usd, "DISCO" } }); fModel.SetupFx(fxM); var aModel = new AssetFxModel(buildDate, fModel); aModel.AddVolSurface("CL", comSurface); aModel.AddPriceCurve("CL", comCurve); var product = AssetProductFactory.CreateAsianOption(buildDate.AddDays(10), buildDate.AddDays(20), 101, "CL", OptionType.Call, usdCal, buildDate.AddDays(21), usd); product.TradeId = "waaah"; product.DiscountCurve = "DISCO"; var pfolio = new Portfolio { Instruments = new List <IInstrument> { product } }; var settings = new McSettings { Generator = RandomGeneratorType.MersenneTwister, NumberOfPaths = (int)System.Math.Pow(2, 13), NumberOfTimesteps = 1, ReportingCurrency = usd, Parallelize = false, CreditSettings = new CreditSettings { ExposureDates = new DateTime[] { buildDate.AddDays(5), buildDate.AddDays(20), buildDate.AddDays(22) } }, }; var sut = new AssetFxMCModel(buildDate, pfolio, aModel, settings, TestProviderHelper.CurrencyProvider, TestProviderHelper.FutureSettingsProvider, TestProviderHelper.CalendarProvider); return(sut); }
public void OISFuture() { var bd = DateTime.Today; var pillars = new[] { bd, bd.AddDays(1000) }; var flatRate = 0.05; var rates = pillars.Select(p => flatRate).ToArray(); CalendarProvider.Collection.TryGetCalendar("LON", out var cal); var usd = TestProviderHelper.CurrencyProvider["USD"]; var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var price = 93.0; var ix = new FloatRateIndex { Currency = usd, DayCountBasis = DayCountBasis.ACT360, FixingOffset = 2.Bd(), HolidayCalendars = cal, ResetTenor = 3.Months(), RollConvention = RollType.MF }; var maturity = bd.AddDays(365); var accrualStart = maturity.AddPeriod(RollType.F, ix.HolidayCalendars, ix.FixingOffset); var accrualEnd = accrualStart.AddPeriod(ix.RollConvention, ix.HolidayCalendars, ix.ResetTenor); var dcf = maturity.CalculateYearFraction(accrualEnd, DayCountBasis.ACT360); var s = new OISFuture { Currency = usd, ContractSize = 1e6, Position = 1, DCF = dcf, AverageStartDate = accrualStart, AverageEndDate = accrualEnd, ForecastCurve = "USD.BLAH", Price = price, Index = ix }; var pv = s.Pv(fModel, false); var rateEst = discoCurve.GetForwardRate(accrualStart, accrualEnd, RateType.Linear, ix.DayCountBasis); var fairPrice = 100.0 - rateEst * 100; var expectedPv = (price - fairPrice) * 1e6 * dcf; Assert.Equal(expectedPv, pv); var ss = s.Sensitivities(fModel); Assert.True(ss.Count == 1 && ss.Keys.Single() == "USD.BLAH"); Assert.True(ss["USD.BLAH"].Count == 2 && ss["USD.BLAH"].Keys.Contains(accrualStart) && ss["USD.BLAH"].Keys.Contains(accrualEnd)); Assert.Equal(accrualEnd, s.LastSensitivityDate); Assert.Empty(s.Dependencies(null)); var s2 = (OISFuture)s.SetParRate(97); Assert.Equal(97, s2.Price); }
private IPvModel GenerateTestData() { Utils.Parallel.ParallelUtils.Instance.MultiThreaded = false; var usd = TestProviderHelper.CurrencyProvider.GetCurrency("USD"); var zar = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR"); var nyc = TestProviderHelper.CalendarProvider.Collection["NYC"]; var ins = new Forward { TradeId = "TestA", AssetId = "FakeAsset", ExpiryDate = _originDate.AddDays(180), PaymentCurrency = zar, Notional = 1e6, Strike = 1400, DiscountCurve = "DISCO-ZAR" }; var pf = new Portfolio { Instruments = new List <IInstrument> { ins } }; var pillars = new[] { _originDate.AddDays(90), _originDate.AddDays(180) }; var discoUsd = new IrCurve(pillars, pillars.Select(p => 0.02).ToArray(), _originDate, "DISCO-USD", Interpolator1DType.Linear, usd); var discoZar = new IrCurve(pillars, pillars.Select(p => 0.02).ToArray(), _originDate, "DISCO-ZAR", Interpolator1DType.Linear, zar); var fxpairs = new List <FxPair> { new FxPair { Domestic = usd, Foreign = zar, PrimaryCalendar = nyc, SpotLag = 2.Bd() }, new FxPair { Domestic = zar, Foreign = usd, PrimaryCalendar = nyc, SpotLag = 2.Bd() }, }; var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider); fxMatrix.Init(usd, _originDate, new Dictionary <Currency, double> { { zar, 14.0 } }, fxpairs, new Dictionary <Currency, string> { { usd, "DISCO-USD" }, { zar, "DISCO-ZAR" } }); var fModel = new FundingModel(_originDate, new[] { discoUsd, discoZar }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); fModel.SetupFx(fxMatrix); var model = new AssetFxModel(_originDate, fModel); var curve = new ConstantPriceCurve(100, _originDate, TestProviderHelper.CurrencyProvider); model.AddPriceCurve("FakeAsset", curve); model.AddFixingDictionary("FakeAsset", new FixingDictionary()); model.AttachPortfolio(pf); return(model); }
public void IrSwap() { var bd = DateTime.Parse("2018-09-13"); var pillars = new[] { bd, bd.AddDays(1000) }; var flatRate = 0.05; var rates = pillars.Select(p => flatRate).ToArray(); var usd = TestProviderHelper.CurrencyProvider["USD"]; var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); CalendarProvider.Collection.TryGetCalendar("LON", out var cal); var ix = new FloatRateIndex { Currency = usd, DayCountBasis = DayCountBasis.ACT360, DayCountBasisFixed = DayCountBasis.ACT360, FixingOffset = 2.Bd(), HolidayCalendars = cal, ResetTenor = 3.Months(), ResetTenorFixed = 3.Months(), RollConvention = RollType.MF }; var parRate = 0.05; var notional = 100e6; var startDate = bd.AddPeriod(RollType.F, cal, 2.Bd()); var maturity = startDate.AddDays(365); var swp = new IrSwap(startDate, 1.Years(), ix, parRate, SwapPayReceiveType.Pay, "USD.BLAH", "USD.BLAH") { Notional = notional, RateIndex = ix }; var pv = swp.Pv(fModel, true); Assert.Equal(-368.89651349, pv, 8); swp = new IrSwap(startDate, 1.Years(), ix, parRate + 0.01, SwapPayReceiveType.Pay, "USD.BLAH", "USD.BLAH") { Notional = notional, RateIndex = ix }; pv = swp.Pv(fModel, true); Assert.Equal(-10217.8229952, pv, 8); Assert.Equal(swp.EndDate, swp.LastSensitivityDate); var d = swp.Dependencies(null); Assert.Single(d); Assert.Equal(0.0496254169169585, swp.CalculateParRate(fModel), 10); Assert.Equal(0.09, (swp.SetParRate(0.09) as IrSwap).ParRate); Assert.Equal(1.0, swp.SupervisoryDelta(null)); Assert.Equal(1.0, swp.MaturityBucket(startDate)); }
public void BasicSelfDiscounting() { var startDate = new DateTime(2016, 05, 20); var swapTenor2 = new Frequency("2y"); var jhb = TestProviderHelper.CalendarProvider.Collection["JHB"]; var pillarDate = startDate.AddPeriod(RollType.MF, jhb, 1.Years()); var pillarDate2 = startDate.AddPeriod(RollType.MF, jhb, swapTenor2); var pillarDateDepo = startDate.AddPeriod(RollType.MF, jhb, 3.Months()); var ccyZar = TestProviderHelper.CurrencyProvider["JHB"]; var zar3m = new FloatRateIndex() { Currency = ccyZar, DayCountBasis = DayCountBasis.Act_365F, DayCountBasisFixed = DayCountBasis.Act_365F, ResetTenor = 3.Months(), FixingOffset = 0.Bd(), HolidayCalendars = jhb, RollConvention = RollType.MF }; var swap = new IrSwap(startDate, 1.Years(), zar3m, 0.06, SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.JIBAR.3M"); var swap2 = new IrSwap(startDate, swapTenor2, zar3m, 0.06, SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.JIBAR.3M"); var depo = new IrSwap(startDate, 3.Months(), zar3m, 0.06, SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.JIBAR.3M"); var fic = new FundingInstrumentCollection(TestProviderHelper.CurrencyProvider) { swap, swap2, depo }; var curve = new IrCurve(new [] { pillarDateDepo, pillarDate, pillarDate2 }, new double[3], startDate, "ZAR.JIBAR.3M", Interpolator1DType.LinearFlatExtrap, ccyZar); var model = new FundingModel(startDate, new[] { curve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var s = new Calibrators.NewtonRaphsonMultiCurveSolver(); if (IsCoverageOnly) { s.Tollerance = 1; } s.Solve(model, fic); var resultSwap1 = swap.Pv(model, false); var resultSwap2 = swap2.Pv(model, false); var resultDepo = depo.Pv(model, false); if (!IsCoverageOnly) { Assert.Equal(0, resultSwap1, 6); Assert.Equal(0, resultSwap2, 6); Assert.Equal(0, resultDepo, 6); } }
public static (IrCurve curve, double spotPrice) GetMetalCurveForCode(string cmxSettleFwdFilename, string cmxSymbol, FxPair metalPair, string curveName, DateTime valDate, IrCurve baseCurve, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider) { var blob = CMEFileParser.Instance.GetBlob(cmxSettleFwdFilename); var fwds = blob.Batch.Where(b => b.Instrmt.Sym == cmxSymbol).ToDictionary(x => x.Instrmt.MatDt, x => Convert.ToDouble(x.Full.Where(x => x.Typ == "6").First().Px)); var curveCcy = metalPair.Domestic; var bc = baseCurve.Clone(); bc.SolveStage = -1; var spotDate = metalPair.SpotDate(valDate); var spotRate = Convert.ToDouble(fwds[spotDate]); fwds = Downsample(fwds, spotDate, metalPair.PrimaryCalendar); var fwdObjects = fwds.Select(x => new FxForward { DomesticCCY = metalPair.Foreign, DeliveryDate = x.Key, DomesticQuantity = 1e6, ForeignCCY = metalPair.Domestic, PillarDate = x.Key, SolveCurve = curveName, Strike = Convert.ToDouble(x.Value), ForeignDiscountCurve = baseCurve.Name, }); var fic = new FundingInstrumentCollection(currencyProvider); fic.AddRange(fwdObjects); var pillars = fwds.Keys.OrderBy(x => x).ToArray(); var curve = new IrCurve(pillars, pillars.Select(p => 0.01).ToArray(), valDate, curveName, Interpolator1DType.Linear, curveCcy); var fm = new FundingModel(valDate, new[] { curve, bc }, currencyProvider, calendarProvider); var matrix = new FxMatrix(currencyProvider); var discoMap = new Dictionary <Currency, string> { { curveCcy, curveName }, { baseCurve.Currency, baseCurve.Name } }; matrix.Init(metalPair.Foreign, valDate, new Dictionary <Currency, double> { { metalPair.Domestic, spotRate } }, new List <FxPair> { metalPair }, discoMap); fm.SetupFx(matrix); var solver = new NewtonRaphsonMultiCurveSolverStaged() { InLineCurveGuessing = true }; solver.Solve(fm, fic); return(curve, spotRate); }
public static IrCurve StripFxBasisCurve(string cmeFwdFileName, FxPair ccyPair, string cmePair, Currency curveCcy, string curveName, DateTime valDate, IrCurve baseCurve, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider) { var fwdsDict = GetFwdFxRatesFromFwdFile(cmeFwdFileName, new Dictionary <string, string> { { ccyPair.ToString(), cmePair } }); var bc = baseCurve.Clone(); bc.SolveStage = -1; var fwds = fwdsDict[ccyPair.ToString()]; var spotDate = ccyPair.SpotDate(valDate); var spotRate = fwds[spotDate]; fwds = Downsample(fwds, spotDate, ccyPair.PrimaryCalendar); var fwdObjects = fwds.Select(x => new FxForward { DomesticCCY = ccyPair.Domestic, DeliveryDate = x.Key, DomesticQuantity = 1e6, ForeignCCY = ccyPair.Foreign, PillarDate = x.Key, SolveCurve = curveName, Strike = x.Value, ForeignDiscountCurve = ccyPair.Foreign == curveCcy ? curveName : baseCurve.Name, }); var fic = new FundingInstrumentCollection(currencyProvider); fic.AddRange(fwdObjects); var pillars = fwds.Keys.OrderBy(x => x).ToArray(); var curve = new IrCurve(pillars, pillars.Select(p => 0.01).ToArray(), valDate, curveName, Interpolator1DType.Linear, curveCcy); var fm = new FundingModel(valDate, new[] { curve, bc }, currencyProvider, calendarProvider); var matrix = new FxMatrix(currencyProvider); var discoMap = new Dictionary <Currency, string> { { curveCcy, curveName }, { baseCurve.Currency, baseCurve.Name } }; matrix.Init(ccyPair.Domestic, valDate, new Dictionary <Currency, double> { { ccyPair.Foreign, spotRate } }, new List <FxPair> { ccyPair }, discoMap); fm.SetupFx(matrix); var solver = new NewtonRaphsonMultiCurveSolverStaged() { InLineCurveGuessing = true }; solver.Solve(fm, fic); return(curve); }
public void CashBalanceFact() { var bd = new DateTime(2019, 06, 14); var pillars = new[] { bd, bd.AddDays(1000) }; var flatRate = 0.05; var rates = pillars.Select(p => flatRate).ToArray(); var usd = TestProviderHelper.CurrencyProvider["USD"]; var zar = TestProviderHelper.CurrencyProvider["ZAR"]; var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider); fxMatrix.Init(usd, bd, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> { { usd, "X" }, { zar, "Y" } }); var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); fModel.SetupFx(fxMatrix); var aModel = new AssetFxModel(bd, fModel); var notional = 100e6; var maturity = bd.AddDays(365); var b = new CashBalance(usd, notional, null); var t = bd.CalculateYearFraction(maturity, DayCountBasis.Act365F); var pv = b.Pv(fModel, false); Assert.Equal(notional, pv); Assert.Empty(b.Dependencies(null)); Assert.Empty(b.AssetIds); Assert.Empty(b.PastFixingDates(bd)); Assert.Equal(0.0, b.CalculateParRate(null)); Assert.Equal(0.0, b.FlowsT0(null)); Assert.Equal(string.Empty, b.FxPair(null)); Assert.Equal(FxConversionType.None, b.FxType(null)); Assert.Equal(usd, b.Currency); Assert.Equal(DateTime.MinValue, b.LastSensitivityDate); var y = (CashBalance)b.Clone(); Assert.True(b.Equals(y)); y.TradeId = "xxx"; Assert.False(b.Equals(y)); Assert.Throws <NotImplementedException>(() => b.Sensitivities(fModel)); Assert.Throws <NotImplementedException>(() => b.SetStrike(0.0)); Assert.Equal(b, b.SetParRate(0.0)); Assert.Single(b.IrCurves(aModel)); }
public double Pv(IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDF, bool updateEstimate) { var totalPV = 0.0; if (FlowScheduleFra.Flows.Count != 1) { throw new InvalidOperationException("FRA should have a sinlge flow"); } var flow = FlowScheduleFra.Flows.Single(); var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; double FV, DF; if (updateEstimate) { var RateFix = flow.FixedRateOrMargin; var RateFloat = forecastCurve.GetForwardRate(s, e, RateType.Linear, Basis); var YF = flow.NotionalByYearFraction; FV = ((RateFloat - RateFix) * YF) / (1 + RateFloat * YF) * flow.Notional; FV *= (PayRec == SwapPayReceiveType.Payer) ? 1.0 : -1.0; } else { FV = flow.Fv; } if (updateDF) { DF = discountCurve.Pv(1.0, flow.SettleDate); } else { DF = flow.Pv / flow.Fv; } totalPV = discountCurve.Pv(FV, flow.SettleDate); if (!updateState) { return(totalPV); } flow.Fv = FV; flow.Pv = totalPV; return(totalPV); }
public static IrCurve StripFxBasisCurve(string cmeFwdFileName, string ccyPair, Currency curveCcy, string curveName, DateTime valDate, IIrCurve baseCurve) { var fwds = GetFwdFxRatesFromFwdFile(cmeFwdFileName, ccyPair); var dfs = fwds.ToDictionary(f => f.Key, f => fwds[valDate] / f.Value * baseCurve.GetDf(valDate, f.Key)); if (ccyPair.EndsWith("USD")) //flip dfs { dfs = dfs.ToDictionary(x => x.Key, x => 1.0 / x.Value); } var pillars = dfs.Keys.OrderBy(k => k).ToArray(); var dfsValues = pillars.Select(p => dfs[p]).ToArray(); var curve = new IrCurve(pillars, dfsValues, valDate, curveName, Interpolator1DType.Linear, curveCcy, null, RateType.DF); return(curve); }
public static object CreateDiscountCurveFromDFs( [ExcelArgument(Description = "Object name")] string ObjectName, [ExcelArgument(Description = "Curve name")] object CurveName, [ExcelArgument(Description = "Build date")] DateTime BuildDate, [ExcelArgument(Description = "Array of pillar dates")] double[] Pillars, [ExcelArgument(Description = "Array of discount factors")] double[] DiscountFactors, [ExcelArgument(Description = "Type of interpolation")] object InterpolationType, [ExcelArgument(Description = "Currency - default USD")] object Currency, [ExcelArgument(Description = "Collateral Spec - default LIBOR.3M")] object CollateralSpec, [ExcelArgument(Description = "Rate storage format - default Exponential")] object RateStorageType) { return(ExcelHelper.Execute(_logger, () => { var curveName = CurveName.OptionalExcel(ObjectName); var curveTypeStr = InterpolationType.OptionalExcel("Linear"); var ccyStr = Currency.OptionalExcel("USD"); var colSpecStr = CollateralSpec.OptionalExcel("LIBOR.3M"); var rateTypeStr = RateStorageType.OptionalExcel("CC"); if (!Enum.TryParse(curveTypeStr, out Interpolator1DType iType)) { return $"Could not parse interpolator type - {curveTypeStr}"; } if (!Enum.TryParse(rateTypeStr, out RateType rType)) { return $"Could not parse rate type - {rateTypeStr}"; } var pDates = Pillars.ToDateTimeArray(); ContainerStores.SessionContainer.GetService <ICalendarProvider>().Collection.TryGetCalendar(ccyStr, out var ccyCal); var ccy = ContainerStores.GlobalContainer.GetRequiredService <ICurrencyProvider>()[ccyStr]; var zeroRates = DiscountFactors .Select((df, ix) => DateTime.FromOADate(Pillars[ix]) == BuildDate ? 0.0 : IrCurve.RateFromDF(BuildDate.CalculateYearFraction(DateTime.FromOADate(Pillars[ix]), DayCountBasis.ACT365F), df, rType)) .ToArray(); if (DateTime.FromOADate(Pillars[0]) == BuildDate && zeroRates.Length > 1) { zeroRates[0] = zeroRates[1]; } var cObj = new IrCurve(pDates, zeroRates, BuildDate, curveName, iType, ccy, colSpecStr, rType); return ExcelHelper.PushToCache <IIrCurve>(cObj, ObjectName); })); }
public void StripCrackedCurve() { var buildDate = new DateTime(2018, 07, 28); string[] futures = { "COV8", "COX8", "COZ8", "COF9", "COG9" }; double[] futuresPrices = { 77, 78, 79, 79.5, 79.75 }; string[] periods = { "AUG18", "SEP18", "OCT18", "NOV18" }; double[] strikes = { -10, -11, -12, -13 }; var cal = TestProviderHelper.CalendarProvider.Collection["LON"]; var usd = TestProviderHelper.CurrencyProvider["USD"]; var bPillars = futures.Select(x => FutureCode.GetExpiryFromCode(x, TestProviderHelper.FutureSettingsProvider)).ToArray(); var brentCurve = new PriceCurve(buildDate, bPillars, futuresPrices, PriceCurveType.ICE, TestProviderHelper.CurrencyProvider, futures) { AssetId = "Brent" }; var instruments = periods.Select((p, ix) => (IAssetInstrument)AssetProductFactory.CreateTermAsianBasisSwap(p, strikes[ix], "Brent", "Sing180", cal, cal, cal, 0.Bd(), usd, 0.Bd(), 0.Bd(), 1000, 1000 / 6.35)) .ToList(); var pillars = instruments.Select(x => ((AsianBasisSwap)x).RecSwaplets.Max(sq => sq.AverageEndDate)).ToList(); DateTime[] dPillars = { buildDate, buildDate.AddDays(1000) }; double[] dRates = { 0, 0 }; var discountCurve = new IrCurve(dPillars, dRates, buildDate, "zeroDiscount", Interpolator1DType.LinearFlatExtrap, usd); var s = new Calibrators.NewtonRaphsonAssetBasisCurveSolver(TestProviderHelper.CurrencyProvider); if (IsCoverageOnly) { s.Tollerance = 1.0; } var curve = s.SolveCurve(instruments, pillars, discountCurve, brentCurve, buildDate, PriceCurveType.ICE); if (!IsCoverageOnly) { for (var i = 0; i < instruments.Count; i++) { var resultPV = Calibrators.NewtonRaphsonAssetBasisCurveSolver.BasisSwapPv(curve, instruments[i], discountCurve, brentCurve); Assert.Equal(0, resultPV, 6); } } }
public static IrCurve GetCurveForCode(string cmeId, string cmeFilename, string qwackCode, string curveName, Dictionary <string, FloatRateIndex> indices, Dictionary <string, string> curves, IFutureSettingsProvider futureSettingsProvider, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider) { var parsed = CMEFileParser.Parse(cmeFilename).Where(r => r.ID == cmeId && r.SecTyp == "FUT"); var q = parsed.ToDictionary(x => DateTime.ParseExact(x.MatDt, "yyyy-MM-dd", CultureInfo.InvariantCulture), x => x.SettlePrice); var origin = DateTime.ParseExact(parsed.First().BizDt, "yyyy-MM-dd", CultureInfo.InvariantCulture); var instruments = parsed.Select(p => ToQwackIns(p, qwackCode, futureSettingsProvider, currencyProvider, indices, curves)).ToList(); var pillars = instruments.Select(x => x.PillarDate).OrderBy(x => x).ToArray(); var fic = new FundingInstrumentCollection(currencyProvider); fic.AddRange(instruments); var curve = new IrCurve(pillars, pillars.Select(p => 0.01).ToArray(), origin, curveName, Interpolator1DType.Linear, currencyProvider.GetCurrency("USD")); var fm = new FundingModel(origin, new[] { curve }, currencyProvider, calendarProvider); var solver = new NewtonRaphsonMultiCurveSolverStaged(); solver.Solve(fm, fic); return(curve); }
public void IrCurveConversionFacts() { Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.Annual)); Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.CC)); Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.Linear)); Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.SemiAnnual)); Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.Quarterly)); Assert.Equal(1.0, IrCurve.DFFromRate(0.0, 0.1, RateType.Monthly)); Assert.Equal(0.1, IrCurve.DFFromRate(0.0, 0.1, RateType.DiscountFactor)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.Annual)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.CC)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.Linear)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.SemiAnnual)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.Quarterly)); Assert.Equal(0.0, IrCurve.RateFromDF(1.0, 1.0, RateType.Monthly)); Assert.Equal(1.0, IrCurve.RateFromDF(1.0, 1.0, RateType.DiscountFactor)); }
public void PastStartingFixedRateLoanDepo() { var bd = DateTime.Today; var pillars = new[] { bd, bd.AddDays(1000) }; var flatRate = 0.05; var rates = pillars.Select(p => flatRate).ToArray(); var usd = TestProviderHelper.CurrencyProvider["USD"]; var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var start = bd.AddDays(-10); var maturity = bd.AddDays(365); var notional = 100e6; var iRate = 0.07; var depo = new FixedRateLoanDeposit(start, maturity, iRate, usd, DayCountBasis.ACT360, notional, "USD.BLAH"); var pv = depo.Pv(fModel, false); var dfEnd = discoCurve.GetDf(bd, maturity); var t = start.CalculateYearFraction(maturity, DayCountBasis.ACT360); var expectedPv = 0.0; //initial notional is in the past expectedPv += -notional * dfEnd; //final notional expectedPv += -notional * (iRate * t) * dfEnd; //final notional Assert.Equal(expectedPv, pv, 8); var loan = new FixedRateLoanDeposit(start, maturity, iRate, usd, DayCountBasis.ACT360, -notional, "USD.BLAH"); pv = loan.Pv(fModel, false); expectedPv = 0.0; //initial notional is in the past expectedPv += notional * dfEnd; //final notional expectedPv += notional * (iRate * t) * dfEnd; //final notional Assert.Equal(expectedPv, pv, 8); }
public void StripCoalSparse() { var startDate = new DateTime(2018, 07, 28); string[] periods = { "AUG18", "SEP18", "Q4-18", "Q1-19", "Q2-19", "H2-19", "CAL-20", "CAL-21" }; double[] strikes = { 100, 99, 98, 97, 96, 95, 94, 93 }; var cal = TestProviderHelper.CalendarProvider.Collection["LON"]; var xaf = TestProviderHelper.CurrencyProvider["XAF"]; var instruments = periods.Select((p, ix) => AssetProductFactory.CreateMonthlyAsianSwap(p, strikes[ix], "coalXXX", cal, cal, 0.Bd(), xaf, TradeDirection.Long, 0.Bd(), 1, DateGenerationType.Fridays) ).ToList(); var pillars = instruments.Select(x => x.Swaplets.Max(sq => sq.AverageEndDate)).ToList(); DateTime[] dPillars = { startDate, startDate.AddDays(1000) }; double[] dRates = { 0, 0 }; var discountCurve = new IrCurve(dPillars, dRates, startDate, "zeroDiscount", Interpolator1DType.LinearFlatExtrap, xaf); var s = new NewtonRaphsonAssetCurveSolver() { Tollerance = IsCoverageOnly ? 1 : 0.00000001 }; var curve = s.Solve(instruments, pillars, discountCurve, startDate, TestProviderHelper.CurrencyProvider); if (!IsCoverageOnly) { for (var i = 0; i < instruments.Count; i++) { var resultPV = NewtonRaphsonAssetCurveSolver.SwapPv(curve, instruments[i], discountCurve); Assert.Equal(0, resultPV, 6); } } }
public void ZeroBond() { var bd = DateTime.Today; var pillars = new[] { bd, bd.AddDays(1000) }; var flatRate = 0.05; var rates = pillars.Select(p => flatRate).ToArray(); var usd = TestProviderHelper.CurrencyProvider["USD"]; var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var price = 0.93; var notional = 100e6; var maturity = bd.AddDays(365); var b = new ZeroBond(price, bd.AddDays(365), "USD.BLAH") { Notional = notional }; var t = bd.CalculateYearFraction(maturity, DayCountBasis.Act365F); var pv = b.Pv(fModel, false); var expectedPv = (Exp(-flatRate * t) - price) * notional; Assert.Equal(expectedPv, pv); var s = b.Sensitivities(fModel); Assert.True(s.Count == 1 && s.Keys.Single() == "USD.BLAH"); Assert.True(s["USD.BLAH"].Count == 1 && s["USD.BLAH"].Single().Key == maturity); Assert.Equal(-t * notional * Exp(-flatRate * t), s["USD.BLAH"][maturity]); Assert.Equal(maturity, b.LastSensitivityDate); Assert.Empty(b.Dependencies(null)); Assert.Equal(Exp(-flatRate * t), b.CalculateParRate(fModel)); var b2 = (ZeroBond)b.SetParRate(0.99); Assert.Equal(0.99, b2.Price); }
public void AsianCompoSwap() { ParallelUtils.Instance.MultiThreaded = false; var startDate = new DateTime(2018, 07, 28); var cal = TestProviderHelper.CalendarProvider.Collection["LON"]; var xaf = TestProviderHelper.CurrencyProvider["XAF"]; var usd = TestProviderHelper.CurrencyProvider["USD"]; var curvePillars = new[] { "1W", "1M", "3M", "6M", "1Y" }; var curvePillarDates = curvePillars.Select(l => startDate.AddPeriod(RollType.F, cal, new Frequency(l))).ToArray(); var curvePoints = new[] { 100.0, 100, 100, 100, 100 }; var curve = new BasicPriceCurve(startDate, curvePillarDates, curvePoints, PriceCurveType.LME, TestProviderHelper.CurrencyProvider, curvePillars) { Currency = usd, CollateralSpec = "CURVE", Name = "Coconuts", AssetId = "Coconuts" }; var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider); var fxSpot = 7; var rates = new Dictionary <Currency, double> { { xaf, fxSpot } }; var discoMap = new Dictionary <Currency, string> { { xaf, "XAF.CURVE" }, { usd, "USD.CURVE" } }; var fxPair = new FxPair() { Domestic = usd, Foreign = xaf, PrimaryCalendar = cal, SpotLag = new Frequency("2b") }; fxMatrix.Init(usd, startDate, rates, new List <FxPair> { fxPair }, discoMap); var irPillars = new[] { startDate, startDate.AddYears(10) }; var xafRates = new[] { 0.1, 0.1 }; var usdRates = new[] { 0.01, 0.01 }; var xafCurve = new IrCurve(irPillars, xafRates, startDate, "XAF.CURVE", Interpolator1DType.Linear, xaf, "CURVE"); var usdCurve = new IrCurve(irPillars, usdRates, startDate, "USD.CURVE", Interpolator1DType.Linear, usd, "CURVE"); var fModel = new FundingModel(startDate, new[] { xafCurve, usdCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); fModel.SetupFx(fxMatrix); var aModel = new AssetFxModel(startDate, fModel); aModel.AddPriceCurve("Coconuts", curve); var periodCode = "SEP-18"; var(Start, End) = periodCode.ParsePeriod(); var fixingDates = Start.BusinessDaysInPeriod(End, cal).ToArray(); var settleDate = fixingDates.Last().AddPeriod(RollType.F, cal, new Frequency("5b")); var fxFwd = aModel.FundingModel.GetFxAverage(fixingDates, usd, xaf); var assetFwd = curve.GetAveragePriceForDates(fixingDates); var fairStrike = fxFwd * assetFwd; var asianSwap = AssetProductFactory.CreateMonthlyAsianSwap(periodCode, fairStrike, "Coconuts", cal, cal, new Frequency("5b"), xaf, TradeDirection.Long, new Frequency("0b"), 1000, DateGenerationType.BusinessDays); asianSwap.TradeId = "aLovelyBunch"; foreach (var sw in asianSwap.Swaplets) { sw.DiscountCurve = "XAF.CURVE"; sw.FxConversionType = FxConversionType.AverageThenConvert; } var pv = asianSwap.PV(aModel, false); Assert.Equal(0, pv, 8); var portfolio = new Portfolio() { Instruments = new List <IInstrument> { asianSwap } }; var pfPvCube = portfolio.PV(aModel); var pfPv = (double)pfPvCube.GetAllRows().First().Value; Assert.Equal(0.0, pfPv, 8); var deltaCube = portfolio.AssetDelta(aModel); var dAgg = deltaCube.Pivot("TradeId", AggregationAction.Sum); var delta = (double)dAgg.GetAllRows().First().Value; var t0Spot = aModel.FundingModel.GetFxRate(startDate, usd, xaf); var df = xafCurve.GetDf(startDate, settleDate); Assert.Equal(995.361065482776, delta, 7); var fxDeltaCube = portfolio.FxDelta(aModel, usd, TestProviderHelper.CurrencyProvider); var dfxAgg = fxDeltaCube.Pivot("TradeId", AggregationAction.Sum); var fxDelta = (double)dfxAgg.GetAllRows().First().Value; Assert.Equal(-1000 * df * fxFwd * 100 / (t0Spot / fxSpot) / usdCurve.GetDf(startDate, fxPair.SpotDate(startDate)), fxDelta, 4); }
public void BasicOisCurveSolving() { var startDate = new DateTime(2016, 05, 20); var depoTenors = new Frequency[] { 3.Months() }; double[] depoPrices = { 0.06 }; string[] FRATenors = { "3x6", "6x9", "9x12" }; double[] FRAPrices = { 0.065, 0.07, 0.075 }; var swapTenors = new Frequency[] { 18.Months(), 2.Years(), 3.Years(), 4.Years(), 5.Years(), 7.Years(), 10.Years(), 15.Years(), 20.Years() }; double[] swapPrices = { 0.075, 0.08, 0.085, 0.09, 0.095, 0.0975, 0.098, 0.099, 0.1 }; var oisTenors = new Frequency[] { 3.Months(), 6.Months(), 1.Years(), 2.Years(), 3.Years(), 4.Years(), 5.Years(), 7.Years(), 10.Years(), 15.Years(), 20.Years() }; var oisPrices = new double[] { 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004 }; var pillarDatesDepo = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var pillarDatesFRA = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, new Frequency(x.Split('x')[1] + "M"))).ToArray(); var pillarDatesSwap = swapTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var pillarDates3m = pillarDatesDepo.Union(pillarDatesSwap).Union(pillarDatesFRA).Distinct().OrderBy(x => x).ToArray(); var pillarDatesOIS = oisTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var swaps = new IrSwap[swapTenors.Length]; var depos = new IrSwap[depoTenors.Length]; var oisSwaps = new IrBasisSwap[oisTenors.Length]; var FRAs = new ForwardRateAgreement[FRATenors.Length]; var fic = new FundingInstrumentCollection(TestProviderHelper.CurrencyProvider); for (var i = 0; i < FRAs.Length; i++) { FRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPrices[i], _zar3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "ZAR.JIBAR.3M", "ZAR.OIS.1B"); fic.Add(FRAs[i]); } for (var i = 0; i < oisSwaps.Length; i++) { oisSwaps[i] = new IrBasisSwap(startDate, oisTenors[i], oisPrices[i], true, zaron, _zar3m, "ZAR.JIBAR.3M", "ZAR.OIS.1B", "ZAR.OIS.1B"); fic.Add(oisSwaps[i]); } for (var i = 0; i < swaps.Length; i++) { swaps[i] = new IrSwap(startDate, swapTenors[i], _zar3m, swapPrices[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.OIS.1B"); fic.Add(swaps[i]); } for (var i = 0; i < depos.Length; i++) { depos[i] = new IrSwap(startDate, depoTenors[i], _zar3m, depoPrices[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.OIS.1B"); fic.Add(depos[i]); } var curve3m = new IrCurve(pillarDates3m, new double[pillarDates3m.Length], startDate, "ZAR.JIBAR.3M", Interpolator1DType.LinearFlatExtrap, ccyZar); var curveOIS = new IrCurve(pillarDatesOIS, new double[pillarDatesOIS.Length], startDate, "ZAR.OIS.1B", Interpolator1DType.LinearFlatExtrap, ccyZar); var model = new FundingModel(startDate, new IrCurve[] { curve3m, curveOIS }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var S = new NewtonRaphsonMultiCurveSolver { Tollerance = IsCoverageOnly ? 1 : 0.00000001, MaxItterations = IsCoverageOnly ? 1 : 100, }; S.Solve(model, fic); if (!IsCoverageOnly) { foreach (var ins in fic) { var pv = ins.Pv(model, false); Assert.Equal(0.0, pv, 7); } } }
public void ComplexerCurve() { var startDate = new DateTime(2016, 05, 20); Frequency[] depoTenors = { 3.Months() }; Frequency[] OISdepoTenors = { 1.Bd() }; double[] depoPricesZAR = { 0.06 }; double[] depoPricesUSD = { 0.01 }; double[] OISdepoPricesZAR = { 0.055 }; double[] OISdepoPricesUSD = { 0.009 }; string[] FRATenors = { "3x6", "6x9", "9x12", "12x15", "15x18", "18x21", "21x24" }; double[] FRAPricesZAR = { 0.065, 0.07, 0.075, 0.077, 0.08, 0.081, 0.082 }; double[] FRAPricesUSD = { 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018 }; Frequency[] swapTenors = { 3.Years(), 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() }; double[] swapPricesZAR = { 0.08, 0.083, 0.085, 0.087, 0.089, 0.091, 0.092, 0.093, 0.094, 0.097, 0.099, 0.099, 0.099 }; double[] swapPricesUSD = { 0.017, 0.018, 0.019, 0.020, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.03 }; Frequency[] oisTenors = { 3.Months(), 6.Months(), 1.Years(), 18.Months(), 2.Years(), 3.Years(), 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() }; double[] oisPricesZAR = { 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004 }; double[] oisPricesUSD = { 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002 }; var fxSpot = 14.0; Frequency[] fxForwardTenors = { 3.Months(), 6.Months(), 1.Years(), 18.Months(), 2.Years(), 3.Years() }; double[] fxForwardPrices = { 14.10, 14.20, 14.40, 14.60, 14.80, 15.20 }; Frequency[] xcySwapTenors = { 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() }; double[] xcySwapPrices = { 0.0055, 0.0050, 0.0045, 0.0040, 0.0035, 0.0030, 0.0025, 0.0020, 0.0015, 0.0010, 0.0005, 0.0000 }; var ZARpillarDatesDepo = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var ZARpillarDatesFRA = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, new Frequency(x.Split('x')[1] + "M"))).ToArray(); var ZARpillarDatesSwap = swapTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var ZARpillarDates3m = ZARpillarDatesDepo.Union(ZARpillarDatesSwap).Union(ZARpillarDatesFRA).Distinct().OrderBy(x => x).ToArray(); var ZARpillarDatesDepoOIS = OISdepoTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var ZARpillarDatesOISSwap = oisTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray(); var ZARpillarDatesOIS = ZARpillarDatesDepoOIS.Union(ZARpillarDatesOISSwap).Distinct().OrderBy(x => x).ToArray(); var USDpillarDatesDepo = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var USDpillarDatesFRA = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, new Frequency(x.Split('x')[1] + "M"))).ToArray(); var USDpillarDatesSwap = swapTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var USDpillarDates3m = USDpillarDatesDepo.Union(USDpillarDatesSwap).Union(USDpillarDatesFRA).Distinct().OrderBy(x => x).ToArray(); var USDpillarDatesDepoOIS = OISdepoTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var USDpillarDatesOISSwap = oisTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var USDpillarDatesOIS = USDpillarDatesDepoOIS.Union(USDpillarDatesOISSwap).Distinct().OrderBy(x => x).ToArray(); var fxForwardPillarDates = fxForwardTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var xcySwapDates = xcySwapTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray(); var fxPillarDates = fxForwardPillarDates.Union(xcySwapDates).Distinct().OrderBy(x => x).ToArray(); var ZARswaps = new IrSwap[swapTenors.Length]; var ZARdepos = new IrSwap[depoTenors.Length]; var ZARdeposOIS = new IrSwap[OISdepoTenors.Length]; var ZARoisSwaps = new IrBasisSwap[oisTenors.Length]; var ZARFRAs = new ForwardRateAgreement[FRATenors.Length]; var USDswaps = new IrSwap[swapTenors.Length]; var USDdepos = new IrSwap[depoTenors.Length]; var USDdeposOIS = new IrSwap[OISdepoTenors.Length]; var USDoisSwaps = new IrBasisSwap[oisTenors.Length]; var USDFRAs = new ForwardRateAgreement[FRATenors.Length]; var fxForwards = new FxForward[fxForwardTenors.Length]; var xcySwaps = new XccyBasisSwap[xcySwapTenors.Length]; var FIC = new FundingInstrumentCollection(TestProviderHelper.CurrencyProvider); for (var i = 0; i < FRATenors.Length; i++) { ZARFRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPricesZAR[i], _zar3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR") { SolveCurve = "ZAR.JIBAR.3M" }; FIC.Add(ZARFRAs[i]); USDFRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPricesUSD[i], usd3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "USD.LIBOR.3M", "USD.DISC.CSA_USD") { SolveCurve = "USD.LIBOR.3M" }; FIC.Add(USDFRAs[i]); } for (var i = 0; i < oisTenors.Length; i++) { ZARoisSwaps[i] = new IrBasisSwap(startDate, oisTenors[i], oisPricesZAR[i], true, zaron, _zar3m, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR", "ZAR.DISC.CSA_ZAR") { SolveCurve = "ZAR.DISC.CSA_ZAR" }; FIC.Add(ZARoisSwaps[i]); USDoisSwaps[i] = new IrBasisSwap(startDate, oisTenors[i], oisPricesUSD[i], true, usdon, usd3m, "USD.LIBOR.3M", "USD.DISC.CSA_USD", "USD.DISC.CSA_USD") { SolveCurve = "USD.DISC.CSA_USD" }; FIC.Add(USDoisSwaps[i]); } for (var i = 0; i < swapTenors.Length; i++) { ZARswaps[i] = new IrSwap(startDate, swapTenors[i], _zar3m, swapPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR") { SolveCurve = "ZAR.JIBAR.3M" }; FIC.Add(ZARswaps[i]); USDswaps[i] = new IrSwap(startDate, swapTenors[i], usd3m, swapPricesUSD[i], SwapPayReceiveType.Payer, "USD.LIBOR.3M", "USD.DISC.CSA_USD") { SolveCurve = "USD.LIBOR.3M" }; FIC.Add(USDswaps[i]); } for (var i = 0; i < depoTenors.Length; i++) { ZARdepos[i] = new IrSwap(startDate, depoTenors[i], _zar3m, depoPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR") { SolveCurve = "ZAR.JIBAR.3M" }; FIC.Add(ZARdepos[i]); USDdepos[i] = new IrSwap(startDate, depoTenors[i], usd3m, depoPricesUSD[i], SwapPayReceiveType.Payer, "USD.LIBOR.3M", "USD.DISC.CSA_USD") { SolveCurve = "USD.LIBOR.3M" }; FIC.Add(USDdepos[i]); } for (var i = 0; i < OISdepoTenors.Length; i++) { ZARdeposOIS[i] = new IrSwap(startDate, OISdepoTenors[i], zaron, OISdepoPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.DISC.CSA_ZAR", "ZAR.DISC.CSA_ZAR") { SolveCurve = "ZAR.DISC.CSA_ZAR" }; FIC.Add(ZARdeposOIS[i]); USDdeposOIS[i] = new IrSwap(startDate, OISdepoTenors[i], usdon, OISdepoPricesUSD[i], SwapPayReceiveType.Payer, "USD.DISC.CSA_USD", "USD.DISC.CSA_USD") { SolveCurve = "USD.DISC.CSA_USD" }; FIC.Add(USDdeposOIS[i]); } for (var i = 0; i < fxForwards.Length; i++) { fxForwards[i] = new FxForward { SolveCurve = "ZAR.DISC.CSA_USD", DeliveryDate = fxForwardPillarDates[i], DomesticCCY = ccyUsd, ForeignCCY = ccyZar, DomesticQuantity = 1e6 / fxForwardPrices[i], Strike = fxForwardPrices[i], ForeignDiscountCurve = "ZAR.DISC.CSA_USD", }; FIC.Add(fxForwards[i]); } for (var i = 0; i < xcySwapTenors.Length; i++) { xcySwaps[i] = new XccyBasisSwap(startDate, xcySwapTenors[i], xcySwapPrices[i], true, usd3m, _zar3m, ExchangeType.Both, MTMSwapType.ReceiveNotionalFixed, "USD.LIBOR.3M", "ZAR.JIBAR.3M", "USD.DISC.CSA_USD", "ZAR.DISC.CSA_USD") { SolveCurve = "ZAR.DISC.CSA_USD" }; FIC.Add(xcySwaps[i]); } var ZARcurve3m = new IrCurve(ZARpillarDates3m, new double[ZARpillarDates3m.Length], startDate, "ZAR.JIBAR.3M", Interpolator1DType.LinearFlatExtrap, ccyZar) { SolveStage = 0 }; var ZARcurveOIS = new IrCurve(ZARpillarDatesOIS, new double[ZARpillarDatesOIS.Length], startDate, "ZAR.DISC.CSA_ZAR", Interpolator1DType.LinearFlatExtrap, ccyZar) { SolveStage = 0 }; var USDcurve3m = new IrCurve(USDpillarDates3m, new double[USDpillarDates3m.Length], startDate, "USD.LIBOR.3M", Interpolator1DType.LinearFlatExtrap, ccyUsd) { SolveStage = 1 }; var USDcurveOIS = new IrCurve(USDpillarDatesOIS, new double[USDpillarDatesOIS.Length], startDate, "USD.DISC.CSA_USD", Interpolator1DType.LinearFlatExtrap, ccyUsd) { SolveStage = 1 }; var fxCurve = new IrCurve(fxPillarDates, new double[fxPillarDates.Length], startDate, "ZAR.DISC.CSA_USD", Interpolator1DType.LinearFlatExtrap, ccyZar) { SolveStage = 2 }; var engine = new FundingModel(startDate, new IrCurve[] { ZARcurve3m, ZARcurveOIS, USDcurve3m, USDcurveOIS, fxCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider); var spotRates = new Dictionary <Currency, double> { { ccyZar, fxSpot } }; var fxPairs = new List <FxPair> { new FxPair { Domestic = ccyUsd, Foreign = ccyZar, SettlementCalendar = _usd, SpotLag = new Frequency("2b") } }; var discountMap = new Dictionary <Currency, string> { { ccyUsd, "USD.DISC.CSA_USD" }, { ccyZar, "ZAR.DISC.CSA_USD" }, }; fxMatrix.Init(ccyUsd, startDate, spotRates, fxPairs, discountMap); engine.SetupFx(fxMatrix); var S = new NewtonRaphsonMultiCurveSolverStaged() { Tollerance = IsCoverageOnly ? 1 : 0.00000001, MaxItterations = IsCoverageOnly ? 1 : 100, }; S.Solve(engine, FIC); if (!IsCoverageOnly) { foreach (var ins in FIC) { var pv = ins.Pv(engine, false); Assert.Equal(0.0, pv, 7); } } }
public void FuturesStripWithConvexity() { var volatility = 0.03; var startDate = new DateTime(2017, 01, 17); var nContracts = 24; var currentDate = startDate.GetNextImmDate(); var expiries = new DateTime[nContracts]; var pillars = new DateTime[nContracts]; var instruments = new IFundingInstrument[nContracts]; var nyc = TestProviderHelper.CalendarProvider.Collection["NYC"]; var lon = TestProviderHelper.CalendarProvider.Collection["LON"]; var ccyUsd = TestProviderHelper.CurrencyProvider["USD"]; var usd3m = new FloatRateIndex() { Currency = ccyUsd, DayCountBasis = DayCountBasis.Act_360, DayCountBasisFixed = DayCountBasis.Act_360, ResetTenor = 3.Months(), FixingOffset = 2.Bd(), HolidayCalendars = nyc, RollConvention = RollType.MF }; for (var i = 0; i < nContracts; i++) { var wed3rd = currentDate.ThirdWednesday(); expiries[i] = wed3rd.SubtractPeriod(RollType.P, lon, 2.Bd()); pillars[i] = wed3rd.AddPeriod(usd3m.RollConvention, usd3m.HolidayCalendars, usd3m.ResetTenor); instruments[i] = new STIRFuture() { Currency = ccyUsd, ContractSize = 1e6, ConvexityAdjustment = FuturesConvexityUtils.CalculateConvexityAdjustment(startDate, expiries[i], pillars[i], volatility), DCF = 0.25, Expiry = expiries[i], ForecastCurve = "USD.LIBOR.3M", Index = usd3m, Position = 1.0, Price = 99.50, SolveCurve = "USD.LIBOR.3M" }; currentDate = currentDate.AddMonths(3); } var fic = new FundingInstrumentCollection(TestProviderHelper.CurrencyProvider); fic.AddRange(instruments); var curve = new IrCurve(pillars, new double[nContracts], startDate, "USD.LIBOR.3M", Interpolator1DType.LinearFlatExtrap, ccyUsd); var model = new FundingModel(startDate, new[] { curve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var s = new Calibrators.NewtonRaphsonMultiCurveSolver() { Tollerance = IsCoverageOnly ? 1 : 0.00000001 }; s.Solve(model, fic); if (!IsCoverageOnly) { for (var i = 0; i < nContracts; i++) { var resultPV = instruments[i].Pv(model, false); Assert.Equal(0, resultPV, 6); } } }
public void ContangoSwap() { var bd = new DateTime(2019, 06, 14); var pillars = new[] { bd, bd.AddDays(1000) }; var flatRateUsd = 0.05; var flatRateXau = 0.01; var spotRate = 1200; var ratesUsd = pillars.Select(p => flatRateUsd).ToArray(); var ratesXau = pillars.Select(p => flatRateXau).ToArray(); var usd = TestProviderHelper.CurrencyProvider["USD"]; var xau = TestProviderHelper.CurrencyProvider["XAU"]; CalendarProvider.Collection.TryGetCalendar("LON", out var cal); var pair = new FxPair() { Domestic = xau, Foreign = usd, SettlementCalendar = cal, SpotLag = 2.Bd() }; var discoCurveUsd = new IrCurve(pillars, ratesUsd, bd, "USD.BLAH", Interpolator1DType.Linear, usd); var discoCurveXau = new IrCurve(pillars, ratesXau, bd, "XAU.BLAH", Interpolator1DType.Linear, xau); var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider); fxMatrix.Init(usd, bd, new Dictionary <Currency, double> { { xau, 1.0 / spotRate } }, new List <FxPair> { pair }, new Dictionary <Currency, string> { { usd, "USD.BLAH" }, { xau, "XAU.BLAH" } }); var fModel = new FundingModel(bd, new[] { discoCurveUsd, discoCurveXau }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); fModel.SetupFx(fxMatrix); var maturity = bd.AddDays(365); var spot = bd.SpotDate(2.Bd(), cal, cal); var c = 0.022; var b = new ContangoSwap { CashCCY = usd, MetalCCY = xau, CashDiscountCurve = "USD.BLAH", DeliveryDate = maturity, ContangoRate = c, MetalQuantity = 1, SpotDate = spot }; var t = spot.CalculateYearFraction(maturity, DayCountBasis.Act360); var pv = b.Pv(fModel, false); var fwdA = (1.0 + c * t) * spotRate; var fwdB = fModel.GetFxRate(maturity, xau, usd); var df = discoCurveUsd.GetDf(bd, maturity); var expectedPv = (fwdB - fwdA) * b.MetalQuantity; expectedPv *= df; Assert.Equal(expectedPv, pv, 10); Assert.Equal(maturity, b.LastSensitivityDate); Assert.Equal(usd, b.Currency); var s = b.Sensitivities(fModel); Assert.True(s.Count == 2 && s.Keys.Contains("USD.BLAH") && s.Keys.Contains("XAU.BLAH")); var s2 = b.Dependencies(fModel.FxMatrix); Assert.True(s2.Count == 2 && s2.Contains("USD.BLAH") && s2.Contains("XAU.BLAH")); Assert.Equal(0.0402428426839156, b.CalculateParRate(fModel), 8); var b2 = (ContangoSwap)b.SetParRate(0.05); Assert.Equal(0.05, b2.ContangoRate); }
private AssetFxMCModel GetSut() { var buildDate = DateTime.Parse("2018-10-04"); var usd = TestProviderHelper.CurrencyProvider["USD"]; var zar = TestProviderHelper.CurrencyProvider["ZAR"]; TestProviderHelper.CalendarProvider.Collection.TryGetCalendar("NYC", out var usdCal); var pair = new FxPair() { Domestic = zar, Foreign = usd, PrimaryCalendar = usdCal, SpotLag = 2.Bd() }; var dfCurve = new IrCurve(new[] { buildDate, buildDate.AddDays(1000) }, new[] { 0.0, 0.0 }, buildDate, "disco", Interpolator1DType.Linear, usd, "DISCO"); var dates = new[] { buildDate, buildDate.AddDays(32), buildDate.AddDays(60), buildDate.AddDays(90) }; var times = dates.Select(d => buildDate.CalculateYearFraction(d, DayCountBasis.Act365F)).ToArray(); var vols = new[] { 0.32, 0.30, 0.29, 0.28 }; var comCurve = new PriceCurve(buildDate, dates, new[] { 100.0, 100.0, 100.0, 100.0 }, PriceCurveType.NYMEX, TestProviderHelper.CurrencyProvider) { Name = "CL", AssetId = "CL" }; var comSurface = new GridVolSurface(buildDate, new[] { 0.5 }, dates, vols.Select(x => new double[] { x }).ToArray(), StrikeType.ForwardDelta, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance, DayCountBasis.Act365F) { AssetId = "CL" }; var fxSurface = new ConstantVolSurface(buildDate, 0.16) { AssetId = "USD/ZAR" }; var correlVector = new CorrelationTimeVector("CL", "USD/ZAR", _correls, times); var fModel = new FundingModel(buildDate, new Dictionary <string, IrCurve> { { "DISCO", dfCurve } }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider); var fxM = new FxMatrix(TestProviderHelper.CurrencyProvider); fxM.Init(usd, buildDate, new Dictionary <Currency, double>() { { zar, 14.0 } }, new List <FxPair>() { pair }, new Dictionary <Currency, string> { { usd, "DISCO" }, { zar, "DISCO" } }); fModel.SetupFx(fxM); fModel.VolSurfaces.Add("ZAR/USD", fxSurface); fModel.VolSurfaces.Add("USD/ZAR", fxSurface); var aModel = new AssetFxModel(buildDate, fModel); aModel.AddVolSurface("CL", comSurface); aModel.AddPriceCurve("CL", comCurve); aModel.CorrelationMatrix = correlVector; var product1 = AssetProductFactory.CreateAsianOption(dates[1], dates[1], 1400, "CL", OptionType.Call, usdCal, dates[1], zar); product1.TradeId = "P1"; product1.DiscountCurve = "DISCO"; product1.FxConversionType = FxConversionType.AverageThenConvert; var product2 = AssetProductFactory.CreateAsianOption(dates[2], dates[2], 1400, "CL", OptionType.Call, usdCal, dates[2], zar); product2.TradeId = "P2"; product2.DiscountCurve = "DISCO"; product2.FxConversionType = FxConversionType.AverageThenConvert; var product3 = AssetProductFactory.CreateAsianOption(dates[3], dates[3], 1400, "CL", OptionType.Call, usdCal, dates[3], zar); product3.TradeId = "P3"; product3.DiscountCurve = "DISCO"; product3.FxConversionType = FxConversionType.AverageThenConvert; var pfolio = new Portfolio { Instruments = new List <IInstrument> { product1, product2, product3 } }; var settings = new McSettings { Generator = RandomGeneratorType.MersenneTwister, NumberOfPaths = (int)2.0.IntPow(15), NumberOfTimesteps = 1, ReportingCurrency = zar, Parallelize = false, LocalCorrelation = true, }; var sut = new AssetFxMCModel(buildDate, pfolio, aModel, settings, TestProviderHelper.CurrencyProvider, TestProviderHelper.FutureSettingsProvider, TestProviderHelper.CalendarProvider); return(sut); }
public static double PV(this CashFlowSchedule schedule, IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDf, bool updateEstimate, DayCountBasis basisFloat, DateTime?filterDate) { double totalPv = 0; for (var i = 0; i < schedule.Flows.Count; i++) { var flow = schedule.Flows[i]; if (filterDate.HasValue && flow.SettleDate < filterDate.Value) { continue; } double fv, pv, df; switch (flow.FlowType) { case FlowType.FixedRate: { if (updateState) { var rateLin = flow.FixedRateOrMargin; var yf = flow.YearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } case FlowType.FloatRate: { if (updateEstimate) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var rateLin = forecastCurve.GetForwardRate(s, e, RateType.Linear, basisFloat); rateLin += flow.FixedRateOrMargin; var yf = flow.YearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } case FlowType.FixedAmount: { fv = flow.Notional; if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } } } return(totalPv); }
private double PV(IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDf, bool updateEstimate) { double totalPv = 0; for (var i = 0; i < FlowScheduleFixed.Flows.Count; i++) { var flow = FlowScheduleFixed.Flows[i]; double fv, df; if (updateState) { var rateLin = flow.FixedRateOrMargin; var yf = flow.NotionalByYearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } var pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } } for (var i = 0; i < FlowScheduleFloat.Flows.Count; i++) { var flow = FlowScheduleFloat.Flows[i]; double fv, df; if (updateEstimate) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var rateLin = forecastCurve.GetForwardRate(s, e, RateType.Linear, BasisFloat); var yf = flow.NotionalByYearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } var pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } } return(totalPv); }