/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.product.swap.type;
import java.time.LocalDate;
import java.time.Period;
import org.joda.convert.FromString;
import org.joda.convert.ToString;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.ReferenceDataNotFoundException;
import com.opengamma.strata.basics.date.DaysAdjustment;
import com.opengamma.strata.basics.date.Tenor;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.collect.named.ExtendedEnum;
import com.opengamma.strata.collect.named.Named;
import com.opengamma.strata.product.TradeConvention;
import com.opengamma.strata.product.TradeInfo;
import com.opengamma.strata.product.common.BuySell;
import com.opengamma.strata.product.swap.SwapTrade;
/**
* A market convention for three leg basis swap trades.
* <p>
* This defines the market convention for a single currency basis swap.
* The convention is formed by combining three swap leg conventions in the same currency.
* <p>
* The market price is for the difference (spread) between the values of the two floating legs.
* This convention has three legs, the "spread leg", the "spread floating leg" and the "flat floating leg".
* The "spread leg" represented by the fixed leg will be added to the "spread floating leg"
* which is typically the leg with the shorter underlying tenor.
* Thus the "spread leg" and "spread floating leg" will have the same pay/receive direction.
* <p>
* To manually create a convention, see {@link ImmutableThreeLegBasisSwapConvention}.
* To register a specific convention, see {@code ThreeLegBasisSwapConvention.ini}.
*/
public interface ThreeLegBasisSwapConvention
extends TradeConvention, Named {
/**
* Obtains an instance from the specified unique name.
*
* @param uniqueName the unique name
* @return the convention
* @throws IllegalArgumentException if the name is not known
*/
@FromString
public static ThreeLegBasisSwapConvention of(String uniqueName) {
ArgChecker.notNull(uniqueName, "uniqueName");
return extendedEnum().lookup(uniqueName);
}
/**
* Gets the extended enum helper.
* <p>
* This helper allows instances of the convention to be looked up.
* It also provides the complete set of available instances.
*
* @return the extended enum helper
*/
public static ExtendedEnum<ThreeLegBasisSwapConvention> extendedEnum() {
return ThreeLegBasisSwapConventions.ENUM_LOOKUP;
}
//-----------------------------------------------------------------------
/**
* Gets the market convention of the spread leg.
*
* @return the spread leg convention
*/
public abstract FixedRateSwapLegConvention getSpreadLeg();
/**
* Gets the market convention of the floating leg to which the spread leg is added.
*
* @return the spread floating leg convention
*/
public abstract IborRateSwapLegConvention getSpreadFloatingLeg();
/**
* Gets the market convention of the floating leg that does not have the spread applied.
*
* @return the flat floating leg convention
*/
public abstract IborRateSwapLegConvention getFlatFloatingLeg();
/**
* Gets the offset of the spot value date from the trade date.
* <p>
* The offset is applied to the trade date to find the start date.
* A typical value is "plus 2 business days".
*
* @return the spot date offset, not null
*/
public abstract DaysAdjustment getSpotDateOffset();
//-------------------------------------------------------------------------
/**
* Creates a spot-starting trade based on this convention.
* <p>
* This returns a trade based on the specified tenor. For example, a tenor
* of 5 years creates a swap starting on the spot date and maturing 5 years later.
* <p>
* The notional is unsigned, with buy/sell determining the direction of the trade.
* If buying the swap, the rate of the floating flat leg is received from the counterparty,
* with the rate of the floating spread leg and the spread of the fixed leg being paid.
* If selling the swap, the opposite occurs.
*
* @param tradeDate the date of the trade
* @param tenor the tenor of the swap
* @param buySell the buy/sell flag
* @param notional the notional amount
* @param spread the spread, typically derived from the market
* @param refData the reference data, used to resolve the trade dates
* @return the trade
* @throws ReferenceDataNotFoundException if an identifier cannot be resolved in the reference data
*/
public default SwapTrade createTrade(
LocalDate tradeDate,
Tenor tenor,
BuySell buySell,
double notional,
double spread,
ReferenceData refData) {
return createTrade(tradeDate, Period.ZERO, tenor, buySell, notional, spread, refData);
}
/**
* Creates a forward-starting trade based on this convention.
* <p>
* This returns a trade based on the specified period and tenor. For example, a period of
* 3 months and a tenor of 5 years creates a swap starting three months after the spot date
* and maturing 5 years later.
* <p>
* The notional is unsigned, with buy/sell determining the direction of the trade.
* If buying the swap, the rate of the floating flat leg is received from the counterparty,
* with the rate of the floating spread leg and the spread of the fixed leg being paid.
* If selling the swap, the opposite occurs.
*
* @param tradeDate the date of the trade
* @param periodToStart the period between the spot date and the start date
* @param tenor the tenor of the swap
* @param buySell the buy/sell flag
* @param notional the notional amount
* @param spread the spread, typically derived from the market
* @param refData the reference data, used to resolve the trade dates
* @return the trade
* @throws ReferenceDataNotFoundException if an identifier cannot be resolved in the reference data
*/
public default SwapTrade createTrade(
LocalDate tradeDate,
Period periodToStart,
Tenor tenor,
BuySell buySell,
double notional,
double spread,
ReferenceData refData) {
LocalDate spotValue = calculateSpotDateFromTradeDate(tradeDate, refData);
LocalDate startDate = spotValue.plus(periodToStart);
LocalDate endDate = startDate.plus(tenor.getPeriod());
return toTrade(tradeDate, startDate, endDate, buySell, notional, spread);
}
/**
* Creates a trade based on this convention.
* <p>
* This returns a trade based on the specified dates.
* <p>
* The notional is unsigned, with buy/sell determining the direction of the trade.
* If buying the swap, the rate of the floating flat leg is received from the counterparty,
* with the rate of the floating spread leg and the spread of the fixed leg being paid.
* If selling the swap, the opposite occurs.
*
* @param tradeDate the date of the trade
* @param startDate the start date
* @param endDate the end date
* @param buySell the buy/sell flag
* @param notional the notional amount
* @param spread the spread, typically derived from the market
* @return the trade
*/
public default SwapTrade toTrade(
LocalDate tradeDate,
LocalDate startDate,
LocalDate endDate,
BuySell buySell,
double notional,
double spread) {
TradeInfo tradeInfo = TradeInfo.of(tradeDate);
return toTrade(tradeInfo, startDate, endDate, buySell, notional, spread);
}
/**
* Creates a trade based on this convention.
* <p>
* This returns a trade based on the specified dates.
* <p>
* The notional is unsigned, with buy/sell determining the direction of the trade.
* If buying the swap, the rate of the floating flat leg is received from the counterparty,
* with the rate of the floating spread leg and the spread of the fixed leg being paid.
* If selling the swap, the opposite occurs.
*
* @param tradeInfo additional information about the trade
* @param startDate the start date
* @param endDate the end date
* @param buySell the buy/sell flag
* @param notional the notional amount
* @param spread the spread, typically derived from the market
* @return the trade
*/
public abstract SwapTrade toTrade(
TradeInfo tradeInfo,
LocalDate startDate,
LocalDate endDate,
BuySell buySell,
double notional,
double spread);
//-------------------------------------------------------------------------
/**
* Calculates the spot date from the trade date.
*
* @param tradeDate the trade date
* @param refData the reference data, used to resolve the date
* @return the spot date
* @throws ReferenceDataNotFoundException if an identifier cannot be resolved in the reference data
*/
public default LocalDate calculateSpotDateFromTradeDate(LocalDate tradeDate, ReferenceData refData) {
return getSpotDateOffset().adjust(tradeDate, refData);
}
//-------------------------------------------------------------------------
/**
* Gets the name that uniquely identifies this convention.
* <p>
* This name is used in serialization and can be parsed using {@link #of(String)}.
*
* @return the unique name
*/
@ToString
@Override
public abstract String getName();
}