Applying compounding frequency for calibrating curves

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

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

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

Hi Stephen,

I haven’t been successful at creating ZeroRatePeriodicDiscountFactors before calling curve calibration.
Would appreciate if you could point me to a code snippet that can generate Periodic discount factors and its placement in below code.Thanking in advance.

        ImmutableMap defns = RatesCalibrationCsvLoader.load((ResourceLocator) groupsResource,
					(ResourceLocator) settingsResource, (ResourceLocator[]) new ResourceLocator[] { nodesResource });
			CurveGroupDefinition curveGroupDefinition = ((CurveGroupDefinition) defns.get((Object) outputCurveGroupName))
					.filtered(valuationDate, refData);
			
			List<ParameterMetadata> PARAM_METADATA_BASE = new ArrayList<ParameterMetadata>();	
			
			curveGroupDefinition.getCurveDefinitions().get(0).getNodes().stream()
					.forEach(s -> PARAM_METADATA_BASE.add(LabelDateParameterMetadata
							.of(LocalDate.of(s.date(valuationDate, refData).getYear(), s.date(valuationDate, refData).getMonth(), s.date(valuationDate, refData).getDayOfMonth()), s.getLabel())));

			
			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);
			logger.error(curr+"---");
			RatesMarketDataLookup lookup = RatesMarketDataLookup.of(
					(Map) ImmutableMap.of((Object) curr, (Object) discCurveId),
					(Map) ImmutableMap.of((Object) iborIndices, (Object) discCurveId));
			RatesProvider provider = lookup.ratesProvider((MarketData) calibratedMarketData);

Regards
Surima

Try adding something like this, editing your curve once calibration has completed:

CurveId curveId = CurveId.of("curveGroupName", "curveName");
Curve curve = calibratedMarketData.findValue(curveId).get();
curve = curve.withMetadata(curve.getMetadata().withInfo(CurveInfoType.COMPOUNDING_PER_YEAR, 4));
calibratedMarketData = calibratedMarketData.withValue(curveId, curve);

Stephen

Hi Stephen,

The results of the curve before and after the addition of compounding frequency are the same.We have applied compounding frequency=1.

			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);
			logger.error(curr+"---");
			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();
			discount = (InterpolatedNodalCurve) df1.getCurve();

			
			Curve curve = calibratedMarketData.findValue(discCurveId).get();
			Curve curve1 = curve.withMetadata(curve.getMetadata().withInfo(CurveInfoType.COMPOUNDING_PER_YEAR, 4));
			BuiltMarketData calibratedMarketData1 = StandardComponents.marketDataFactory().create(reqs, marketDataConfig,
					marketData.withValue(discCurveId, curve1), refData);
			RatesProvider provider1 = lookup.ratesProvider((MarketData) calibratedMarketData1);

			
			DiscountIborIndexRates rates1 = (DiscountIborIndexRates) provider1.iborIndexRates(iborIndices);
			
			ZeroRateDiscountFactors df2 = (ZeroRateDiscountFactors) rates1.getDiscountFactors();

Please guide if any code has been missed out here.

Regards
Surima

Hi Stephen,

Need your valuable insight on the above issue.If required I can share the expected outputs,output generated before and after applying compounding frequency.

Regards
Surima