/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.security.irs; import java.util.Collections; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.BeanDefinition; 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.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.threeten.bp.LocalDate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.opengamma.financial.security.swap.InterestRateNotional; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; /** * Notional that can handle a schedule. Currency must be constant throughout. * Expects to be handed a list of dates and the notional (absolute or delta) taking effect in that period. * Can be passed a single amount for a constant notional. * Dates provided may be business day adjusted during analytics calculations. */ @BeanDefinition public final class InterestRateSwapNotional extends InterestRateNotional { /** Serialization version. */ private static final long serialVersionUID = 1L; /** * The dates for which custom notionals take effect. */ @PropertyDefinition private List<LocalDate> _dates; /** * The custom notionals. Possible this should be delta's on top of first notional. */ @PropertyDefinition private List<Double> _notionals; /** * Controls if the custom notionals are delta on the original or absolute values. */ @PropertyDefinition private List<Rate.ShiftType> _shiftTypes; //@Override public <T> T accept(InterestRateSwapNotionalVisitor<LocalDate, T> visitor, LocalDate period) { return visitor.visitInterestRateSwapNotional(this, period); } //@Override public <T> T accept(InterestRateSwapNotionalVisitor<Object , T> visitor) { return visitor.visitInterestRateSwapNotional(this); } /** * Return the notional amount. * * @deprecated getInitialAmount() should be used in preference to this. * @return the initial notional. */ @Deprecated @Override public double getAmount() { return getInitialAmount(); } /** * Return the initial notional amount. * * @return the initial notional. */ public double getInitialAmount() { return super.getAmount(); } /** * Get the notional as of a given date * * @param date the (business day adjusted) date you want the notional for. * @return the notional */ public double getAmount(final LocalDate date) { if (getDates().size() == 0 || date.isBefore(getDates().get(0))) { // constant notional or before schedule begins return super.getAmount(); } final int index = Collections.binarySearch(_dates, date); if (index >= 0) { if (_shiftTypes.get(index) == Rate.ShiftType.OUTRIGHT) { return _notionals.get(index); // short circuit if we don't need to adjust from previous } // Recurse back until it hits an outright amount (the initial notional is outright) final int previousIndex = index - 1; double previousValue; if (previousIndex < 0) { previousValue = getInitialAmount(); } else { previousValue = getAmount(getDates().get(previousIndex)); } return _shiftTypes.get(index).getRate(previousValue, getNotionals().get(index)); } // if value not explicitly set for this date, take from last notional before this date. return getAmount(getDates().get(-(index + 2))); } /** * Create a variable notional schedule. * * @param ccy the currency * @param dates the dates the provided values take effect (unadjusted for business days) * @param notionals the notional values (or shifts to the previous notional) that take effect * @param types the shift types for each step in the schedule * @return the notional schedule */ public static InterestRateSwapNotional of(Currency ccy, final List<LocalDate> dates, final List<Double> notionals, List<Rate.ShiftType> types) { ArgumentChecker.noNulls(dates, "dates"); ArgumentChecker.noNulls(notionals, "notionals"); ArgumentChecker.noNulls(types, "types"); ArgumentChecker.isTrue(dates.size() == notionals.size(), "Different numbers of overrides & notionals"); ArgumentChecker.isTrue(dates.size() == types.size(), "Different numbers of overrides & notionals"); ArgumentChecker.isTrue(notionals.size() > 0, "Require at least one notional"); if (notionals.size() == 1) { // constant notional return new InterestRateSwapNotional(ccy, notionals.get(0)); } ArgumentChecker.isTrue(types.get(0) == Rate.ShiftType.OUTRIGHT, "First notional in schedule must be an OUTRIGHT quote"); return new InterestRateSwapNotional(ccy, dates, notionals, types); } /** * Create a variable notional schedule. * * @param ccy the currency * @param dates the dates the provided values take effect (unadjusted for business days) * @param notionals the notional values that take effect * @return the notional schedule */ public static InterestRateSwapNotional of(Currency ccy, final List<LocalDate> dates, final List<Double> notionals) { List<Rate.ShiftType> types = Lists.newArrayListWithExpectedSize(notionals.size()); for (int i = 0; i < dates.size(); i++) { types.add(Rate.ShiftType.OUTRIGHT); } return of(ccy, dates, notionals, types); } /** * Create a constant notional * * @param ccy the currency * @param notional the notional value * @return the constant notional */ public static InterestRateSwapNotional of(Currency ccy, final double notional) { return new InterestRateSwapNotional(ccy, notional); } private InterestRateSwapNotional(Currency ccy, List<LocalDate> overridePeriods, List<Double> notionals, List<Rate.ShiftType> types) { super(ccy, ArgumentChecker.notEmpty(notionals, "notionals").iterator().next()); ArgumentChecker.isTrue(overridePeriods.size() == notionals.size(), "Different overrides & notionals"); ArgumentChecker.isTrue(overridePeriods.size() == types.size(), "Different overrides & adjustment types"); _dates = ImmutableList.copyOf(overridePeriods); _notionals = ImmutableList.copyOf(notionals); _shiftTypes = ImmutableList.copyOf(types); } /** * Create a constant notional * * @param ccy the currency * @param notional the notional value */ public InterestRateSwapNotional(final Currency ccy, final double notional) { super(ccy, notional); _dates = Collections.emptyList(); _notionals = Collections.emptyList(); _shiftTypes = Collections.emptyList(); } protected InterestRateSwapNotional() { } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code InterestRateSwapNotional}. * @return the meta-bean, not null */ public static InterestRateSwapNotional.Meta meta() { return InterestRateSwapNotional.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(InterestRateSwapNotional.Meta.INSTANCE); } @Override public InterestRateSwapNotional.Meta metaBean() { return InterestRateSwapNotional.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the dates for which custom notionals take effect. * @return the value of the property */ public List<LocalDate> getDates() { return _dates; } /** * Sets the dates for which custom notionals take effect. * @param dates the new value of the property */ public void setDates(List<LocalDate> dates) { this._dates = dates; } /** * Gets the the {@code dates} property. * @return the property, not null */ public Property<List<LocalDate>> dates() { return metaBean().dates().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the custom notionals. Possible this should be delta's on top of first notional. * @return the value of the property */ public List<Double> getNotionals() { return _notionals; } /** * Sets the custom notionals. Possible this should be delta's on top of first notional. * @param notionals the new value of the property */ public void setNotionals(List<Double> notionals) { this._notionals = notionals; } /** * Gets the the {@code notionals} property. * @return the property, not null */ public Property<List<Double>> notionals() { return metaBean().notionals().createProperty(this); } //----------------------------------------------------------------------- /** * Gets controls if the custom notionals are delta on the original or absolute values. * @return the value of the property */ public List<Rate.ShiftType> getShiftTypes() { return _shiftTypes; } /** * Sets controls if the custom notionals are delta on the original or absolute values. * @param shiftTypes the new value of the property */ public void setShiftTypes(List<Rate.ShiftType> shiftTypes) { this._shiftTypes = shiftTypes; } /** * Gets the the {@code shiftTypes} property. * @return the property, not null */ public Property<List<Rate.ShiftType>> shiftTypes() { return metaBean().shiftTypes().createProperty(this); } //----------------------------------------------------------------------- @Override public InterestRateSwapNotional clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { InterestRateSwapNotional other = (InterestRateSwapNotional) obj; return JodaBeanUtils.equal(getDates(), other.getDates()) && JodaBeanUtils.equal(getNotionals(), other.getNotionals()) && JodaBeanUtils.equal(getShiftTypes(), other.getShiftTypes()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getDates()); hash = hash * 31 + JodaBeanUtils.hashCode(getNotionals()); hash = hash * 31 + JodaBeanUtils.hashCode(getShiftTypes()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("InterestRateSwapNotional{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("dates").append('=').append(JodaBeanUtils.toString(getDates())).append(',').append(' '); buf.append("notionals").append('=').append(JodaBeanUtils.toString(getNotionals())).append(',').append(' '); buf.append("shiftTypes").append('=').append(JodaBeanUtils.toString(getShiftTypes())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code InterestRateSwapNotional}. */ public static final class Meta extends InterestRateNotional.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code dates} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<List<LocalDate>> _dates = DirectMetaProperty.ofReadWrite( this, "dates", InterestRateSwapNotional.class, (Class) List.class); /** * The meta-property for the {@code notionals} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<List<Double>> _notionals = DirectMetaProperty.ofReadWrite( this, "notionals", InterestRateSwapNotional.class, (Class) List.class); /** * The meta-property for the {@code shiftTypes} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<List<Rate.ShiftType>> _shiftTypes = DirectMetaProperty.ofReadWrite( this, "shiftTypes", InterestRateSwapNotional.class, (Class) List.class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> _metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "dates", "notionals", "shiftTypes"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 95356549: // dates return _dates; case 1910080819: // notionals return _notionals; case 1923906839: // shiftTypes return _shiftTypes; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends InterestRateSwapNotional> builder() { return new DirectBeanBuilder<InterestRateSwapNotional>(new InterestRateSwapNotional()); } @Override public Class<? extends InterestRateSwapNotional> beanType() { return InterestRateSwapNotional.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return _metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code dates} property. * @return the meta-property, not null */ public MetaProperty<List<LocalDate>> dates() { return _dates; } /** * The meta-property for the {@code notionals} property. * @return the meta-property, not null */ public MetaProperty<List<Double>> notionals() { return _notionals; } /** * The meta-property for the {@code shiftTypes} property. * @return the meta-property, not null */ public MetaProperty<List<Rate.ShiftType>> shiftTypes() { return _shiftTypes; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 95356549: // dates return ((InterestRateSwapNotional) bean).getDates(); case 1910080819: // notionals return ((InterestRateSwapNotional) bean).getNotionals(); case 1923906839: // shiftTypes return ((InterestRateSwapNotional) bean).getShiftTypes(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 95356549: // dates ((InterestRateSwapNotional) bean).setDates((List<LocalDate>) newValue); return; case 1910080819: // notionals ((InterestRateSwapNotional) bean).setNotionals((List<Double>) newValue); return; case 1923906839: // shiftTypes ((InterestRateSwapNotional) bean).setShiftTypes((List<Rate.ShiftType>) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }