/// <summary> /// Generate an array of PricingStructurePoint from a set of input arrays /// The array can then be added to the Matrix /// </summary> /// <param name="expiry">Expiry values to use</param> /// <param name="strike">Strike values to use</param> /// <param name="volatility">An array of volatility values</param> /// <returns></returns> private static PricingStructurePoint[] ProcessRawSurface(String[] expiry, Double[] strike, double[,] volatility) { var expiryLength = expiry.Length; var strikeLength = strike.Length; var pointIndex = 0; var points = new PricingStructurePoint[expiryLength * strikeLength]; for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++) { for (var strikeIndex = 0; strikeIndex < strikeLength; strikeIndex++) { // Extract the row,column indexed volatility var vol = (decimal)volatility[expiryIndex, strikeIndex]; // Add the value to the points array (dataPoints entry in the matrix) var coordinates = new PricingDataPointCoordinate[1]; coordinates[0] = PricingDataPointCoordinateFactory.Create(expiry[expiryIndex], null, (Decimal)strike[strikeIndex]); var pt = new PricingStructurePoint { value = vol, valueSpecified = true, coordinate = coordinates }; points[pointIndex++] = pt; } } return(points); }
/// <summary> /// Generate an array of PricingStructurePoint from a set of input arrays /// The array can then be added to the Matrix /// </summary> /// <param name="expiry">Expiry values to use</param> /// <param name="tenors">Tenor values to use</param> /// <param name="volatility">An array of volatility values</param> /// <param name="underlyingAssetReference">The underlying asset references.</param> /// <returns></returns> private PricingStructurePoint[] ProcessRawSurface(String[] expiry, String[] tenors, double[,] volatility, AssetReference underlyingAssetReference) { var expiryLength = expiry.Length; var tenorsLength = tenors.Length; var pointIndex = 0; var points = new PricingStructurePoint[expiryLength * tenorsLength]; for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++) { // extract the current expiry var expiryKeyPart = expiry[expiryIndex]; for (var strikeIndex = 0; strikeIndex < tenorsLength; strikeIndex++) { // Extract the strike to use in the helper key var tenorKeyPart = tenors[strikeIndex]; // Extract the row,column indexed volatility var vol = (decimal)volatility[expiryIndex, strikeIndex]; var key = new ExpiryTenorStrikeKey(expiryKeyPart, tenorKeyPart); _matrixIndexHelper.Add(key, pointIndex); // Add the value to the points array (dataPoints entry in the matrix) var coordinates = new PricingDataPointCoordinate[1]; coordinates[0] = PricingDataPointCoordinateFactory.Create(expiry[expiryIndex], tenors[strikeIndex], null, "ATMSurface"); var pt = new PricingStructurePoint { value = vol, valueSpecified = true, coordinate = coordinates, underlyingAssetReference = underlyingAssetReference }; points[pointIndex++] = pt; } } return(points); }
private static PricingStructurePoint[] ProcessRawSurface(string[] expiries, string[] tenors, decimal[] strikes, decimal[,] volatility, PriceQuoteUnits strikeQuoteUnits, AssetReference underlyingAssetReference) { var expiryLength = expiries.Length; var strikeLength = strikes.Length; var tenorLength = tenors.Length; var points = new List <PricingStructurePoint>(); for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++) { for (var strikeIndex = 0; strikeIndex < strikeLength; strikeIndex++) { for (var tenorIndex = 0; tenorIndex < tenorLength; tenorIndex++) { // Extract the row,column indexed volatility var vol = volatility[expiryIndex + tenorIndex * expiryLength, strikeIndex]; // Add the value to the points array (dataPoints entry in the matrix) var coordinates = new PricingDataPointCoordinate[1]; coordinates[0] = PricingDataPointCoordinateFactory.Create(expiries[expiryIndex], tenors[tenorIndex], strikes[strikeIndex]); var point = new PricingStructurePoint { value = vol, valueSpecified = true, coordinate = coordinates, underlyingAssetReference = underlyingAssetReference, quoteUnits = strikeQuoteUnits }; points.Add(point); } } } return(points.ToArray()); }
/// <summary> /// Maps from double arrays to an IPoint list. The number of values is equal to the multiplication of xCoords and yCoords. /// </summary> /// <param name="pt">A PricingStructurePoint.</param> public static Point CreatePoint(PricingStructurePoint pt) { //TODO trap the generic. Also add baseDate for carry calculations. var coordinate = pt.coordinate[0]; if (coordinate.expiration == null || coordinate.strike == null) { return(null); } var expiry = coordinate.expiration[0].Items[0] as Period; var strike = (double)coordinate.strike[0]; var value = Convert.ToDouble(pt.value); Point point; var expiryTime = expiry.ToYearFraction(); if (coordinate.term != null) { var term = coordinate.term[0].Items[0] as Period; var termTime = term.ToYearFraction(); point = new Point3D(expiryTime, termTime, strike, value); } else { point = new Point2D(expiryTime, strike, value); } return(point); }
///<summary> ///</summary> ///<param name="expiryByStrikeSurface"></param> ///<returns></returns> ///<exception cref="NotImplementedException"></exception> // {null, 0.25, 0.50, 0.75, 1.00},//strike row // {"1y", 0.11, 0.12, 0.13, 0.14},// // {"2y", 0.21, 0.22, 0.23, 0.24},// // {"3y", 0.31, 0.32, 0.33, 0.34},// // {"4y", 0.41, 0.42, 0.43, 0.44},// // {"5y", 0.51, 0.52, 0.53, 0.54},// // {"6y", 0.61, 0.62, 0.63, 0.64},//expiry - 6 // {"7y", 0.71, 0.72, 0.73, 0.74} //expiry - 7 public static List <PricingStructurePoint> ExtractDataPoints(object[,] expiryByStrikeSurface) { var result = new List <PricingStructurePoint>(); // extract // for (int expiryIndex = expiryByStrikeSurface.GetLowerBound(0) + 1; expiryIndex <= expiryByStrikeSurface.GetUpperBound(0); ++expiryIndex) { object expiryAsObject = expiryByStrikeSurface[expiryIndex, 0]; for (int strikeIndex = expiryByStrikeSurface.GetLowerBound(1) + 1; strikeIndex <= expiryByStrikeSurface.GetUpperBound(1); ++strikeIndex) { object strikeAsObject = expiryByStrikeSurface[0, strikeIndex]; object volatilityAsObject = expiryByStrikeSurface[expiryIndex, strikeIndex]; var pricingStructurePoint = new PricingStructurePoint { coordinate = new[] { new PricingDataPointCoordinate() }, valueSpecified = true, value = Convert.ToDecimal(volatilityAsObject) }; // value // // expiry // pricingStructurePoint.coordinate[0].expiration = new[] { new TimeDimension() }; pricingStructurePoint.coordinate[0].expiration[0].Items = new object[] { 1 }; pricingStructurePoint.coordinate[0].expiration[0].Items[0] = PeriodHelper.Parse(expiryAsObject.ToString()); // strike // pricingStructurePoint.coordinate[0].strike = new[] { Convert.ToDecimal(strikeAsObject) }; result.Add(pricingStructurePoint); } } return(result); }
/// <summary> /// The volatility value. /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <param name="coord"></param> public VolatilityValue(string name, object value, IPoint coord) : base(name, value, coord) { PricePoint = new PricingStructurePoint { id = name, value = Convert.ToDecimal(value), valueSpecified = true, coordinate = new[] { ((Coordinate)coord).PricingDataCoordinate } }; }
///<summary> /// A swaption ppd grid. ///</summary> ///<param name="rows"></param> ///<param name="cols"></param> ///<param name="data"></param> public SwaptionPPDGrid(string[] rows, string[] cols, object[][] data) : this() { measureType = new AssetMeasureType { Value = "PPD" }; quoteUnits = new PriceQuoteUnits { Value = "points" }; // build the co-ordinate tree.. data[row][column] // row = expiry, column = tenor var points = new List <PricingStructurePoint>(); for (int row = 0; row < rows.Length; row++) { for (int col = 0; col < cols.Length; col++) { if (data[row][col] != null) { var currentPoint = new PricingStructurePoint { coordinate = new PricingDataPointCoordinate[1] }; // Set up the coordinate for this point currentPoint.coordinate[0] = new PricingDataPointCoordinate { expiration = new TimeDimension[1] }; // The row - Expiry currentPoint.coordinate[0].expiration[0] = new TimeDimension { Items = new object[] { PeriodHelper.Parse(rows[row]) } }; // The column - Tenor currentPoint.coordinate[0].term = new TimeDimension[1]; currentPoint.coordinate[0].term[0] = new TimeDimension { Items = new object[] { PeriodHelper.Parse(cols[col]) } }; // The data value currentPoint.valueSpecified = true; currentPoint.value = Convert.ToDecimal(data[row][col]); points.Add(currentPoint); } } } point = points.ToArray(); }
/// <summary> /// Generate an array of PricingStructurePoint from a set of input arrays /// The array can then be added to the Matrix /// </summary> /// <param name="expiry">Expiry values to use</param> /// <param name="term">Tenor values to use</param> /// <param name="strike">Strike values to use</param> /// <param name="volatility">An array of volatility values</param> /// <returns></returns> private PricingStructurePoint[] ProcessRawSurface(string[] expiry, string[] term, string[] strike, double[,] volatility) { var expiryLength = expiry.Length; var termLength = term?.Length ?? 1; var strikeLength = strike.Length; var pointIndex = 0; var points = new PricingStructurePoint[expiryLength * termLength * strikeLength]; // Offset row counter var row = 0; for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++) { // extract the current expiry var expiryKeyPart = expiry[expiryIndex]; for (var termIndex = 0; termIndex < termLength; termIndex++) { // extract the current tenor (term) of null if there are no tenors var tenorKeyPart = term?[termIndex]; // Offset column counter var column = 0; for (var strikeIndex = 0; strikeIndex < strikeLength; strikeIndex++) { // Extract the strike to use in the helper key var strikeKeyPart = strike[strikeIndex]; // Extract the row,column indexed volatility var vol = (decimal)volatility[row, column++]; // Build the index offset list helper var key = new ExpiryTenorStrikeKey(expiryKeyPart, tenorKeyPart, strikeKeyPart); _matrixIndexHelper.Add(key, pointIndex); // Add the value to the points array (dataPoints entry in the matrix) var val = new VolatilityValue(null, vol, new Coordinate(expiryKeyPart, tenorKeyPart, strike[strikeIndex])); points[pointIndex++] = val.PricePoint; } row++; } } return(points); }
/// <summary> /// Maps from double arrays to an IPoint list. The number of values is equal to the multiplication of xCoords and yCoords. /// </summary> /// <param name="pt">A PricingStructurePoint.</param> /// <param name="baseDate"></param> public static double[] To2DArray(PricingStructurePoint pt, DateTime?baseDate) { //TODO trap the generic. Also add baseDate for carry calculations. var coordinate = pt.coordinate[0]; if (coordinate.expiration == null) { return(null); } double value = Convert.ToDouble(pt.value); var expiry = coordinate.expiration[0].Items[0] as Period; double expiryTime; if (expiry != null) { expiryTime = expiry.ToYearFraction(); } else if (baseDate.HasValue && coordinate.expiration[0].Items[0] is DateTime) { var expiryDate = (DateTime)coordinate.expiration[0].Items[0]; expiryTime = (expiryDate - baseDate.Value).TotalDays / 365d; } else { throw new InvalidCastException("Coordinate expiration must be a Period or DateTime"); } double yDimension = (coordinate.term?[0].Items[0] as Period)?.ToYearFraction() ?? (coordinate.strike != null ? (double)coordinate.strike[0] : 0); var point = new[] { expiryTime, yDimension, value }; return(point); }
/// <summary> /// The volatility value. /// </summary> /// <param name="point"></param> public VolatilityValue(PricingStructurePoint point) : base(point.id, point.value, new Coordinate(point.coordinate[0])) { PricePoint = point; }
/// <summary> /// /// </summary> /// <param name="logger"></param> /// <param name="cache"></param> /// <param name="nameSpace"></param> /// <param name="properties"></param> /// <param name="expiries"></param> /// <param name="vols"></param> /// <param name="inputInstruments"></param> /// <param name="inputSwapRates"></param> /// <param name="inputBlackVolRates"></param> protected ExpiryTermStrikeVolatilitySurface(ILogger logger, ICoreCache cache, String nameSpace, NamedValueSet properties, DateTime[] expiries, double[] vols, string[] inputInstruments, double[] inputSwapRates, double[] inputBlackVolRates) { Algorithm = PropertyHelper.ExtractAlgorithm(properties); PricingStructureIdentifier = new VolatilitySurfaceIdentifier(properties); var surfaceId = (VolatilitySurfaceIdentifier)PricingStructureIdentifier; var expiryLength = expiries.Length; var pointIndex = 0; var points = new PricingStructurePoint[expiryLength]; _matrixIndexHelper = new SortedList <ExpiryTenorStrikeKey, int>(new ExpiryTenorStrikeKey()); for (var expiryIndex = 0; expiryIndex < expiryLength; expiryIndex++) { // extract the current expiry var expiryKeyPart = expiries[expiryIndex]; var key = new ExpiryTenorStrikeKey(expiryKeyPart.ToString(CultureInfo.InvariantCulture), 0); _matrixIndexHelper.Add(key, pointIndex); // Add the value to the points array (dataPoints entry in the matrix) var coordinates = new PricingDataPointCoordinate[1]; coordinates[0] = new PricingDataPointCoordinate { expiration = new TimeDimension[1] }; coordinates[0].expiration[0] = new TimeDimension { Items = new object[] { expiries[expiryIndex] } }; var pt = new PricingStructurePoint { value = (decimal)vols[expiryIndex], valueSpecified = true, coordinate = coordinates, }; points[pointIndex++] = pt; } // Record the row/column sizes of the inputs _matrixRowCount = expiries.Length; _matrixColumnCount = 1; PricingStructure = CreateVolatilityRepresentation(surfaceId); PricingStructureValuation = CreateDataPoints(points, surfaceId); if (inputInstruments != null) { int inputCount = inputInstruments.GetUpperBound(0); var assetQuotes = new List <BasicAssetValuation>(); var assetSet = new List <Asset>(); var itemsList = new List <ItemsChoiceType19>(); for (int i = 0; i <= inputCount; i++) { var assetProperties = new PriceableAssetProperties(inputInstruments[i]); assetSet.Add(new SimpleIRSwap { id = inputInstruments[i], term = assetProperties.TermTenor }); var rateQuote = BasicQuotationHelper.Create((decimal)inputSwapRates[i], AssetMeasureEnum.MarketQuote, PriceQuoteUnitsEnum.DecimalRate); var volQuote = BasicQuotationHelper.Create((decimal)inputBlackVolRates[i], AssetMeasureEnum.Volatility, PriceQuoteUnitsEnum.LogNormalVolatility); assetQuotes.Add(new BasicAssetValuation { objectReference = new AnyAssetReference { href = inputInstruments[i] }, definitionRef = assetProperties.TermTenor.ToString(), quote = new[] { rateQuote, volQuote } }); itemsList.Add(ItemsChoiceType19.simpleIrSwap);//TODO NOt actually correct. } var instrumentSet = new InstrumentSet { Items = assetSet.ToArray(), ItemsElementName = itemsList.ToArray() }; ((VolatilityMatrix)PricingStructureValuation).inputs = new QuotedAssetSet { assetQuote = assetQuotes.ToArray(), instrumentSet = instrumentSet }; } // Generate an interpolator to use double[] expiryTerms = expiries.Select(a => (surfaceId.BaseDate - a).TotalDays / 365d).ToArray(); var holder = new PricingStructureAlgorithmsHolder(logger, cache, nameSpace, surfaceId.PricingStructureType, surfaceId.Algorithm); var curveInterpolationMethod = InterpolationMethodHelper.Parse(holder.GetValue("CurveInterpolation")); Interpolator = new VolSurfaceInterpolator(expiryTerms, new double[] { 1 }, new Matrix(vols), curveInterpolationMethod, true); }
/// <summary> /// An FpML constructor. /// </summary> /// <param name="pt"></param> /// <param name="baseDate"></param> public PricingDataPoint2D(PricingStructurePoint pt, DateTime?baseDate) : base(PointHelpers.To2DArray(pt, baseDate)) { PricingDataPointCoordinate = pt.coordinate[0]; }
/// <summary> /// Construct an FpML MultiDimensionalPricingData from the spreadsheet values /// </summary> /// <param name="headers">The columns to write</param> /// <param name="data">The values to store</param> /// <param name="settings">The settings used by this matrix</param> /// <param name="valueDate">The valuation date</param> /// <param name="surfaceId">The id of this surface</param> public CapFloorATMMatrix(string[] headers, object[][] data, object[][] settings, DateTime valueDate, string surfaceId) : this() { // Include a QuotedAssetSet to hold the Settings object used to generate this SABR parameters Matrix if (settings != null) { Settings = AssignSettings(settings); } id = surfaceId; baseDate = new IdentifiedDate { Value = valueDate }; var rows = data.GetUpperBound(0) + 1; var points = new List <PricingStructurePoint>(); int expiry = Find("Expiry", headers); int atm = Find("ATM", headers); int type = Find("Type", headers); int ppd = Find("PPD", headers); for (int row = 0; row < rows; row++) { var point = new PricingStructurePoint(); if (data[row][0] != null) { // Populate each data point from the data array for (var column = 0; column < headers.Length; column++) { object datum = data[row][column]; if (column == expiry) { // Add the coordinate value (the expiry) var expiration = PeriodHelper.Parse(datum.ToString()); point.coordinate = new PricingDataPointCoordinate[1]; point.coordinate[0] = new PricingDataPointCoordinate { expiration = new TimeDimension[1] }; point.coordinate[0].expiration[0] = new TimeDimension { Items = new object[] { expiration } }; } else if (column == atm) { point.measureType = new AssetMeasureType { Value = "ATM" }; point.valueSpecified = true; point.value = Convert.ToDecimal(datum); } else if (column == ppd) { point.measureType = new AssetMeasureType { Value = "PPD" }; point.valueSpecified = true; point.value = Convert.ToDecimal(datum); } else if (column == type) { point.cashflowType = new CashflowType { Value = datum.ToString() }; } else { throw new ArgumentException("Unknown column name: " + column); } } } points.Add(point); } dataPoints = new MultiDimensionalPricingData { point = points.ToArray() }; }
/// <summary> /// Maps from double arrays to an IPoint list. The number of values is equal to the multiplication of xCoords and yCoords. /// </summary> /// <param name="pt">A PricingStructurePoint.</param> public static double[] To2DArray(PricingStructurePoint pt) { return(To2DArray(pt, null)); }
/// <summary> /// A PricingDataPoint3D. /// </summary> /// <param name="pt"></param> public PricingDataPoint3D(PricingStructurePoint pt) : base(PointHelpers.To3DArray(pt)) { PricingDataPointCoordinate = pt.coordinate[0]; }