/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.generator; import static org.threeten.bp.temporal.ChronoUnit.MONTHS; import org.threeten.bp.ZonedDateTime; import com.opengamma.financial.security.FinancialSecurityUtils; import com.opengamma.financial.security.option.EuropeanExerciseType; import com.opengamma.financial.security.option.SwaptionSecurity; import com.opengamma.financial.security.swap.CommodityNotional; import com.opengamma.financial.security.swap.FixedInflationSwapLeg; import com.opengamma.financial.security.swap.FixedInterestRateLeg; import com.opengamma.financial.security.swap.FixedVarianceSwapLeg; import com.opengamma.financial.security.swap.FloatingGearingIRLeg; import com.opengamma.financial.security.swap.FloatingInterestRateLeg; import com.opengamma.financial.security.swap.FloatingSpreadIRLeg; import com.opengamma.financial.security.swap.FloatingVarianceSwapLeg; import com.opengamma.financial.security.swap.InflationIndexSwapLeg; import com.opengamma.financial.security.swap.InterestRateNotional; import com.opengamma.financial.security.swap.NotionalVisitor; import com.opengamma.financial.security.swap.SecurityNotional; import com.opengamma.financial.security.swap.SwapLeg; import com.opengamma.financial.security.swap.SwapLegVisitor; import com.opengamma.financial.security.swap.SwapSecurity; import com.opengamma.financial.security.swap.VarianceSwapNotional; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.time.Expiry; /** * Source of random, but reasonable, swaption security instances. */ public class SwaptionSecurityGenerator extends SecurityGenerator<SwaptionSecurity> { private static final int[] OPTION_LENGTH = new int[] {1, 2, 3, 6, 9, 12, 24, 36, 60 }; private final SwapSecurityGenerator _underlying; private final SecurityPersister _securityPersister; public SwaptionSecurityGenerator(final SwapSecurityGenerator underlying, final SecurityPersister securityPersister) { ArgumentChecker.notNull(underlying, "underlying"); ArgumentChecker.notNull(securityPersister, "securityPersister"); _underlying = underlying; _securityPersister = securityPersister; } protected SwapSecurityGenerator getUnderlyingGenerator() { return _underlying; } protected SecurityPersister getSecurityPersister() { return _securityPersister; } protected SwapSecurity createUnderlying(final ZonedDateTime earliestMaturity, final ZonedDateTime swaptionExpiry) { SwapSecurity security; do { do { getUnderlyingGenerator().setSwationExpiry(swaptionExpiry.toLocalDate()); security = getUnderlyingGenerator().createSecurity(); } while (security == null); } while ((FinancialSecurityUtils.getCurrency(security) == null) || security.getMaturityDate().isBefore(earliestMaturity)); return security; } private String lengthString(final int months) { if ((months % 12) == 0) { return (months / 12) + "Y"; } else { return months + "M"; } } protected String createName(final Currency currency, final int optionLength, final int swapLength, final double notional, final double rate) { final StringBuilder sb = new StringBuilder(); sb.append("Vanilla swaption, ").append(lengthString(optionLength)).append(" x ").append(lengthString(swapLength)).append(", "); sb.append(currency.getCode()).append(" ").append(NOTIONAL_FORMATTER.format(notional)).append(" @ ").append(RATE_FORMATTER.format(rate)); return sb.toString(); } private Double getRate(final SwapLeg leg) { return leg.accept(new SwapLegVisitor<Double>() { @Override public Double visitFixedInterestRateLeg(final FixedInterestRateLeg swapLeg) { return swapLeg.getRate(); } @Override public Double visitFloatingInterestRateLeg(final FloatingInterestRateLeg swapLeg) { return null; } @Override public Double visitFloatingSpreadIRLeg(final FloatingSpreadIRLeg swapLeg) { return null; } @Override public Double visitFloatingGearingIRLeg(final FloatingGearingIRLeg swapLeg) { return null; } @Override public Double visitFixedVarianceSwapLeg(final FixedVarianceSwapLeg swapLeg) { return swapLeg.getStrike(); } @Override public Double visitFloatingVarianceSwapLeg(final FloatingVarianceSwapLeg swapLeg) { return null; } @Override public Double visitFixedInflationSwapLeg(final FixedInflationSwapLeg swapLeg) { return swapLeg.getRate(); } @Override public Double visitInflationIndexSwapLeg(final InflationIndexSwapLeg swapLeg) { return null; } }); } @Override public SwaptionSecurity createSecurity() { final int optionLength = getRandom(OPTION_LENGTH); ZonedDateTime expiry = ZonedDateTime.now().plusMonths(optionLength); final SwapSecurity underlying = createUnderlying(expiry.plusMonths(2), expiry); final Currency currency = FinancialSecurityUtils.getCurrency(underlying); expiry = nextWorkingDay(expiry, currency); final boolean isPayer = getRandom().nextBoolean(); final boolean isLong = getRandom().nextBoolean(); final boolean isCashSettled = getRandom().nextBoolean(); final ZonedDateTime settlementDate = nextWorkingDay(expiry.plusDays(2), currency); final Double notional = underlying.getPayLeg().getNotional().accept(new NotionalVisitor<Double>() { @Override public Double visitCommodityNotional(final CommodityNotional notional) { return null; } @Override public Double visitInterestRateNotional(final InterestRateNotional notional) { return notional.getAmount(); } @Override public Double visitSecurityNotional(final SecurityNotional notional) { return null; } @Override public Double visitVarianceSwapNotional(final VarianceSwapNotional notional) { return notional.getAmount(); } }); if (notional == null) { return null; } Double rate = getRate(underlying.getPayLeg()); if (rate == null) { rate = getRate(underlying.getReceiveLeg()); if (rate == null) { return null; } } final SwaptionSecurity security = new SwaptionSecurity(isPayer, getSecurityPersister().storeSecurity(underlying).iterator().next(), isLong, new Expiry(expiry), isCashSettled, currency, notional, new EuropeanExerciseType(), settlementDate); security.setName(createName(currency, optionLength, (int) MONTHS.between(underlying.getEffectiveDate(), underlying.getMaturityDate()), notional, rate)); return security; } }