/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.instrument.future; import org.apache.commons.lang.ObjectUtils; import org.threeten.bp.LocalDate; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.interestrate.future.derivative.FuturesSecurity; import com.opengamma.util.ArgumentChecker; /** * Abstract class for transactions on generic futures-like products =, i.e. financial instruments with daily marniging. * @param <FS> The futures type of the underlying security. */ public abstract class FuturesTransactionDefinition<FS extends FuturesSecurityDefinition<? extends FuturesSecurity>> { /** * Underlying future security. Not null; */ private final FS _underlyingSecurity; /** * Quantity of future. Can be positive or negative. */ private final long _quantity; /** * Transaction date. Not null. */ private final ZonedDateTime _tradeDate; /** * Transaction price. The price is in relative number and not in percent. A standard price will be 0.985 and not 98.5. */ private final double _tradePrice; /** * Constructor. * @param underlyingSecurity The underlying futures security. * @param quantity The quantity of the transaction. * @param tradeDate The transaction date. * @param tradePrice The transaction price (in the convention of the futures). */ public FuturesTransactionDefinition(final FS underlyingSecurity, long quantity, ZonedDateTime tradeDate, double tradePrice) { super(); ArgumentChecker.notNull(underlyingSecurity, "Underlying futures"); ArgumentChecker.notNull(tradeDate, "Trade date"); _underlyingSecurity = underlyingSecurity; _quantity = quantity; _tradeDate = tradeDate; _tradePrice = tradePrice; } /** * Returns the underlying futures security. * @return The security. */ public FS getUnderlyingSecurity() { return _underlyingSecurity; } /** * Returns the transaction quantity. * @return The quantity. */ public long getQuantity() { return _quantity; } /** * Returns the transaction date. * @return The date. */ public ZonedDateTime getTradeDate() { return _tradeDate; } /** * Returns the transaction price (in the convention of the futures). * @return The price. */ public double getTradePrice() { return _tradePrice; } /** * Returns the reference price of a futures transaction. * On the trade date, it is the trade price, on the dates (strictly) after the trade date, it is the last margin price. * @param dateTime The valuation date. * @param lastMarginPrice The lat margin price. * @return The price. */ public double referencePrice(final ZonedDateTime dateTime, final Double lastMarginPrice) { ArgumentChecker.notNull(dateTime, "date"); final LocalDate dateLocal = dateTime.toLocalDate(); final LocalDate transactionDateLocal = getTradeDate().toLocalDate(); ArgumentChecker.isTrue(!dateTime.isBefore(getTradeDate()), "Valuation date, {}, is before the trade date, {} ", dateTime, getTradeDate()); final LocalDate lastTradingDateLocal = getUnderlyingSecurity().getLastTradingDate().toLocalDate(); ArgumentChecker.isFalse(dateLocal.isAfter(lastTradingDateLocal), "Valuation date, {}, is after last trading date, ", dateLocal, lastTradingDateLocal); double referencePrice; if (transactionDateLocal.isBefore(dateLocal)) { // Transaction was before valuation date. ArgumentChecker.notNull(lastMarginPrice, "last margin price should not be null"); referencePrice = lastMarginPrice; } else { // Transaction is today referencePrice = getTradePrice(); } return referencePrice; } @Override public String toString() { final String result = "Quantity: " + _quantity + " of " + _underlyingSecurity.toString(); return result; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (_quantity ^ (_quantity >>> 32)); result = prime * result + _tradeDate.hashCode(); long temp; temp = Double.doubleToLongBits(_tradePrice); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + _underlyingSecurity.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } FuturesTransactionDefinition<?> other = (FuturesTransactionDefinition<?>) obj; if (_quantity != other._quantity) { return false; } if (!ObjectUtils.equals(_tradeDate, other._tradeDate)) { return false; } if (Double.doubleToLongBits(_tradePrice) != Double.doubleToLongBits(other._tradePrice)) { return false; } if (!ObjectUtils.equals(_underlyingSecurity, other._underlyingSecurity)) { return false; } return true; } }