com.opengamma.financial.analytics.ircurve.FixedIncomeStrip.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.financial.analytics.ircurve.FixedIncomeStrip.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.financial.analytics.ircurve;

import java.io.Serializable;

import org.apache.commons.lang.ObjectUtils;
import org.fudgemsg.FudgeField;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeSerializer;

import com.opengamma.financial.fudgemsg.FixedIncomeStripFudgeBuilder;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.time.Tenor;

/**
 * A fixed income strip. <b>Note that the futures are assumed to be quarterly.</b>
 */
public class FixedIncomeStrip implements Serializable, Comparable<FixedIncomeStrip> {

    private static final long serialVersionUID = 1L;

    private final StripInstrumentType _instrumentType;
    private final Tenor _curveNodePointTime;
    private final String _conventionName;
    private final int _nthFutureFromTenor;
    private final int _periodsPerYear;
    private final Tenor _payTenor;
    private final Tenor _receiveTenor;
    private final Tenor _resetTenor;
    private final IndexType _payIndexType;
    private final IndexType _receiveIndexType;
    private final IndexType _indexType;
    private final FixedIncomeStrip _strip1;
    private final FixedIncomeStrip _strip2;
    private final OperationType _operation;

    /**
     * Creates a strip for non-future and non-basis swap instruments.
     *
     * @param instrumentType  the instrument type
     * @param curveNodePointTime  the time of the curve node point
     * @param conventionName  the name of the yield curve specification builder configuration
     */
    public FixedIncomeStrip(final StripInstrumentType instrumentType, final Tenor curveNodePointTime,
            final String conventionName) {
        ArgumentChecker.notNull(instrumentType, "InstrumentType");
        ArgumentChecker.isTrue(instrumentType != StripInstrumentType.FUTURE,
                "Cannot handle futures in this constructor");
        ArgumentChecker.isTrue(instrumentType != StripInstrumentType.PERIODIC_ZERO_DEPOSIT,
                "Cannot handle periodic zero deposits in this constructor");
        ArgumentChecker.isTrue(instrumentType != StripInstrumentType.BASIS_SWAP,
                "Cannot handle basis swaps in this constructor");
        ArgumentChecker.notNull(curveNodePointTime, "Tenor");
        ArgumentChecker.notNull(conventionName, "ConventionName");
        _instrumentType = instrumentType;
        _curveNodePointTime = curveNodePointTime;
        _nthFutureFromTenor = 0;
        _periodsPerYear = 0;
        _conventionName = conventionName;
        _payTenor = null;
        _receiveTenor = null;
        _payIndexType = null;
        _receiveIndexType = null;
        _resetTenor = null;
        _indexType = null;
        _strip1 = null;
        _strip2 = null;
        _operation = null;
    }

    /**
     * Creates a future strip.
     *
     * @param instrumentType  the instrument type
     * @param curveNodePointTime  the time of the curve node point
     * @param conventionName  the name of the convention to use to resolve the strip into a security
     * @param nthFutureFromTenor  how many futures to step through from the curveDate + the tenor. 1-based, must be >0.
     *   e.g. 3 (tenor = 1YR) => 3rd quarterly future after curveDate +  1YR.
     */
    public FixedIncomeStrip(final StripInstrumentType instrumentType, final Tenor curveNodePointTime,
            final int nthFutureFromTenor, final String conventionName) {
        ArgumentChecker.isTrue(instrumentType == StripInstrumentType.FUTURE,
                "Strip type for this constructor must be a future");
        ArgumentChecker.notNull(curveNodePointTime, "Tenor");
        ArgumentChecker.isTrue(nthFutureFromTenor > 0, "Number of future must be greater than zero");
        ArgumentChecker.notNull(conventionName, "ConventionName");
        _instrumentType = instrumentType;
        _curveNodePointTime = curveNodePointTime;
        _nthFutureFromTenor = nthFutureFromTenor;
        _conventionName = conventionName;
        _periodsPerYear = 0;
        _payTenor = null;
        _receiveTenor = null;
        _payIndexType = null;
        _receiveIndexType = null;
        _resetTenor = null;
        _indexType = null;
        _strip1 = null;
        _strip2 = null;
        _operation = null;
    }

