/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.credit; import java.io.Serializable; import java.time.LocalDate; import java.time.Period; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.BeanDefinition; import org.joda.beans.ImmutableBean; import org.joda.beans.ImmutableValidator; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.Lists; import com.opengamma.strata.basics.date.Tenor; import com.opengamma.strata.market.curve.CurveMetadata; import com.opengamma.strata.market.curve.CurveName; import com.opengamma.strata.market.curve.DefaultCurveMetadata; import com.opengamma.strata.market.param.ParameterMetadata; import com.opengamma.strata.market.param.TenorDateParameterMetadata; import com.opengamma.strata.product.credit.type.IsdaYieldCurveConvention; /** * The par rates used when calibrating an ISDA yield curve. */ @BeanDefinition(builderScope = "private") public final class IsdaYieldCurveInputs implements ImmutableBean, Serializable { // TODO replace arrays with lists /** * The curve name. */ @PropertyDefinition(validate = "notNull") private final CurveName name; /** * The tenor at each curve node. */ @PropertyDefinition(validate = "notNull") private final Period[] yieldCurvePoints; /** * The end date at each curve node. */ @PropertyDefinition(validate = "notNull") private final LocalDate[] endDatePoints; /** * The instrument type at each curve node. */ @PropertyDefinition(validate = "notNull") private final IsdaYieldCurveUnderlyingType[] yieldCurveInstruments; /** * The par rate at each curve node. */ @PropertyDefinition(validate = "notNull") private final double[] parRates; /** * The underlying convention. */ @PropertyDefinition(validate = "notNull") private final IsdaYieldCurveConvention curveConvention; //------------------------------------------------------------------------- /** * Provides curve meta data to capture tenor and anchor point date information. * * @return the curve metadata */ public CurveMetadata getCurveMetaData() { List<ParameterMetadata> parameters = Lists.newArrayList(); for (int i = 0; i < yieldCurvePoints.length; i++) { TenorDateParameterMetadata pointData = TenorDateParameterMetadata.of(endDatePoints[i], Tenor.of(yieldCurvePoints[i])); parameters.add(pointData); } return DefaultCurveMetadata.builder() .curveName(name) .parameterMetadata(parameters) .build(); } /** * Creates an instance of the par rates. * * @param name the curve name * @param yieldCurvePoints the tenor at each curve node * @param endDatePoints the end dates * @param yieldCurveInstruments the instrument type at each curve node * @param parRates the par rate at each curve node * @param curveConvention the underlying convention * @return the par rates */ public static IsdaYieldCurveInputs of( CurveName name, Period[] yieldCurvePoints, LocalDate[] endDatePoints, IsdaYieldCurveUnderlyingType[] yieldCurveInstruments, double[] parRates, IsdaYieldCurveConvention curveConvention) { return new IsdaYieldCurveInputs( name, yieldCurvePoints, endDatePoints, yieldCurveInstruments, parRates, curveConvention); } @ImmutableValidator private void validate() { if (yieldCurvePoints.length <= 0) { throw new IllegalArgumentException("Cannot have zero points"); } if (yieldCurvePoints.length != yieldCurveInstruments.length || yieldCurvePoints.length != parRates.length) { throw new IllegalArgumentException("Points do not line up"); } } //------------------------------------------------------------------------- /** * Applies a parallel shift to all the nodes. * * @param shift the shift to apply * @return the bumped instance */ public IsdaYieldCurveInputs parallelShiftParRatesinBps(double shift) { double[] shiftedRates = parRates.clone(); for (int i = 0; i < shiftedRates.length; i++) { shiftedRates[i] = shiftedRates[i] + shift; } return applyShift(shiftedRates); } /** * Applies a bucketed shift to a single node. * * @param index the index of the node to shift * @param shift the shift to apply * @return the bumped instance */ public IsdaYieldCurveInputs bucketedShiftParRatesinBps(int index, double shift) { double[] shiftedRates = parRates.clone(); shiftedRates[index] = shiftedRates[index] + shift; return applyShift(shiftedRates); } /** * Gets the number of nodes. * * @return the number of points */ public int getNumberOfPoints() { return yieldCurvePoints.length; } // applies the shift private IsdaYieldCurveInputs applyShift(double[] shiftedRates) { return IsdaYieldCurveInputs.of( name, yieldCurvePoints.clone(), endDatePoints.clone(), yieldCurveInstruments.clone(), shiftedRates, curveConvention); } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code IsdaYieldCurveInputs}. * @return the meta-bean, not null */ public static IsdaYieldCurveInputs.Meta meta() { return IsdaYieldCurveInputs.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(IsdaYieldCurveInputs.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private IsdaYieldCurveInputs( CurveName name, Period[] yieldCurvePoints, LocalDate[] endDatePoints, IsdaYieldCurveUnderlyingType[] yieldCurveInstruments, double[] parRates, IsdaYieldCurveConvention curveConvention) { JodaBeanUtils.notNull(name, "name"); JodaBeanUtils.notNull(yieldCurvePoints, "yieldCurvePoints"); JodaBeanUtils.notNull(endDatePoints, "endDatePoints"); JodaBeanUtils.notNull(yieldCurveInstruments, "yieldCurveInstruments"); JodaBeanUtils.notNull(parRates, "parRates"); JodaBeanUtils.notNull(curveConvention, "curveConvention"); this.name = name; this.yieldCurvePoints = yieldCurvePoints; this.endDatePoints = endDatePoints; this.yieldCurveInstruments = yieldCurveInstruments; this.parRates = parRates.clone(); this.curveConvention = curveConvention; validate(); } @Override public IsdaYieldCurveInputs.Meta metaBean() { return IsdaYieldCurveInputs.Meta.INSTANCE; } @Override public <R> Property<R> property(String propertyName) { return metaBean().<R>metaProperty(propertyName).createProperty(this); } @Override public Set<String> propertyNames() { return metaBean().metaPropertyMap().keySet(); } //----------------------------------------------------------------------- /** * Gets the curve name. * @return the value of the property, not null */ public CurveName getName() { return name; } //----------------------------------------------------------------------- /** * Gets the tenor at each curve node. * @return the value of the property, not null */ public Period[] getYieldCurvePoints() { return yieldCurvePoints; } //----------------------------------------------------------------------- /** * Gets the end date at each curve node. * @return the value of the property, not null */ public LocalDate[] getEndDatePoints() { return endDatePoints; } //----------------------------------------------------------------------- /** * Gets the instrument type at each curve node. * @return the value of the property, not null */ public IsdaYieldCurveUnderlyingType[] getYieldCurveInstruments() { return yieldCurveInstruments; } //----------------------------------------------------------------------- /** * Gets the par rate at each curve node. * @return the value of the property, not null */ public double[] getParRates() { return parRates.clone(); } //----------------------------------------------------------------------- /** * Gets the underlying convention. * @return the value of the property, not null */ public IsdaYieldCurveConvention getCurveConvention() { return curveConvention; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { IsdaYieldCurveInputs other = (IsdaYieldCurveInputs) obj; return JodaBeanUtils.equal(name, other.name) && JodaBeanUtils.equal(yieldCurvePoints, other.yieldCurvePoints) && JodaBeanUtils.equal(endDatePoints, other.endDatePoints) && JodaBeanUtils.equal(yieldCurveInstruments, other.yieldCurveInstruments) && JodaBeanUtils.equal(parRates, other.parRates) && JodaBeanUtils.equal(curveConvention, other.curveConvention); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(name); hash = hash * 31 + JodaBeanUtils.hashCode(yieldCurvePoints); hash = hash * 31 + JodaBeanUtils.hashCode(endDatePoints); hash = hash * 31 + JodaBeanUtils.hashCode(yieldCurveInstruments); hash = hash * 31 + JodaBeanUtils.hashCode(parRates); hash = hash * 31 + JodaBeanUtils.hashCode(curveConvention); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("IsdaYieldCurveInputs{"); buf.append("name").append('=').append(name).append(',').append(' '); buf.append("yieldCurvePoints").append('=').append(yieldCurvePoints).append(',').append(' '); buf.append("endDatePoints").append('=').append(endDatePoints).append(',').append(' '); buf.append("yieldCurveInstruments").append('=').append(yieldCurveInstruments).append(',').append(' '); buf.append("parRates").append('=').append(parRates).append(',').append(' '); buf.append("curveConvention").append('=').append(JodaBeanUtils.toString(curveConvention)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code IsdaYieldCurveInputs}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty<CurveName> name = DirectMetaProperty.ofImmutable( this, "name", IsdaYieldCurveInputs.class, CurveName.class); /** * The meta-property for the {@code yieldCurvePoints} property. */ private final MetaProperty<Period[]> yieldCurvePoints = DirectMetaProperty.ofImmutable( this, "yieldCurvePoints", IsdaYieldCurveInputs.class, Period[].class); /** * The meta-property for the {@code endDatePoints} property. */ private final MetaProperty<LocalDate[]> endDatePoints = DirectMetaProperty.ofImmutable( this, "endDatePoints", IsdaYieldCurveInputs.class, LocalDate[].class); /** * The meta-property for the {@code yieldCurveInstruments} property. */ private final MetaProperty<IsdaYieldCurveUnderlyingType[]> yieldCurveInstruments = DirectMetaProperty.ofImmutable( this, "yieldCurveInstruments", IsdaYieldCurveInputs.class, IsdaYieldCurveUnderlyingType[].class); /** * The meta-property for the {@code parRates} property. */ private final MetaProperty<double[]> parRates = DirectMetaProperty.ofImmutable( this, "parRates", IsdaYieldCurveInputs.class, double[].class); /** * The meta-property for the {@code curveConvention} property. */ private final MetaProperty<IsdaYieldCurveConvention> curveConvention = DirectMetaProperty.ofImmutable( this, "curveConvention", IsdaYieldCurveInputs.class, IsdaYieldCurveConvention.class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name", "yieldCurvePoints", "endDatePoints", "yieldCurveInstruments", "parRates", "curveConvention"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return name; case 695376101: // yieldCurvePoints return yieldCurvePoints; case 578522476: // endDatePoints return endDatePoints; case -1469575510: // yieldCurveInstruments return yieldCurveInstruments; case 1157229426: // parRates return parRates; case 1796217280: // curveConvention return curveConvention; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends IsdaYieldCurveInputs> builder() { return new IsdaYieldCurveInputs.Builder(); } @Override public Class<? extends IsdaYieldCurveInputs> beanType() { return IsdaYieldCurveInputs.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty<CurveName> name() { return name; } /** * The meta-property for the {@code yieldCurvePoints} property. * @return the meta-property, not null */ public MetaProperty<Period[]> yieldCurvePoints() { return yieldCurvePoints; } /** * The meta-property for the {@code endDatePoints} property. * @return the meta-property, not null */ public MetaProperty<LocalDate[]> endDatePoints() { return endDatePoints; } /** * The meta-property for the {@code yieldCurveInstruments} property. * @return the meta-property, not null */ public MetaProperty<IsdaYieldCurveUnderlyingType[]> yieldCurveInstruments() { return yieldCurveInstruments; } /** * The meta-property for the {@code parRates} property. * @return the meta-property, not null */ public MetaProperty<double[]> parRates() { return parRates; } /** * The meta-property for the {@code curveConvention} property. * @return the meta-property, not null */ public MetaProperty<IsdaYieldCurveConvention> curveConvention() { return curveConvention; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((IsdaYieldCurveInputs) bean).getName(); case 695376101: // yieldCurvePoints return ((IsdaYieldCurveInputs) bean).getYieldCurvePoints(); case 578522476: // endDatePoints return ((IsdaYieldCurveInputs) bean).getEndDatePoints(); case -1469575510: // yieldCurveInstruments return ((IsdaYieldCurveInputs) bean).getYieldCurveInstruments(); case 1157229426: // parRates return ((IsdaYieldCurveInputs) bean).getParRates(); case 1796217280: // curveConvention return ((IsdaYieldCurveInputs) bean).getCurveConvention(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code IsdaYieldCurveInputs}. */ private static final class Builder extends DirectFieldsBeanBuilder<IsdaYieldCurveInputs> { private CurveName name; private Period[] yieldCurvePoints; private LocalDate[] endDatePoints; private IsdaYieldCurveUnderlyingType[] yieldCurveInstruments; private double[] parRates; private IsdaYieldCurveConvention curveConvention; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return name; case 695376101: // yieldCurvePoints return yieldCurvePoints; case 578522476: // endDatePoints return endDatePoints; case -1469575510: // yieldCurveInstruments return yieldCurveInstruments; case 1157229426: // parRates return parRates; case 1796217280: // curveConvention return curveConvention; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (CurveName) newValue; break; case 695376101: // yieldCurvePoints this.yieldCurvePoints = (Period[]) newValue; break; case 578522476: // endDatePoints this.endDatePoints = (LocalDate[]) newValue; break; case -1469575510: // yieldCurveInstruments this.yieldCurveInstruments = (IsdaYieldCurveUnderlyingType[]) newValue; break; case 1157229426: // parRates this.parRates = (double[]) newValue; break; case 1796217280: // curveConvention this.curveConvention = (IsdaYieldCurveConvention) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty<?> property, Object value) { super.set(property, value); return this; } @Override public Builder setString(String propertyName, String value) { setString(meta().metaProperty(propertyName), value); return this; } @Override public Builder setString(MetaProperty<?> property, String value) { super.setString(property, value); return this; } @Override public Builder setAll(Map<String, ? extends Object> propertyValueMap) { super.setAll(propertyValueMap); return this; } @Override public IsdaYieldCurveInputs build() { return new IsdaYieldCurveInputs( name, yieldCurvePoints, endDatePoints, yieldCurveInstruments, parRates, curveConvention); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("IsdaYieldCurveInputs.Builder{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)).append(',').append(' '); buf.append("yieldCurvePoints").append('=').append(JodaBeanUtils.toString(yieldCurvePoints)).append(',').append(' '); buf.append("endDatePoints").append('=').append(JodaBeanUtils.toString(endDatePoints)).append(',').append(' '); buf.append("yieldCurveInstruments").append('=').append(JodaBeanUtils.toString(yieldCurveInstruments)).append(',').append(' '); buf.append("parRates").append('=').append(JodaBeanUtils.toString(parRates)).append(',').append(' '); buf.append("curveConvention").append('=').append(JodaBeanUtils.toString(curveConvention)); buf.append('}'); return buf.toString(); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }