Applying compounding frequency for calibrating curves

#1

Hi All,

We have a use case of curve calibration where we want to apply compounding frequency ANNUAL instead of continuous compounding frequency while calculating ZERO RATES.However i donot see any difference in the rates calculated after applying the compounding frequency.

ResourceLocator groupsResource = ResourceLocator
					.ofFile((File) new File(String.valueOf(pathConfig) +"/"+outputCurveGroupName+"_Groups.csv"));
ResourceLocator settingsResource = ResourceLocator
					.ofFile((File) new File(String.valueOf(pathConfig) +"/"+outputCurveGroupName+"_CurveSettings.csv"));
ResourceLocator nodesResource = ResourceLocator
					.ofFile((File) new File(String.valueOf(pathConfig) +"/"+outputCurveGroupName+"_CurveNodes.csv"));
ResourceLocator quotesResource = ResourceLocator
					.ofFile((File) new File(String.valueOf(pathConfig) +"/"+inputCurveGroupName+"_CurveQuotes.csv"));
LocalDate valuationDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
ImmutableMap quotes = QuotesCsvLoader.load((LocalDate) valuationDate,
					(ResourceLocator[]) new ResourceLocator[] { quotesResource });
MarketData marketData = MarketData.of((LocalDate) valuationDate, (Map) quotes);

ImmutableMap defns = RatesCalibrationCsvLoader.load((ResourceLocator) groupsResource,
					(ResourceLocator) settingsResource, (ResourceLocator[]) new ResourceLocator[] { nodesResource });
CurveGroupDefinition curveGroupDefinition = ((CurveGroupDefinition) defns.get((Object) outputCurveGroupName))
					.filtered(valuationDate, refData);
ImmutableList columns = ImmutableList.of((Object) Column.of((Measure) Measures.PAR_RATE));
Stream<CurveNode> tradeMap= curveGroupDefinition.getCurveDefinitions().stream()
			.flatMap(defn -> defn.getNodes().stream())			
			.filter(node -> !(node instanceof IborFixingDepositCurveNode));
			
List trades = (List) tradeMap
					.map(node -> node.trade(1.0, marketData, refData)).collect(Guavate.toImmutableList());
MarketDataConfig marketDataConfig = MarketDataConfig.builder()
					.add((TypedString) outputCurveGroupName, (Object) curveGroupDefinition).build();
CalculationFunctions functions = StandardComponents.calculationFunctions();
RatesMarketDataLookup ratesLookup = RatesMarketDataLookup.of((CurveGroupDefinition) curveGroupDefinition);
CalculationRules rules = CalculationRules.of((CalculationFunctions) functions,
					(CalculationParameter[]) new CalculationParameter[] { ratesLookup });
MarketDataRequirements reqs = MarketDataRequirements.of((CalculationRules) rules, (List) trades,
					(List) columns, (ReferenceData) refData);
BuiltMarketData calibratedMarketData = StandardComponents.marketDataFactory().create(reqs, marketDataConfig,
					marketData, refData);
CurveId discCurveId = CurveId.of((String) outputCurveGroupName.toString(), (String) dscIdStr);

RatesMarketDataLookup lookup = RatesMarketDataLookup.of(
					(Map) ImmutableMap.of((Object) curr, (Object) discCurveId),
					(Map) ImmutableMap.of((Object) iborIndices, (Object) discCurveId));
RatesProvider provider = lookup.ratesProvider((MarketData) calibratedMarketData);

			
DiscountIborIndexRates rates = (DiscountIborIndexRates) provider.iborIndexRates(iborIndices);
ZeroRateDiscountFactors df1 = (ZeroRateDiscountFactors) rates.getDiscountFactors();
InterpolatedNodalCurve discount = (InterpolatedNodalCurve) df1.getCurve();
CurveMetadata META_ZERO_PERIODIC = DefaultCurveMetadata.builder()
				.curveName(discount.getName())
				.xValueType(ValueType.YEAR_FRACTION)
				.yValueType(ValueType.ZERO_RATE)
				.dayCount(DayCounts.ACT_365F)
				.addInfo(CurveInfoType.COMPOUNDING_PER_YEAR, 1)
				.build();
InterpolatedNodalCurve discount1=discount.of(META_ZERO_PERIODIC, discount.getXValues(), discount.getYValues(), discount.getInterpolator());
ZeroRatePeriodicDiscountFactors zPDf=ZeroRatePeriodicDiscountFactors.of(Currency.of("AED"), valuationDate, discount1);

Here zPDf.yValues() is same as df1 .yValues()

Regards
Surima

#2

Hi All,

Any insight on how this can be achieved?Let me know if further information is required.Appreciate your help on this topic.

Regards
Surima

#3

I assume you are using something other than Java to code in, but I’ve tried to understand the code above as best I can.

The reason why zPDf.yValues() is same as df1 .yValues() is because the code that creates zPDf doesn’t actually do anything. It literally just copies the x-values and y-values from one immutable bean to the other. While the metadata is different, that will have no effect at that point.

What I think you need to do is to setup the metadata with periodic compounding (CurveInfoType.COMPOUNDING_PER_YEAR) before calibrating the curve. ie. the input to StandardComponents.marketDataFactory().create(...) needs to have the altered curve metadata.

Hope that helps
Stephen