    /**
     * Creates a zero deposit strip
     * @param instrumentType The instrument type
     * @param curveNodePointTime The time of the curve node point
     * @param periodsPerYear The number of periods per year
     * @param isPeriodicZeroDepositStrip Is this instrument a periodic zero deposit strip
     * @param conventionName The name of the convention to use to resolve the strip into a security
     */
    public FixedIncomeStrip(final StripInstrumentType instrumentType, final Tenor curveNodePointTime,
            final int periodsPerYear, final boolean isPeriodicZeroDepositStrip, final String conventionName) {
        ArgumentChecker.isTrue(instrumentType == StripInstrumentType.PERIODIC_ZERO_DEPOSIT,
                "Strip type for this constructor must be a periodic zero deposit");
        ArgumentChecker.isTrue(isPeriodicZeroDepositStrip,
                "Must have flag indicating periodic zero deposit set to true");
        ArgumentChecker.notNull(curveNodePointTime, "Tenor");
        ArgumentChecker.isTrue(periodsPerYear > 0, "Number of periods per year must be greater than zero");
        ArgumentChecker.notNull(conventionName, "ConventionName");
        _instrumentType = instrumentType;
        _curveNodePointTime = curveNodePointTime;
        _periodsPerYear = periodsPerYear;
        _nthFutureFromTenor = 0;
        _conventionName = conventionName;
        _payTenor = null;
        _receiveTenor = null;
        _payIndexType = null;
        _receiveIndexType = null;
        _resetTenor = null;
        _indexType = null;
        _strip1 = null;
        _strip2 = null;
        _operation = null;
    }

    /**
     * Creates a basis swap strip where the two legs are on the same type of index (e.g. a USD 3M Fed Funds / 6M Libor swap)
     * @param instrumentType The instrument type
     * @param curveNodePointTime The time of the curve node point
     * @param payTenor The pay tenor
     * @param receiveTenor The receive tenor
     * @param payIndexType The pay index type
     * @param receiveIndexType The receive index type
     * @param conventionName The name of the convention to use to resolve the strip into a security
     */
    public FixedIncomeStrip(final StripInstrumentType instrumentType, final Tenor curveNodePointTime,
            final Tenor payTenor, final Tenor receiveTenor, final IndexType payIndexType,
            final IndexType receiveIndexType, final String conventionName) {
        ArgumentChecker.isTrue(instrumentType == StripInstrumentType.BASIS_SWAP,
                "Strip type for this constructor must be a basis swap");
        ArgumentChecker.notNull(curveNodePointTime, "curve node tenor");
        ArgumentChecker.notNull(payTenor, "pay tenor");
        ArgumentChecker.notNull(receiveTenor, "receive tenor");
        ArgumentChecker.notNull(conventionName, "convention name");
        _instrumentType = instrumentType;
        _curveNodePointTime = curveNodePointTime;
        _periodsPerYear = 0;
        _nthFutureFromTenor = 0;
        _conventionName = conventionName;
        _payTenor = payTenor;
        _receiveTenor = receiveTenor;
        _payIndexType = payIndexType;
        _receiveIndexType = receiveIndexType;
        _resetTenor = null;
        _indexType = null;
        _strip1 = null;
        _strip2 = null;
        _operation = null;
    }

    /**
     * Creates a basis swap strip where the two legs are on the same type of index (e.g. a USD 3M Fed Funds / 6M Libor swap)
     * @param instrumentType The instrument type
     * @param curveNodePointTime The time of the curve node point
     * @param resetTenor The reset tenor
     * @param indexType The index type
     * @param conventionName The name of the convention to use to resolve the strip into a security
     */
    public FixedIncomeStrip(final StripInstrumentType instrumentType, final Tenor curveNodePointTime,
            final Tenor resetTenor, final IndexType indexType, final String conventionName) {
        ArgumentChecker.notNull(curveNodePointTime, "curve node tenor");
        ArgumentChecker.notNull(resetTenor, "reset tenor");
        ArgumentChecker.notNull(conventionName, "convention name");
        _instrumentType = instrumentType;
        _curveNodePointTime = curveNodePointTime;
        _periodsPerYear = 0;
        _nthFutureFromTenor = 0;
        _conventionName = conventionName;
        _resetTenor = resetTenor;
        _indexType = indexType;
        _payTenor = null;
        _receiveTenor = null;
        _payIndexType = null;
        _receiveIndexType = null;
        _strip1 = null;
        _strip2 = null;
        _operation = null;
    }

