return new SwapLegVisitor<AnnuityDefinition<? extends PaymentDefinition>>() {
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFixedInterestRateLeg(final FixedInterestRateLeg swapLeg) {
final ExternalId regionId = swapLeg.getRegionId();
final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, regionId);
final InterestRateNotional interestRateNotional = (InterestRateNotional) swapLeg.getNotional();
final Currency currency = interestRateNotional.getCurrency();
final String fixedLegConventionName = getConventionName(currency, IRS_FIXED_LEG);
final SwapFixedLegConvention fixedLegConvention = _conventionSource.getConvention(SwapFixedLegConvention.class, ExternalId.of(SCHEME_NAME, fixedLegConventionName));
if (fixedLegConvention == null) {
throw new OpenGammaRuntimeException("Could not get fixed leg convention with the identifier " + ExternalId.of(SCHEME_NAME, fixedLegConventionName));
}
final Frequency freqFixed = swapLeg.getFrequency();
final Period tenorFixed = getTenor(freqFixed);
final double notional = interestRateNotional.getAmount();
final DayCount dayCount = fixedLegConvention.getDayCount();
final boolean isEOM = fixedLegConvention.isIsEOM();
final double rate = swapLeg.getRate();
final BusinessDayConvention businessDayConvention = fixedLegConvention.getBusinessDayConvention();
return AnnuityCouponFixedDefinition.from(currency, effectiveDate, maturityDate, tenorFixed, calendar, dayCount,
businessDayConvention, isEOM, notional, rate, isPayer);
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFloatingInterestRateLeg(final FloatingInterestRateLeg swapLeg) {
final InterestRateNotional interestRateNotional = (InterestRateNotional) swapLeg.getNotional();
final Currency currency = interestRateNotional.getCurrency();
final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, swapLeg.getRegionId());
switch (swapLeg.getFloatingRateType()) {
case IBOR:
return getIborAnnuity(swapLeg, interestRateNotional, currency, calendar);
case OIS:
return getOISAnnuity(swapLeg, interestRateNotional, currency);
case CMS:
return getCMSAnnuity(swapLeg, interestRateNotional, currency, calendar);
case OVERNIGHT_ARITHMETIC_AVERAGE:
return getOvernightAAverageAnnuity(swapLeg, interestRateNotional, currency);
default:
throw new OpenGammaRuntimeException("Cannot handle floating type " + swapLeg.getFloatingRateType());
}
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFloatingSpreadIRLeg(final FloatingSpreadIRLeg swapLeg) {
final InterestRateNotional interestRateNotional = (InterestRateNotional) swapLeg.getNotional();
final Currency currency = interestRateNotional.getCurrency();
final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, swapLeg.getRegionId());
switch (swapLeg.getFloatingRateType()) {
case IBOR:
return getIborAnnuity(swapLeg, interestRateNotional, currency, calendar);
case OIS:
return getOISAnnuity(swapLeg, interestRateNotional, currency);
case CMS:
return getCMSAnnuity(swapLeg, interestRateNotional, currency, calendar);
case OVERNIGHT_ARITHMETIC_AVERAGE:
return getOvernightAAverageAnnuity(swapLeg, interestRateNotional, currency);
default:
throw new OpenGammaRuntimeException("Cannot handle floating type " + swapLeg.getFloatingRateType());
}
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFloatingGearingIRLeg(final FloatingGearingIRLeg swapLeg) {
throw new OpenGammaRuntimeException("Cannot handle " + swapLeg.getClass());
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFixedVarianceSwapLeg(final FixedVarianceSwapLeg swapLeg) {
throw new OpenGammaRuntimeException("Cannot handle " + swapLeg.getClass());
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFloatingVarianceSwapLeg(final FloatingVarianceSwapLeg swapLeg) {
throw new OpenGammaRuntimeException("Cannot handle " + swapLeg.getClass());
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitFixedInflationSwapLeg(final FixedInflationSwapLeg swapLeg) {
throw new OpenGammaRuntimeException("Cannot handle " + swapLeg.getClass());
}
@Override
public final AnnuityDefinition<? extends PaymentDefinition> visitInflationIndexSwapLeg(final InflationIndexSwapLeg swapLeg) {
throw new OpenGammaRuntimeException("Cannot handle " + swapLeg.getClass());
}
private AnnuityDefinition<? extends PaymentDefinition> getIborAnnuity(final FloatingInterestRateLeg swapLeg, final InterestRateNotional interestRateNotional,
final Currency currency, final Calendar calendar) {
final String tenorString = getTenorString(swapLeg.getFrequency());
final String iborLegConventionName = getConventionName(currency, tenorString, IRS_IBOR_LEG);
final VanillaIborLegConvention iborLegConvention = _conventionSource.getConvention(VanillaIborLegConvention.class, ExternalId.of(SCHEME_NAME, iborLegConventionName));
if (iborLegConvention == null) {
throw new OpenGammaRuntimeException("Could not get Ibor leg convention with the identifier " + ExternalId.of(SCHEME_NAME, iborLegConventionName));
}
final IborIndexConvention iborIndexConvention = _conventionSource.getConvention(IborIndexConvention.class, iborLegConvention.getIborIndexConvention());
final Frequency freqIbor = swapLeg.getFrequency();
final Period tenorIbor = getTenor(freqIbor);
final int spotLag = iborIndexConvention.getSettlementDays();
final DayCount dayCount = swapLeg.getDayCount();
final BusinessDayConvention businessDayConvention = swapLeg.getBusinessDayConvention();
final double notional = interestRateNotional.getAmount();
final IborIndex iborIndex = new IborIndex(currency, tenorIbor, spotLag, iborIndexConvention.getDayCount(), iborIndexConvention.getBusinessDayConvention(),
iborIndexConvention.isIsEOM(), iborIndexConvention.getName());
if (swapLeg instanceof FloatingSpreadIRLeg) {
final FloatingSpreadIRLeg spread = (FloatingSpreadIRLeg) swapLeg;
return AnnuityCouponIborSpreadDefinition.from(effectiveDate, maturityDate, tenorIbor, notional, iborIndex, isPayer, businessDayConvention, swapLeg.isEom(), dayCount,
spread.getSpread(), calendar);
}
return AnnuityCouponIborDefinition.from(effectiveDate, maturityDate, tenorIbor, notional, iborIndex, isPayer, businessDayConvention, swapLeg.isEom(), dayCount,
calendar);
}
private AnnuityDefinition<? extends PaymentDefinition> getOISAnnuity(final FloatingInterestRateLeg swapLeg, final InterestRateNotional interestRateNotional,
final Currency currency) {
final String oisConventionName = getConventionName(currency, OIS_ON_LEG);
final OISLegConvention oisConvention = _conventionSource.getConvention(OISLegConvention.class, ExternalId.of(SCHEME_NAME, oisConventionName));
if (oisConvention == null) {
throw new OpenGammaRuntimeException("Could not get OIS leg convention with the identifier " + ExternalId.of(SCHEME_NAME, oisConventionName));
}
final OvernightIndexConvention indexConvention = _conventionSource.getConvention(OvernightIndexConvention.class, oisConvention.getOvernightIndexConvention());
if (indexConvention == null) {
throw new OpenGammaRuntimeException("Could not get OIS index convention with the identifier " + oisConvention.getOvernightIndexConvention());
}
final String currencyString = currency.getCode();
final Integer publicationLag = indexConvention.getPublicationLag();
final Period paymentFrequency = getTenor(swapLeg.getFrequency());
final IndexON index = new IndexON(indexConvention.getName(), currency, indexConvention.getDayCount(), publicationLag);
final BusinessDayConvention businessDayConvention = swapLeg.getBusinessDayConvention();
final double notional = interestRateNotional.getAmount();
final int paymentLag = oisConvention.getPaymentLag();
final boolean isEOM = oisConvention.isIsEOM();
final Calendar indexCalendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, indexConvention.getRegionCalendar());
if (swapLeg instanceof FloatingSpreadIRLeg) {
final FloatingSpreadIRLeg spread = (FloatingSpreadIRLeg) swapLeg;
return AnnuityCouponONSpreadDefinition.from(effectiveDate, maturityDate, notional, isPayer, index, paymentLag, indexCalendar, businessDayConvention, paymentFrequency, isEOM,
spread.getSpread());
}
return AnnuityCouponONDefinition.from(effectiveDate, maturityDate, notional, isPayer, index, paymentLag, indexCalendar, businessDayConvention, paymentFrequency, isEOM);
}
private AnnuityDefinition<? extends PaymentDefinition> getCMSAnnuity(final FloatingInterestRateLeg swapLeg, final InterestRateNotional interestRateNotional,
final Currency currency, final Calendar calendar) {
if (swapLeg instanceof FloatingSpreadIRLeg) {
throw new OpenGammaRuntimeException("Cannot create an annuity for a CMS leg with a spread");
}
final String tenorString = getTenorString(swapLeg.getFrequency());
final String iborLegConventionName = getConventionName(currency, tenorString, IRS_IBOR_LEG);
final VanillaIborLegConvention iborLegConvention = _conventionSource.getConvention(VanillaIborLegConvention.class,
ExternalId.of(SCHEME_NAME, getConventionName(currency, tenorString, IRS_IBOR_LEG)));
if (iborLegConvention == null) {
throw new OpenGammaRuntimeException("Could not get Ibor leg convention with the identifier " + ExternalId.of(SCHEME_NAME, iborLegConventionName));
}
final IborIndexConvention iborIndexConvention = _conventionSource.getConvention(IborIndexConvention.class, iborLegConvention.getIborIndexConvention());
final String swapIndexConventionName = getConventionName(currency, tenorString, SWAP_INDEX);
final SwapIndexConvention swapIndexConvention = _conventionSource.getConvention(SwapIndexConvention.class, ExternalId.of(SCHEME_NAME, swapIndexConventionName));
if (swapIndexConvention == null) {
throw new OpenGammaRuntimeException("Could not get swap index convention with the identifier " + ExternalId.of(SCHEME_NAME, swapIndexConventionName));
}
final SwapConvention underlyingSwapConvention = _conventionSource.getConvention(SwapConvention.class, swapIndexConvention.getSwapConvention());
if (underlyingSwapConvention == null) {
throw new OpenGammaRuntimeException("Could not get swap convention with the identifier " + swapIndexConvention.getSwapConvention());
}
final SwapFixedLegConvention payLegConvention = _conventionSource.getConvention(SwapFixedLegConvention.class, underlyingSwapConvention.getPayLegConvention());
if (payLegConvention == null) {
throw new OpenGammaRuntimeException("Could not get convention with the identifier " + underlyingSwapConvention.getPayLegConvention());
}
final VanillaIborLegConvention receiveLegConvention = _conventionSource.getConvention(VanillaIborLegConvention.class, underlyingSwapConvention.getReceiveLegConvention());
if (receiveLegConvention == null) {
throw new OpenGammaRuntimeException("Could not get convention with the identifier " + underlyingSwapConvention.getReceiveLegConvention());
}
final Frequency freqIbor = swapLeg.getFrequency();
final Period tenorIbor = getTenor(freqIbor);
final int spotLag = iborIndexConvention.getSettlementDays();
final DayCount dayCount = swapLeg.getDayCount();
final BusinessDayConvention businessDayConvention = swapLeg.getBusinessDayConvention();
final double notional = interestRateNotional.getAmount();
final IborIndex iborIndex = new IborIndex(currency, tenorIbor, spotLag, iborIndexConvention.getDayCount(), iborIndexConvention.getBusinessDayConvention(),
iborIndexConvention.isIsEOM(), iborIndexConvention.getName());
final Period fixedLegPaymentPeriod = payLegConvention.getPaymentTenor().getPeriod();
final DayCount fixedLegDayCount = payLegConvention.getDayCount();
final Period period = Period.ofYears(10); // TODO why is a variable field like this in IndexSwap? It's only used in one place in the entire analytics library.
final IndexSwap swapIndex = new IndexSwap(fixedLegPaymentPeriod, fixedLegDayCount, iborIndex, period, calendar);
return AnnuityCouponCMSDefinition.from(effectiveDate, maturityDate, notional, swapIndex, tenorIbor, dayCount, isPayer, calendar);
}
private AnnuityDefinition<? extends PaymentDefinition> getOvernightAAverageAnnuity(final FloatingInterestRateLeg swapLeg, final InterestRateNotional interestRateNotional,
final Currency currency) {
final String oisConventionName = getConventionName(currency, OIS_ON_LEG);
final OISLegConvention oisConvention = _conventionSource.getConvention(OISLegConvention.class, ExternalId.of(SCHEME_NAME, oisConventionName));
if (oisConvention == null) {
throw new OpenGammaRuntimeException("Could not get OIS leg convention with the identifier " + ExternalId.of(SCHEME_NAME, oisConventionName));
}
final OvernightIndexConvention indexConvention = _conventionSource.getConvention(OvernightIndexConvention.class, oisConvention.getOvernightIndexConvention());
if (indexConvention == null) {
throw new OpenGammaRuntimeException("Could not get OIS index convention with the identifier " + oisConvention.getOvernightIndexConvention());
}
final String currencyString = currency.getCode();
final Integer publicationLag = indexConvention.getPublicationLag();
final Period paymentFrequency = getTenor(swapLeg.getFrequency());
final IndexON index = new IndexON(indexConvention.getName(), currency, indexConvention.getDayCount(), publicationLag);
final BusinessDayConvention businessDayConvention = swapLeg.getBusinessDayConvention();
final double notional = interestRateNotional.getAmount();
final int paymentLag = oisConvention.getPaymentLag();
final boolean isEOM = oisConvention.isIsEOM();
final Calendar indexCalendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, indexConvention.getRegionCalendar());
if (swapLeg instanceof FloatingSpreadIRLeg) {
final FloatingSpreadIRLeg spread = (FloatingSpreadIRLeg) swapLeg;
return AnnuityCouponArithmeticAverageONSpreadDefinition.from(effectiveDate, maturityDate, notional, spread.getSpread(), isPayer, paymentFrequency, index,
paymentLag, businessDayConvention, isEOM, indexCalendar);
}