/// <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); }
/// <summary> /// This call returns an IValue structure for an exact match with a given point. /// If the point does not exist this method will return null. /// </summary> /// <param name="pt">The point in the surface/cube to get the value of</param> /// <returns>An IValue object representing the value/coordinates of the point</returns> public override IValue GetValue(IPoint pt) { IValue val = null; string tenor = null; string strike; var expiry = ((Period)pt.Coords[0]).ToString(); if (pt.Coords.Count > 2) { tenor = ((Period)pt.Coords[1]).ToString(); strike = pt.Coords[2].ToString(); } else { strike = pt.Coords[1].ToString(); } var key = new ExpiryTenorStrikeKey(expiry, tenor, strike); if (_matrixIndexHelper.ContainsKey(key)) { var idx = _matrixIndexHelper[key]; var volatility = GetVolatilityMatrix().dataPoints.point[idx].value; var id = GetVolatilityMatrix().dataPoints.point[idx].id; val = new VolatilityValue(id, volatility, pt); } return(val); }
/// <summary> /// This call returns an IValue structure for an exact match with a given point. /// If the point does not exist this method will return null. /// </summary> /// <param name="pt">The point in the surface/cube to get the value of</param> /// <returns>An IValue object representing the value/coordinates of the point</returns> public override IValue GetValue(IPoint pt) { string expiry = ((Period)pt.Coords[0]).ToString(); string tenor = ((Period)pt.Coords[1]).ToString(); decimal strike = Convert.ToDecimal(pt.Coords[2]); var key = new ExpiryTenorStrikeKey(expiry, tenor, strike); if (_matrixIndexHelper.ContainsKey(key)) { int idx = _matrixIndexHelper[key]; decimal volatility = VolatilityMatrix.dataPoints.point[idx].value; string id = VolatilityMatrix.dataPoints.point[idx].id; return(new VolatilityValue(id, volatility, pt)); } return(null); }
/// <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> /// /// </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); }