/// <summary> /// Create a surface from an FpML /// </summary> /// <param name="fpmlData"></param> public VolatilitySurface(Pair <PricingStructure, PricingStructureValuation> fpmlData) { IDayCounter dc = Actual365.Instance; var termPoints = new List <TermPoint> { TermPointFactory.Create(1.0m, new DateTime()), TermPointFactory.Create(0.99m, new DateTime().AddDays(10)), TermPointFactory.Create(0.97m, new DateTime().AddDays(100)) }; var termCurve = TermCurve.Create(new DateTime(), new InterpolationMethod { Value = "LinearInterpolation" }, true, termPoints); Interpolator = new TermCurveInterpolator(termCurve, new DateTime(), dc);//TODO need to create a surfaceinterpolator. _algorithm = "Linear"; SetFpMLData(fpmlData); // var holder = new PricingStructureAlgorithmsHolder(); bool doBuild = GetVolatilityMatrix().dataPoints.point == null; if (doBuild) { // var bootstrapperName = holder.GetValue(PricingStructureType.RateVolatilityMatrix, _algorithm, "Bootstrapper"); // Bootstrapper = Bootstrap(bootstrapperName, PricingStructure, PricingStructureValuation); } // SetInterpolator(PricingStructureValuation.baseDate.Value, _algorithm, holder); _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey()); ProcessVolatilityRepresentation(); }
// need a based date? // ///<summary> ///</summary> ///<param name="discountCurve"></param> ///<param name="baseDate"></param> ///<param name="frequency"></param> ///<param name="dayCounter"></param> ///<returns></returns> ///<exception cref="System.Exception"></exception> public static TermCurve ToZeroCurve(TermCurve discountCurve, DateTime baseDate, CompoundingFrequencyEnum frequency, IDayCounter dayCounter) { TermCurve result = TermCurve.Create(new List <TermPoint>()); foreach (TermPoint point in discountCurve.point) { DateTime pointDate = XsdClassesFieldResolver.TimeDimensionGetDate(point.term); double zeroRateDouble; if (baseDate != pointDate) { double time = dayCounter.YearFraction(baseDate, pointDate); zeroRateDouble = RateAnalytics.DiscountFactorToZeroRate((double)point.mid, time, frequency); } else { // set after the loop zeroRateDouble = 0; } TermPoint zeroPoint = TermPointFactory.Create(Convert.ToDecimal(zeroRateDouble), pointDate); zeroPoint.id = point.id; result.Add(zeroPoint); } if (result.point[0].mid == 0) { result.point[0].mid = result.point[1].mid; } return(result); }
/// <summary> /// </summary> /// <param name="discountCurve"></param> /// <param name="tenor"></param> /// <param name="baseDate"></param> /// <param name="interpolatedCurve"></param> /// <param name="paymentCalendar"></param> /// <param name="dayCounter"></param> /// <returns></returns> /// <exception cref="System.Exception"></exception> public static TermCurve ToForwardCurve(TermCurve discountCurve, Period tenor, DateTime baseDate, InterpolatedCurve interpolatedCurve, IBusinessCalendar paymentCalendar, IDayCounter dayCounter) { TermCurve result = TermCurve.Create(new List <TermPoint>()); var length = discountCurve.point.Length; var offset = new Offset { dayType = DayTypeEnum.Calendar, dayTypeSpecified = true, period = tenor.period, periodMultiplier = tenor.periodMultiplier, periodSpecified = true }; if (paymentCalendar == null) { return(result); } for (int i = 0; i < length - 1; i++) //This will only go to the penultimate point. Extrapolation required for more. { var pointStart = discountCurve.point[i]; DateTime startDate = XsdClassesFieldResolver.TimeDimensionGetDate(pointStart.term); var endDate = paymentCalendar.Advance(startDate, offset, BusinessDayConventionEnum.FOLLOWING); var endPoint = new DateTimePoint1D(baseDate, endDate); var endDF = interpolatedCurve.Value(endPoint); double time = dayCounter.YearFraction(startDate, endDate); var forwardRateDouble = RateAnalytics.DiscountFactorsToForwardRate((double)pointStart.mid, endDF, time); TermPoint forwardPoint = TermPointFactory.Create(Convert.ToDecimal(forwardRateDouble), startDate); forwardPoint.id = tenor.id; result.Add(forwardPoint); } return(result); }
private void SetInterpolator() { IDayCounter dc = Actual365.Instance; var termPoints = new List <TermPoint> { TermPointFactory.Create(1.0m, new DateTime()), TermPointFactory.Create(0.99m, new DateTime().AddDays(10)), TermPointFactory.Create(0.97m, new DateTime().AddDays(100)) }; var termCurve = TermCurve.Create(new DateTime(), new InterpolationMethod { Value = "LinearInterpolation" }, true, termPoints); Interpolator = new TermCurveInterpolator(termCurve, new DateTime(), dc); }
///<summary> ///</summary> ///<param name="discountCurve"></param> ///<param name="baseDate"></param> ///<param name="forwardRateTenor"></param> ///<param name="priceableXibor"></param> ///<returns></returns> public TermCurve ToPriceableXiborForwardCurve(TermCurve discountCurve, DateTime baseDate, Period forwardRateTenor, PriceableXibor priceableXibor) //TODO { //CompoundingFrequency frequency = CompoundingFrequencyHelper.Create("Annual"); var dates = discountCurve.GetListTermDates(); var yearFractions = new List <double>(); foreach (var date in dates) { var yearFraction = (date - baseDate).TotalDays / 365.0;//TODO extend this with a general daycountraction. yearFractions.Add(yearFraction); } var midValues = discountCurve.GetListMidValues(); var discountFactors = new List <double>(Array.ConvertAll(midValues.ToArray(), Convert.ToDouble)); var forwardTermCurve = TermCurve.Create(new List <TermPoint>()); var index = 0; foreach (var startOfPeriodDateTime in dates) { var yearFractionsbeginPeriod = yearFractions[index]; var endOfPeriodDateTime = forwardRateTenor.Add(startOfPeriodDateTime); var yearFractionAtEndOfPeriod = (endOfPeriodDateTime - baseDate).TotalDays / 365.0; //get df corresponding to end of period // IInterpolation interpolation = new LinearRateInterpolation(); interpolation.Initialize(yearFractions.ToArray(), discountFactors.ToArray()); var dfAtEndOfPeriod = interpolation.ValueAt(yearFractionAtEndOfPeriod, true); var dfAtTheBeginingOfPeriod = discountFactors[index]; var forwardRate = (dfAtTheBeginingOfPeriod / dfAtEndOfPeriod - 1) / (yearFractionAtEndOfPeriod - yearFractionsbeginPeriod); var zeroPoint = TermPointFactory.Create(Convert.ToDecimal(forwardRate), startOfPeriodDateTime); forwardTermCurve.Add(zeroPoint); ++index; } return(forwardTermCurve); }
/// <summary> /// Unpack a raw surface and create a VolatilitySurface /// The object array is assumed to be zero based when it is passed to the constructor /// (That is any Excel idiosyncrasies have been expunged) /// We'll test and modify if necessary to zero base the array /// </summary> /// <param name="rawSurface"></param> /// <param name="surfaceId"></param> /// <param name="date"></param> /// <param name="buildDateTime"></param> // /// <param name="algorithm">The algorithm for interpolation. Not implemented yet.</param> public VolatilitySurface(object[,] rawSurface, VolatilitySurfaceIdentifier surfaceId, DateTime date, DateTime buildDateTime) { PricingStructureIdentifier = surfaceId; IDayCounter dc = Actual365.Instance; var termPoints = new List <TermPoint> { TermPointFactory.Create(1.0m, new DateTime()), TermPointFactory.Create(0.99m, new DateTime().AddDays(10)), TermPointFactory.Create(0.97m, new DateTime().AddDays(100)) }; var termCurve = TermCurve.Create(new DateTime(), new InterpolationMethod { Value = "LinearInterpolation" }, true, termPoints); Interpolator = new TermCurveInterpolator(termCurve, date, dc);//TODO need to create a surfaceinterpolator. var zeroedRawSurface = rawSurface.GetLowerBound(0) == 1 ? RedimensionRawSurface(rawSurface) : rawSurface; _algorithm = "Linear"; // An ugly trick to find out if this is a cube or a surface bool isCube = !double.TryParse(zeroedRawSurface[1, 1].ToString(), out _); // Extract the strikes/tenors/expiries and build the surface var expiry = ExtractExpiryFromRawSurface(zeroedRawSurface); var term = ExtractTenorFromRawSurface(zeroedRawSurface, isCube); var strike = ExtractStrikeFromRawSurface(zeroedRawSurface, isCube); var volatility = ExtractVolatilitiesFromRawSurface(zeroedRawSurface, isCube); _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey()); var points = ProcessRawSurface(expiry, term, strike, volatility); PricingStructure = new VolatilityRepresentation { name = surfaceId.Name, id = surfaceId.Id, asset = new AnyAssetReference { href = "Unknown" }, }; PricingStructureValuation = new VolatilityMatrix { dataPoints = new MultiDimensionalPricingData { point = points }, objectReference = new AnyAssetReference { href = PricingStructure.id }, baseDate = new IdentifiedDate { Value = date }, buildDateTime = buildDateTime, buildDateTimeSpecified = true }; // Record the row/column sizes of the inputs _matrixRowCount = expiry.Length; _matrixRowCount *= term?.Length ?? 1; // Columns includes expiry and term (tenor) if it exists. _matrixColumnCount = strike.Length + 1; _matrixColumnCount += term != null ? 1 : 0; // Generate an interpolator to use if (term == null || term.Length == 0) { _interpolation = new BilinearInterpolator(); } else { _interpolation = new TrilinearInterpolator(); } }
/// <summary> /// The constructor /// </summary> /// <param name="assetRef">The Asset this volatility models</param> /// <param name="name">The id to use with this matrix</param> /// <param name="date">The value date relating to this surface</param> /// <param name="expiry">An array of expiry definitions</param> /// <param name="term">An array of tenors or null if there is no term dimension.</param> /// <paparam name="strike">An array of strike descriptions</paparam> /// <param name="strike">The strike array.</param> /// <param name="volatility">A 2d array of volatilities. /// This must be equal to (expiry.Count x (1 <= y <= term.Count) x strike.Count </param> public VolatilitySurface(string assetRef, string name, DateTime date, string[] expiry, string[] term, string[] strike, double[,] volatility) { IDayCounter dc = Actual365.Instance; var termPoints = new List <TermPoint> { TermPointFactory.Create(1.0m, new DateTime()), TermPointFactory.Create(0.99m, new DateTime().AddDays(10)), TermPointFactory.Create(0.97m, new DateTime().AddDays(100)) }; var termCurve = TermCurve.Create(new DateTime(), new InterpolationMethod { Value = "LinearInterpolation" }, true, termPoints); Interpolator = new TermCurveInterpolator(termCurve, date, dc);//TODO need to create a surfaceinterpolator. _algorithm = "Linear"; _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey()); var points = ProcessRawSurface(expiry, term, strike, volatility); PricingStructure = new VolatilityRepresentation { name = name , id = name + date.ToString("yyyyMMdd") , asset = new AnyAssetReference { href = assetRef } }; PricingStructureValuation = new VolatilityMatrix { dataPoints = new MultiDimensionalPricingData { point = points } , objectReference = new AnyAssetReference { href = PricingStructure.id } , baseDate = new IdentifiedDate { Value = date } , buildDateTime = DateTime.Now , buildDateTimeSpecified = true }; // Record the row/column sizes of the inputs _matrixRowCount = expiry.Length; _matrixRowCount *= term?.Length ?? 1; // Columns includes expiry and term (tenor) if it exists. _matrixColumnCount = strike.Length + 1; _matrixColumnCount += term != null ? 1 : 0; //TODO // Generate an interpolator to use if (term == null || term.Length == 0) { _interpolation = new BilinearInterpolator(); } else { _interpolation = new TrilinearInterpolator(); } }