/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.curve;
import org.threeten.bp.Period;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.instrument.InstrumentDefinition;
import com.opengamma.analytics.financial.instrument.index.IndexPrice;
import com.opengamma.analytics.financial.instrument.inflation.CouponInflationZeroCouponInterpolationDefinition;
import com.opengamma.analytics.financial.instrument.inflation.CouponInflationZeroCouponMonthlyDefinition;
import com.opengamma.analytics.financial.instrument.payment.CouponFixedCompoundingDefinition;
import com.opengamma.analytics.financial.instrument.swap.SwapFixedInflationZeroCouponDefinition;
import com.opengamma.analytics.financial.schedule.ScheduleCalculator;
import com.opengamma.core.convention.ConventionSource;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeries;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.link.ConventionLink;
import com.opengamma.core.link.SecurityLink;
import com.opengamma.core.marketdatasnapshot.SnapshotDataBundle;
import com.opengamma.core.region.RegionSource;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.financial.analytics.conversion.CalendarUtils;
import com.opengamma.financial.analytics.ircurve.strips.ZeroCouponInflationNode;
import com.opengamma.financial.analytics.timeseries.HistoricalTimeSeriesBundle;
import com.opengamma.financial.convention.InflationLegConvention;
import com.opengamma.financial.convention.PriceIndexConvention;
import com.opengamma.financial.convention.SwapFixedLegConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.security.index.PriceIndex;
import com.opengamma.id.ExternalId;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
/**
*
*/
public class ZeroCouponInflationNodeConverter extends CurveNodeVisitorAdapter<InstrumentDefinition<?>> {
/** The holiday source */
private final HolidaySource _holidaySource;
/** The region source */
private final RegionSource _regionSource;
/** The market data */
private final SnapshotDataBundle _marketData;
/** The data id */
private final ExternalId _dataId;
/** The valuation time */
private final ZonedDateTime _valuationTime;
/** The time series bundle */
private final HistoricalTimeSeriesBundle _timeSeries;
/**
* @param holidaySource The holiday source, not null
* @param regionSource The region source, not null
* @param marketData The market data, not null
* @param dataId The data id, not null
* @param valuationTime The valuation time, not null
* @param timeSeries The time series, not null
*/
public ZeroCouponInflationNodeConverter(HolidaySource holidaySource,
RegionSource regionSource,
SnapshotDataBundle marketData,
ExternalId dataId,
ZonedDateTime valuationTime,
HistoricalTimeSeriesBundle timeSeries) {
_holidaySource = ArgumentChecker.notNull(holidaySource, "holidaySource");
_regionSource = ArgumentChecker.notNull(regionSource, "regionSource");
_marketData = ArgumentChecker.notNull(marketData, "marketData");
_dataId = ArgumentChecker.notNull(dataId, "dataId");
_valuationTime = ArgumentChecker.notNull(valuationTime, "valuationTime");
_timeSeries = ArgumentChecker.notNull(timeSeries, "timeSeries");
}
/**
* @param securitySource The security source. Not required.
* @param conventionSource The convention source, not required
* @param holidaySource The holiday source, not null
* @param regionSource The region source, not null
* @param marketData The market data, not null
* @param dataId The data id, not null
* @param valuationTime The valuation time, not null
* @param timeSeries The time series, not null
* @deprecated use constructor without securitySource and conventionSource
*/
@Deprecated
public ZeroCouponInflationNodeConverter(
SecuritySource securitySource, ConventionSource conventionSource, HolidaySource holidaySource,
RegionSource regionSource, SnapshotDataBundle marketData,
ExternalId dataId, ZonedDateTime valuationTime, HistoricalTimeSeriesBundle timeSeries) {
this(holidaySource, regionSource, marketData, dataId, valuationTime, timeSeries);
}
@Override
public InstrumentDefinition<?> visitZeroCouponInflationNode(ZeroCouponInflationNode inflationNode) {
Double rate = _marketData.getDataPoint(_dataId);
if (rate == null) {
throw new OpenGammaRuntimeException("Could not get market data for " + _dataId);
}
SwapFixedLegConvention fixedLegConvention =
ConventionLink.resolvable(inflationNode.getFixedLegConvention(), SwapFixedLegConvention.class).resolve();
InflationLegConvention inflationLegConvention =
ConventionLink.resolvable(inflationNode.getInflationLegConvention(), InflationLegConvention.class).resolve();
PriceIndex indexSecurity =
SecurityLink.resolvable(inflationLegConvention.getPriceIndexConvention(), PriceIndex.class).resolve();
PriceIndexConvention priceIndexConvention =
ConventionLink.resolvable(indexSecurity.getConventionId(), PriceIndexConvention.class).resolve();
int settlementDays = fixedLegConvention.getSettlementDays();
Period tenor = inflationNode.getTenor().getPeriod();
double notional = 1;
//TODO business day convention and currency are in both conventions - should we enforce that they're the same or use
// different ones for each leg?
BusinessDayConvention businessDayConvention = fixedLegConvention.getBusinessDayConvention();
boolean endOfMonth = fixedLegConvention.isIsEOM();
Currency currency = priceIndexConvention.getCurrency();
Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, priceIndexConvention.getRegion());
ZoneId zone = _valuationTime.getZone(); //TODO time zone set to midnight UTC
ZonedDateTime settlementDate =
ScheduleCalculator.getAdjustedDate(_valuationTime, settlementDays, calendar).toLocalDate().atStartOfDay(zone);
ZonedDateTime paymentDate =
ScheduleCalculator.getAdjustedDate(settlementDate, tenor, businessDayConvention, calendar, endOfMonth)
.toLocalDate().atStartOfDay(zone);
CouponFixedCompoundingDefinition fixedCoupon =
CouponFixedCompoundingDefinition.from(currency, settlementDate, paymentDate, notional, tenor.getYears(), rate);
HistoricalTimeSeries ts =
_timeSeries.get(MarketDataRequirementNames.MARKET_VALUE, priceIndexConvention.getPriceIndexId());
if (ts == null) {
throw new OpenGammaRuntimeException(
"Could not get price index time series with id " + priceIndexConvention.getPriceIndexId());
}
int conventionalMonthLag = inflationLegConvention.getMonthLag();
int monthLag = inflationLegConvention.getMonthLag();
final IndexPrice indexPrice = new IndexPrice(indexSecurity.getName(), currency);
switch (inflationNode.getInflationNodeType()) {
case INTERPOLATED: {
CouponInflationZeroCouponInterpolationDefinition inflationCoupon =
CouponInflationZeroCouponInterpolationDefinition.from(
settlementDate, paymentDate, -notional, indexPrice, conventionalMonthLag, monthLag, false);
return new SwapFixedInflationZeroCouponDefinition(fixedCoupon, inflationCoupon, calendar);
}
case MONTHLY: {
CouponInflationZeroCouponMonthlyDefinition inflationCoupon =
CouponInflationZeroCouponMonthlyDefinition.from(
settlementDate, paymentDate, -notional, indexPrice, conventionalMonthLag, monthLag, false);
return new SwapFixedInflationZeroCouponDefinition(fixedCoupon, inflationCoupon, calendar);
}
default:
throw new OpenGammaRuntimeException(
"Could not handle inflation nodes of type " + inflationNode.getInflationNodeType());
}
}
}