    public FixedIncomeStrip(final FixedIncomeStrip strip1, final FixedIncomeStrip strip2,
            final OperationType operation, final Tenor curveNodePointTime, final String conventionName) {
        ArgumentChecker.notNull(strip1, "strip 1");
        ArgumentChecker.notNull(strip2, "strip 2");
        ArgumentChecker.notNull(operation, "operation");
        ArgumentChecker.notNull(curveNodePointTime, "curve node point time");
        ArgumentChecker.notNull(conventionName, "convention name");
        _strip1 = strip1;
        _strip2 = strip2;
        _operation = operation;
        _curveNodePointTime = curveNodePointTime;
        _conventionName = conventionName;
        _instrumentType = StripInstrumentType.SPREAD;
        _periodsPerYear = 0;
        _nthFutureFromTenor = 0;
        _payTenor = null;
        _receiveTenor = null;
        _payIndexType = null;
        _receiveIndexType = null;
        _resetTenor = null;
        _indexType = null;
    }

    //-------------------------------------------------------------------------
    /**
     * Gets the instrument type used to construct this strip.
     *
     * @return the instrument type, not null
     */
    public StripInstrumentType getInstrumentType() {
        if (_strip1 != null) {
            throw new IllegalStateException("Cannot get strip instrument type for a spread strip " + toString());
        }
        return _instrumentType;
    }

    /**
     * Gets the curve node point in time.
     *
     * @return a tenor representing the time of the curve node point, not null
     */
    public Tenor getCurveNodePointTime() {
        return _curveNodePointTime;
    }

    /**
     * Get the number of the quarterly IR futures after the tenor to choose.
     * NOTE: THIS DOESN'T REFER TO A GENERIC FUTURE
     *
     * @return the number of futures after the tenor
     * @throws IllegalStateException if called on a non-future strip
     */
    public int getNumberOfFuturesAfterTenor() {
        if (_instrumentType != StripInstrumentType.FUTURE) {
            throw new IllegalStateException(
                    "Cannot get number of futures after tenor for a non-future strip " + toString());
        }
        return _nthFutureFromTenor;
    }

    /**
     * Get the periods per year of a periodic zero deposit security
     *
     * @return the number of periods per year
     * @throws IllegalStateException if called on a non-periodic zero deposit strip
     */
    public int getPeriodsPerYear() {
        if (_instrumentType != StripInstrumentType.PERIODIC_ZERO_DEPOSIT) {
            throw new IllegalStateException(
                    "Cannot get number of periods per year for a non-periodic zero deposit strip " + toString());
        }
        return _periodsPerYear;
    }

    /**
     * Gets the name of the convention used to resolve this strip definition into a security.
     *
     * @return the name, not null
     */
    public String getConventionName() {
        return _conventionName;
    }

    /**
     * Calculates the tenor of a strip. For all instruments except futures, this is the same as that entered on construction.
     * For futures, this is the start tenor + (3 * future number)
     * @return The effective tenor of the strip
     */
    public Tenor getEffectiveTenor() {
        return Tenor.of(getInstrumentType() == StripInstrumentType.FUTURE
                ? getCurveNodePointTime().getPeriod().plusMonths(3 * getNumberOfFuturesAfterTenor())
                : getCurveNodePointTime().getPeriod());
    }

    /**
     * Gets the pay tenor for a basis swap
     * @return The pay tenor
     */
    public Tenor getPayTenor() {
        if (_instrumentType != StripInstrumentType.BASIS_SWAP) {
            throw new IllegalStateException(
                    "Cannot get the pay tenor for an instrument that is not a basis swap; have " + toString());
        }
        return _payTenor;
    }

    /**
     * Gets the receive tenor for a basis swap
     * @return The receive tenor
     */
    public Tenor getReceiveTenor() {
        if (_instrumentType != StripInstrumentType.BASIS_SWAP) {
            throw new IllegalStateException(
                    "Cannot get the receive tenor for an instrument that is not a basis swap; have " + toString());
        }
        return _receiveTenor;
    }

