/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.credit; import java.util.Arrays; import java.util.Map.Entry; import java.util.SortedMap; import org.threeten.bp.Period; import com.google.common.collect.Iterables; import com.opengamma.analytics.financial.credit.isdastandardmodel.ISDACompliantYieldCurve; import com.opengamma.analytics.financial.credit.isdastandardmodel.ISDACompliantYieldCurveBuild; import com.opengamma.analytics.financial.credit.isdastandardmodel.ISDAInstrumentTypes; import com.opengamma.core.holiday.HolidaySource; import com.opengamma.core.region.RegionSource; import com.opengamma.financial.analytics.conversion.CalendarUtils; import com.opengamma.financial.analytics.isda.credit.YieldCurveData; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.financial.convention.calendar.MondayToFridayCalendar; import com.opengamma.id.ExternalId; import com.opengamma.sesame.Environment; import com.opengamma.sesame.credit.curve.YieldCurveDataProviderFn; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.result.Result; import com.opengamma.util.time.Tenor; /** * Default implementation. Builds an ISDA curve for the passed currency using the {@link YieldCurveDataProviderFn} * configured. The returned {@link ISDACompliantYieldCurve} is the yield curve used in ISDA compliant analytic * credit computations. * * This function expects to be able to query a provider which, given a currency, can provide a {@link YieldCurveData} * instance. These are typically sourced from a market data snapshot. */ public class DefaultIsdaCompliantYieldCurveFn implements IsdaCompliantYieldCurveFn { private final YieldCurveDataProviderFn _yieldCurveProvider; private final RegionSource _regionSource; private final HolidaySource _holidaySource; /** * Builds a new instance. * @param yieldCurveProvider a provider which, given a currency, returns a {@link YieldCurveData} instance. * @param regionSource used to source holiday calendar data * @param holidaySource used to source holiday calendar data */ public DefaultIsdaCompliantYieldCurveFn(YieldCurveDataProviderFn yieldCurveProvider, RegionSource regionSource, HolidaySource holidaySource) { _yieldCurveProvider = ArgumentChecker.notNull(yieldCurveProvider, "yieldCurveProvider"); _regionSource = ArgumentChecker.notNull(regionSource, "regionSource"); _holidaySource = ArgumentChecker.notNull(holidaySource, "holidaySource"); } @Override public Result<IsdaYieldCurve> buildIsdaCompliantCurve(Environment env, Currency ccy) { Result<YieldCurveData> yieldCurveData = _yieldCurveProvider.retrieveYieldCurveData(env, ccy); if (!yieldCurveData.isSuccess()) { return Result.failure(yieldCurveData); } ISDACompliantYieldCurve curve = buildCurve(env, yieldCurveData.getValue()); IsdaYieldCurve yieldCurve = IsdaYieldCurve.builder() .calibratedCurve(curve) .curveData(yieldCurveData.getValue()) .build(); return Result.success(yieldCurve); } /** * Simply pulls fields off of the {@link YieldCurveData} object and passes into the analytics object. */ private ISDACompliantYieldCurve buildCurve(Environment env, YieldCurveData yieldCurveData) { SortedMap<Tenor, Double> cashData = yieldCurveData.getCashData(); SortedMap<Tenor, Double> swapData = yieldCurveData.getSwapData(); int curveNodesLength = cashData.size() + swapData.size(); Period[] periods = new Period[curveNodesLength]; double[] rates = new double[curveNodesLength]; ISDAInstrumentTypes[] instrumentTypes = new ISDAInstrumentTypes[curveNodesLength]; int i = 0; Arrays.fill(instrumentTypes, 0, cashData.size(), ISDAInstrumentTypes.MoneyMarket); Arrays.fill(instrumentTypes, cashData.size(), curveNodesLength, ISDAInstrumentTypes.Swap); for (Entry<Tenor, Double> entry : Iterables.concat(cashData.entrySet(), swapData.entrySet())) { Tenor tenor = entry.getKey(); Double dataPoint = entry.getValue(); periods[i] = tenor.getPeriod(); rates[i] = dataPoint; i++; } ExternalId regionId = yieldCurveData.getRegionId(); Calendar calendar; if (regionId != null) { calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, regionId); } else { calendar = new MondayToFridayCalendar("weekend_only"); } ISDACompliantYieldCurveBuild builder = new ISDACompliantYieldCurveBuild( env.getValuationDate(), //can theoretically be after the spot date yieldCurveData.getSpotDate(), instrumentTypes, periods, yieldCurveData.getCashDayCount(), yieldCurveData.getSwapDayCount(), yieldCurveData.getSwapFixedLegInterval().getPeriod(), yieldCurveData.getCurveDayCount(), yieldCurveData.getCurveBusinessDayConvention(), calendar ); return builder.build(rates); } }