/// <summary> /// Calculate the end date of the FRA which /// will replace the cash instrument /// </summary> /// <param name="calendar"></param> /// <param name="assetController"></param> /// <returns></returns> public DateTime CalculateFraEndTime(IBusinessCalendar calendar, IPriceableRateAssetController assetController)//, //string currency, string rollConvention) { var deposit = (PriceableDeposit)assetController; BusinessDayConventionEnum adjustment = deposit.BusinessDayAdjustments.businessDayConvention; return(DatePeriodHelper.AddPeriod(assetController.GetRiskMaturityDate(), "3M", calendar, adjustment.ToString(), null)); }
/// <summary> /// Initializes a new instance of the <see cref="RateAssetQuote"/> class. /// </summary> /// <param name="priceableAsset">The priceable asset.</param> /// <param name="baseDate">The base date.</param> /// <param name="interpolation">The interpolation.</param> /// <param name="extrapolation">if set to <c>true</c> [extrapolation].</param> /// <param name="dfs">The discount factors.</param> /// <param name="tolerance">The tolerance.</param> public RateAssetQuote(IPriceableRateAssetController priceableAsset, DateTime baseDate, InterpolationMethod interpolation, bool extrapolation, IDictionary <DateTime, double> dfs, double tolerance) { PriceableAsset = priceableAsset; BaseDate = baseDate; Dfs = dfs; InterpolationMethod = interpolation; Extrapolation = extrapolation; Tolerance = tolerance; Quote = MarketQuoteHelper.NormalisePriceUnits(PriceableAsset.MarketQuote, "DecimalRate").value; }
/// <summary> /// PreCondition: the initialCurve must have been /// assigned /// </summary> /// <param name="index"></param> private void CheckDepositInstrument(int index) { if (_initialCurve == null) { throw new System.Exception("The initial curve has not been constructed."); } IPriceableRateAssetController rateAssetController = _initialCurve.PriceableRateAssets[index]; if (!rateAssetController.Id.ToUpper().Contains("DEPOSIT")) { throw new ArgumentException("The specified asset is not CASH asset."); } }
/// <summary> /// Bootstraps the specified priceable assets. /// </summary> /// <param name="priceableAssets">The priceable assets.</param> /// <param name="baseZeroCurve">The base Zero Curve</param> /// <param name="algorithmHolder">The algorithmHolder</param> /// <returns></returns> public TermPoint[] Bootstrap(List <IPriceableRateAssetController> priceableAssets, IRateCurve baseZeroCurve, PricingStructureAlgorithmsHolder algorithmHolder) { var items = new SortedDictionary <DateTime, Pair <string, decimal> >(); DateTime baseDate = baseZeroCurve.GetBaseDate(); items.Add(baseDate, new Pair <string, decimal>(null, 1m)); bool firstTime = true; const double compoundingPeriod = 0.25; IPriceableRateAssetController previousAsset = null; IEnumerable <TermPoint> basePillars = baseZeroCurve.GetTermCurve().point; IDayCounter dayCounter = null; foreach (IPriceableRateAssetController priceableAsset in priceableAssets) { List <DateTime> assetDates; if (priceableAsset is PriceableSwapRateAsset swap) { dayCounter = DayCounterHelper.Parse(swap.DayCountFraction.Value); assetDates = swap.AdjustedPeriodDates; } else { PriceableDeposit deposit = priceableAsset as PriceableDeposit; if (deposit == null) { throw new ArgumentException( $"PriceableAsset must be a PriceableSwapRateAsset or PriceableDeposit, '{priceableAsset.GetType()}' is not implemented."); } dayCounter = DayCounterHelper.Parse(deposit.Deposit.dayCountFraction.Value); assetDates = new List <DateTime> { deposit.AdjustedStartDate, deposit.GetRiskMaturityDate() }; } DateTime maturityDate = priceableAsset.GetRiskMaturityDate(); if (items.Keys.Contains(maturityDate)) { throw new ArgumentException( $"Duplicate priceable asset on '{maturityDate:yyyy-MM-dd}'", nameof(priceableAssets)); } //The min and max values to use with the solver. const int xmin = -1; const int xmax = 1; var accuracy = 10 ^ -12; if (firstTime) { firstTime = false; // Solve to find the quarterly compounded zero rate spread var solverFunctions = new NewtonRaphsonSolverFunctions(priceableAsset, null, algorithmHolder, baseZeroCurve, baseDate, items, compoundingPeriod, ZeroRateSpreads, dayCounter, assetDates); var solver = new Newton(); var initialGuess = (double)priceableAsset.MarketQuote.value; //var solution = new CenteredFiniteDifferenceDerivative(); Func <double, double> f = solverFunctions.ShortEndTargetFunction; var derivativeOfTargetFunction = new NumericalDerivative().CreateDerivativeFunctionHandle(f, 1); double zeroRateSpread = solver.Solve(f, derivativeOfTargetFunction, accuracy, initialGuess, xmin, xmax); // add first point DateTime startDate = assetDates.First(); decimal df = (decimal)GetAdjustedDiscountFactor(baseDate, startDate, dayCounter, zeroRateSpread, baseZeroCurve); if (startDate != baseDate) { items.Add(startDate, new Pair <string, decimal>(null, df)); } ZeroRateSpreads.Add(maturityDate, zeroRateSpread); // add extra points IEnumerable <TermPoint> extraPoints = basePillars.Where(b => (DateTime)b.term.Items[0] > startDate && (DateTime)b.term.Items[0] < maturityDate); // Extrapolate the preceding extra points foreach (TermPoint extraPoint in extraPoints) { DateTime date = (DateTime)extraPoint.term.Items[0]; df = (decimal)GetAdjustedDiscountFactor(baseDate, date, dayCounter, zeroRateSpread, baseZeroCurve); items.Add(date, new Pair <string, decimal>(extraPoint.id, df)); } // add final point df = (decimal)GetAdjustedDiscountFactor(baseDate, maturityDate, dayCounter, zeroRateSpread, baseZeroCurve); items.Add(maturityDate, new Pair <string, decimal>(priceableAsset.Id, df)); } else { items.Add(maturityDate, new Pair <string, decimal>(priceableAsset.Id, 0)); ZeroRateSpreads.Add(maturityDate, (double)priceableAsset.MarketQuote.value); // Solve to find the quarterly compounded zero rate spread var solverFunctions = new NewtonRaphsonSolverFunctions(priceableAsset, previousAsset, algorithmHolder, baseZeroCurve, baseDate, items, compoundingPeriod, ZeroRateSpreads, dayCounter, assetDates); Func <double, double> f = solverFunctions.LongEndTargetFunction; var solver = new Newton(); var initialGuess = (double)priceableAsset.MarketQuote.value; var derivativeOfTargetFunction = new NumericalDerivative().CreateDerivativeFunctionHandle(f, 1); double zeroRateSpread = solver.Solve(f, derivativeOfTargetFunction, accuracy, initialGuess, xmin, xmax); // Update discount factor value decimal df = (decimal)GetAdjustedDiscountFactor(baseDate, maturityDate, dayCounter, zeroRateSpread, baseZeroCurve); items[maturityDate].Second = df; ZeroRateSpreads[maturityDate] = zeroRateSpread; solverFunctions.UpdateDiscountFactors(baseDate); } previousAsset = priceableAsset; } // Extrapolate the following extra points IEnumerable <TermPoint> finalPoints = basePillars.Where(b => (DateTime)b.term.Items[0] > items.Last().Key); KeyValuePair <DateTime, double> zeroRateSpreadFinal = ZeroRateSpreads.Last(); foreach (TermPoint extraPoint in finalPoints) { DateTime date = (DateTime)extraPoint.term.Items[0]; decimal df = (decimal)GetAdjustedDiscountFactor(baseDate, date, dayCounter, zeroRateSpreadFinal.Value, baseZeroCurve); items.Add(date, new Pair <string, decimal>(extraPoint.id, df)); } return(TermPointsFactory.Create(items)); }
/// <summary> /// Initializes a new instance of the <see cref="RateAssetQuote"/> class. /// </summary> /// <param name="priceableAsset">The priceable asset.</param> /// <param name="baseDate">The base date.</param> /// <param name="interpolation">The interpolation.</param> /// <param name="extrapolation">if set to <c>true</c> [extrapolation].</param> /// <param name="dfs">The discount factors.</param> public RateAssetQuote(IPriceableRateAssetController priceableAsset, DateTime baseDate, InterpolationMethod interpolation, bool extrapolation, IDictionary <DateTime, double> dfs) : this(priceableAsset, baseDate, interpolation, extrapolation, dfs, DefaultTolerance) { }
/// <summary> /// Calculate the start date of the FRA which /// will replace the cash instrument /// </summary> /// <param name="assetController"></param> /// <returns></returns> public DateTime CalculateFraStartTime(IPriceableRateAssetController assetController) { return(assetController.GetRiskMaturityDate()); }