    /**
     * Gets the reset tenor.
     * @return The reset tenor
     */
    public Tenor getResetTenor() {
        return _resetTenor;
    }

    /**
     * Gets the pay index type for a basis swap
     * @return The pay index type
     */
    public IndexType getPayIndexType() {
        if (_instrumentType != StripInstrumentType.BASIS_SWAP) {
            throw new IllegalStateException(
                    "Cannot get the pay index type for an instrument that is not a basis swap; have " + toString());
        }
        return _payIndexType;
    }

    /**
     * Gets the receive tenor for a basis swap
     * @return The receive tenor
     */
    public IndexType getReceiveIndexType() {
        if (_instrumentType != StripInstrumentType.BASIS_SWAP) {
            throw new IllegalStateException(
                    "Cannot get the receive index type for an instrument that is not a basis swap; have "
                            + toString());
        }
        return _receiveIndexType;
    }

    /**
     * Gets the index type.
     * @return The receive tenor
     */
    public IndexType getIndexType() {
        return _indexType;
    }

    public FixedIncomeStrip getStrip1() {
        if (_instrumentType != StripInstrumentType.SPREAD) {
            throw new IllegalStateException(
                    "Cannot get the first strip for an instrument that is not a spread strip " + toString());
        }
        return _strip1;
    }

    public FixedIncomeStrip getStrip2() {
        if (_instrumentType != StripInstrumentType.SPREAD) {
            throw new IllegalStateException(
                    "Cannot get the second strip for an instrument that is not a spread strip " + toString());
        }
        return _strip2;
    }

    public OperationType getOperation() {
        if (_instrumentType != StripInstrumentType.SPREAD) {
            throw new IllegalStateException(
                    "Cannot get the operation for an instrument that is not a spread strip " + toString());
        }
        return _operation;
    }

    //-------------------------------------------------------------------------
    @Override
    public int compareTo(final FixedIncomeStrip other) {
        int result = DateUtils.estimatedDuration(getEffectiveTenor().getPeriod())
                .compareTo(DateUtils.estimatedDuration(other.getEffectiveTenor().getPeriod()));
        if (result != 0) {
            return result;
        }
        if (_instrumentType == StripInstrumentType.SPREAD) {
            result = getStrip1().compareTo(other.getStrip1());
            if (result != 0) {
                return result;
            }
            result = getStrip2().compareTo(other.getStrip2());
            if (result != 0) {
                return result;
            }
            return getOperation().ordinal() - other.getOperation().ordinal();
        }
        result = getInstrumentType().ordinal() - other.getInstrumentType().ordinal();
        if (result != 0) {
            return result;
        } else if (getInstrumentType() == StripInstrumentType.FUTURE) {
            result = getNumberOfFuturesAfterTenor() - other.getNumberOfFuturesAfterTenor();
        } else if (getInstrumentType() == StripInstrumentType.PERIODIC_ZERO_DEPOSIT) {
            result = getPeriodsPerYear() - other.getPeriodsPerYear();
        } else if (getInstrumentType() == StripInstrumentType.SWAP
                || getInstrumentType() == StripInstrumentType.OIS_SWAP && getIndexType() != null) {
            result = ObjectUtils.compare(getResetTenor(), other.getResetTenor());
            if (result != 0) {
                return result;
            }
            return ObjectUtils.compare(getIndexType(), other.getIndexType());
        } else if (getInstrumentType() == StripInstrumentType.BASIS_SWAP) {
            result = getPayTenor().compareTo(other.getPayTenor());
            if (result != 0) {
                return result;
            }
            result = ObjectUtils.compare(getReceiveTenor(), other.getReceiveTenor());
            if (result != 0) {
                return result;
            }
            result = ObjectUtils.compare(getPayIndexType(), other.getPayIndexType());
            if (result != 0) {
                return result;
            }
            result = ObjectUtils.compare(getReceiveIndexType(), other.getReceiveIndexType());
        }
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof FixedIncomeStrip) {
            final FixedIncomeStrip other = (FixedIncomeStrip) obj;
            if (_instrumentType == StripInstrumentType.SPREAD) {
                return ObjectUtils.equals(_curveNodePointTime, other._curveNodePointTime)
                        && ObjectUtils.equals(_conventionName, other._conventionName)
                        && ObjectUtils.equals(_strip1, other._strip1) && ObjectUtils.equals(_strip2, other._strip2)
                        && _operation == other._operation;
            }
            final boolean result = ObjectUtils.equals(_curveNodePointTime, other._curveNodePointTime)
                    && ObjectUtils.equals(_conventionName, other._conventionName)
                    && _instrumentType == other._instrumentType;
            if (getInstrumentType() == StripInstrumentType.FUTURE) {
                return result && _nthFutureFromTenor == other._nthFutureFromTenor;
            }
            if (getInstrumentType() == StripInstrumentType.PERIODIC_ZERO_DEPOSIT) {
                return result && _periodsPerYear == other._periodsPerYear;
            }
            if (getInstrumentType() == StripInstrumentType.SWAP
                    || getInstrumentType() == StripInstrumentType.OIS_SWAP && getIndexType() != null) {
                return result && ObjectUtils.equals(getResetTenor(), other.getResetTenor())
                        && ObjectUtils.equals(getIndexType(), other.getIndexType());
            }
            if (getInstrumentType() == StripInstrumentType.BASIS_SWAP) {
                return result && ObjectUtils.equals(getPayTenor(), other.getPayTenor())
                        && ObjectUtils.equals(getReceiveTenor(), other.getReceiveTenor())
                        && getPayIndexType() == other.getPayIndexType()
                        && getReceiveIndexType() == other.getReceiveIndexType();
            }
            return result;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return _curveNodePointTime.hashCode();
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("FixedIncomeStrip[");
        if (_instrumentType == StripInstrumentType.SPREAD) {
            sb.append(_strip1.toString());
            sb.append(_operation.getSymbol());
            sb.append(_strip2.toString());
            sb.append("]");
            return sb.toString();
        }
        sb.append("instrument type=");
        sb.append(getInstrumentType());
        sb.append(", ");
        sb.append("tenor=");
        sb.append(getCurveNodePointTime());
        sb.append(", ");
        if (getInstrumentType() == StripInstrumentType.FUTURE) {
            sb.append("future number after tenor=");
            sb.append(getNumberOfFuturesAfterTenor());
            sb.append(", ");
        } else if (getInstrumentType() == StripInstrumentType.PERIODIC_ZERO_DEPOSIT) {
            sb.append("periods per year=");
            sb.append(getPeriodsPerYear());
            sb.append(", ");
        } else if (getInstrumentType() == StripInstrumentType.SWAP
                || getInstrumentType() == StripInstrumentType.OIS_SWAP && getIndexType() != null) {
            sb.append("reset tenor=");
            sb.append(getResetTenor());
            sb.append(" on ");
            sb.append(getIndexType());
            sb.append(", ");
        } else if (getInstrumentType() == StripInstrumentType.BASIS_SWAP) {
            sb.append("pay tenor=");
            sb.append(getPayTenor());
            sb.append(" on ");
            sb.append(getPayIndexType());
            sb.append(", receive tenor=");
            sb.append(getReceiveTenor());
            sb.append(" on ");
            sb.append(getReceiveIndexType());
            sb.append(", ");
        }
        sb.append("convention name=");
        sb.append(getConventionName());
        sb.append("]");
        return sb.toString();
    }

    //-------------------------------------------------------------------------
    // REVIEW: jim 22-Aug-2010 -- get rid of these and use the builder directly
    public void toFudgeMsg(final FudgeSerializer serializer, final MutableFudgeMsg message) {
        final FixedIncomeStripFudgeBuilder builder = new FixedIncomeStripFudgeBuilder();
        final MutableFudgeMsg container = builder.buildMessage(serializer, this);
        for (final FudgeField field : container.getAllFields()) {
            message.add(field);
        }
    }

    // REVIEW: jim 22-Aug-2010 -- get rid of these and use the builder directly
    public static FixedIncomeStrip fromFudgeMsg(final FudgeDeserializer deserializer, final FudgeMsg message) {
        final FixedIncomeStripFudgeBuilder builder = new FixedIncomeStripFudgeBuilder();
        return builder.buildObject(deserializer, message);
    }

}