Package com.opengamma.financial.analytics.ircurve

Source Code of com.opengamma.financial.analytics.ircurve.FixedIncomeStripIdentifierAndMaturityBuilder$InstrumentHandler

/**
* 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.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalTime;
import org.threeten.bp.Period;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.Iterables;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.schedule.ScheduleCalculator;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.core.marketdatasnapshot.SnapshotDataBundle;
import com.opengamma.core.region.Region;
import com.opengamma.core.region.RegionSource;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.financial.analytics.conversion.CalendarUtils;
import com.opengamma.financial.convention.ConventionBundle;
import com.opengamma.financial.convention.ConventionBundleSource;
import com.opengamma.financial.convention.InMemoryConventionBundleMaster;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.daycount.DayCount;
import com.opengamma.financial.convention.frequency.Frequency;
import com.opengamma.financial.convention.frequency.PeriodFrequency;
import com.opengamma.financial.security.cash.CashSecurity;
import com.opengamma.financial.security.deposit.PeriodicZeroDepositSecurity;
import com.opengamma.financial.security.fra.FRASecurity;
import com.opengamma.financial.security.future.FutureSecurity;
import com.opengamma.financial.security.swap.FixedInterestRateLeg;
import com.opengamma.financial.security.swap.FloatingInterestRateLeg;
import com.opengamma.financial.security.swap.FloatingRateType;
import com.opengamma.financial.security.swap.FloatingSpreadIRLeg;
import com.opengamma.financial.security.swap.InterestRateNotional;
import com.opengamma.financial.security.swap.SwapSecurity;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.time.Tenor;

/**
* Converts specifications into fully resolved security definitions
*/
public class FixedIncomeStripIdentifierAndMaturityBuilder {
  private static final Logger s_logger = LoggerFactory.getLogger(FixedIncomeStripIdentifierAndMaturityBuilder.class);
  private static final LocalTime CASH_EXPIRY_TIME = LocalTime.of(11, 00);

  private final RegionSource _regionSource;
  private final ConventionBundleSource _conventionBundleSource;
  private final SecuritySource _secSource;
  private final HolidaySource _holidaySource;

  // TODO: Don't accept a SecuritySource here; use the ComputationTargetResolver
  public FixedIncomeStripIdentifierAndMaturityBuilder(final RegionSource regionSource, final ConventionBundleSource conventionBundleSource, final SecuritySource secSource,
      final HolidaySource holidaySource) {
    _regionSource = regionSource;
    _conventionBundleSource = conventionBundleSource;
    _secSource = secSource;
    _holidaySource = holidaySource;
  }

  public InterpolatedYieldCurveSpecificationWithSecurities resolveToSecurity(final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues) {
    final Collection<FixedIncomeStripWithSecurity> securityStrips = new TreeSet<>();
    final LocalDate curveDate = curveSpecification.getCurveDate();
    for (final FixedIncomeStripWithIdentifier strip : curveSpecification.getStrips()) {
      final InstrumentHandler handler = getInstrumentHandler(strip);
      final Security security = handler.getSecurity(this, curveSpecification, marketValues, strip);
      final ZonedDateTime maturity = handler.getMaturity(this, curveDate, strip, security);
      final Tenor resolvedTenor = Tenor.of(Period.between(curveDate, maturity.toLocalDate()));
      securityStrips.add(new FixedIncomeStripWithSecurity(strip.getStrip(), resolvedTenor, maturity, strip.getSecurity(), security));
    }
    return new InterpolatedYieldCurveSpecificationWithSecurities(curveDate, curveSpecification.getName(), curveSpecification.getCurrency(), curveSpecification.getInterpolator(),
        curveSpecification.interpolateYield(), securityStrips);
  }

  // TODO: Implement the "getRequirements" methods and use this to make sure that target resolver caches are pre-populated at execution time
  public Set<ValueRequirement> getResolutionRequirements(final InterpolatedYieldCurveSpecification curveSpecification) {
    final Set<ValueRequirement> requirements = new HashSet<>();
    for (final FixedIncomeStripWithIdentifier strip : curveSpecification.getStrips()) {
      final InstrumentHandler handler = getInstrumentHandler(strip);
      requirements.addAll(handler.getRequirements(this, curveSpecification, strip));
    }
    return requirements;
  }

  private abstract static class InstrumentHandler {

    public abstract Security getSecurity(FixedIncomeStripIdentifierAndMaturityBuilder self, InterpolatedYieldCurveSpecification curveSpecification, SnapshotDataBundle marketValues,
        FixedIncomeStripWithIdentifier strip);

    public abstract ZonedDateTime getMaturity(FixedIncomeStripIdentifierAndMaturityBuilder self, LocalDate curveDate, FixedIncomeStripWithIdentifier strip, Security security);

    public abstract Set<ValueRequirement> getRequirements(FixedIncomeStripIdentifierAndMaturityBuilder self, InterpolatedYieldCurveSpecification curveSpecification,
        FixedIncomeStripWithIdentifier strip);

  }

  private static final InstrumentHandler s_cash = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity cashSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (cashSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve cash curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return cashSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity cashSecurity = (CashSecurity) security;
      final Region region = self._regionSource.getHighestLevelRegion(cashSecurity.getRegionId());
      ZoneId timeZone = region.getTimeZone();
      timeZone = ensureZone(timeZone);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_fra3m = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final FRASecurity fraSecurity = self.getFRA(curveSpecification, strip, marketValues, Tenor.THREE_MONTHS);
      if (fraSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve FRA curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return fraSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final FRASecurity fraSecurity = (FRASecurity) security;
      return fraSecurity.getEndDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_fra6m = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final FRASecurity fraSecurity = self.getFRA(curveSpecification, strip, marketValues, Tenor.SIX_MONTHS);
      if (fraSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve FRA curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return fraSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final FRASecurity fraSecurity = (FRASecurity) security;
      return fraSecurity.getEndDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_fra = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final FRASecurity fraSecurity = self.getFRA(curveSpecification, strip, marketValues, Tenor.THREE_MONTHS);
      if (fraSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve FRA curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return fraSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final FRASecurity fraSecurity = (FRASecurity) security;
      return fraSecurity.getEndDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_future = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: jim 17-Aug-2010 -- we need to sort out the zoned date time related to the expiry.
      final FutureSecurity futureSecurity = self.getFuture(strip);
      if (futureSecurity == null) {
        throw new OpenGammaRuntimeException("Security source did not contain future curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return futureSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final FutureSecurity futureSecurity = (FutureSecurity) security;
      return futureSecurity.getExpiry().getExpiry().plusMonths(3); //TODO shouldn't hard-code to 3 - find out why comparator in FixedIncomeStrip isn't working properly
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_libor = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity rateSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (rateSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve Libor curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return rateSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity rateSecurity = (CashSecurity) security;
      final Region region2 = self._regionSource.getHighestLevelRegion(rateSecurity.getRegionId());
      ZoneId timeZone2 = region2.getTimeZone();
      timeZone2 = ensureZone(timeZone2);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone2);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_euribor = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity rateSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (rateSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve Euribor curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return rateSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity rateSecurity = (CashSecurity) security;
      final Region region2 = self._regionSource.getHighestLevelRegion(rateSecurity.getRegionId());
      ZoneId timeZone2 = region2.getTimeZone();
      timeZone2 = ensureZone(timeZone2);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone2);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_cdor = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity rateSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (rateSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve CDOR curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return rateSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity rateSecurity = (CashSecurity) security;
      final Region region2 = self._regionSource.getHighestLevelRegion(rateSecurity.getRegionId());
      ZoneId timeZone2 = region2.getTimeZone();
      timeZone2 = ensureZone(timeZone2);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone2);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_cibor = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity rateSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (rateSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve CIBOR curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return rateSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity rateSecurity = (CashSecurity) security;
      final Region region2 = self._regionSource.getHighestLevelRegion(rateSecurity.getRegionId());
      ZoneId timeZone2 = region2.getTimeZone();
      timeZone2 = ensureZone(timeZone2);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone2);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_stibor = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final CashSecurity rateSecurity = self.getCash(curveSpecification, strip, marketValues);
      if (rateSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve STIBOR curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return rateSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final CashSecurity rateSecurity = (CashSecurity) security;
      final Region region2 = self._regionSource.getHighestLevelRegion(rateSecurity.getRegionId());
      ZoneId timeZone2 = region2.getTimeZone();
      timeZone2 = ensureZone(timeZone2);
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(CASH_EXPIRY_TIME).atZone(timeZone2);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_swap = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      // In case there's any old curve definitions hanging around - assume that all swaps are 3m
      // TODO get defaults from convention? (e.g. USD = 3m, EUR = 6M)
      final SwapSecurity swapSecurity = self.getSwap(curveSpecification, strip, marketValues, Tenor.THREE_MONTHS);
      if (swapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return swapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity swapSecurity = (SwapSecurity) security;
      return swapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_swap3m = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity swapSecurity = self.getSwap(curveSpecification, strip, marketValues, Tenor.THREE_MONTHS);
      if (swapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return swapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity swapSecurity = (SwapSecurity) security;
      return swapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_swap6m = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity swapSecurity = self.getSwap(curveSpecification, strip, marketValues, Tenor.SIX_MONTHS);
      if (swapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return swapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity swapSecurity = (SwapSecurity) security;
      return swapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_swap12m = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity swapSecurity = self.getSwap(curveSpecification, strip, marketValues, Tenor.ONE_YEAR);
      if (swapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return swapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity swapSecurity = (SwapSecurity) security;
      return swapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_swap28d = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity swapSecurity = self.get28DaySwap(curveSpecification, strip, marketValues);
      if (swapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return swapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity swapSecurity = (SwapSecurity) security;
      return swapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_tenorSwap = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity tenorSwapSecurity = self.getTenorSwap(curveSpecification, strip, marketValues);
      if (tenorSwapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return tenorSwapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity tenorSwapSecurity = (SwapSecurity) security;
      return tenorSwapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_oisSwap = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      return self.getOISSwap(curveSpecification, strip, marketValues);
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      return curveDate.plus(strip.getMaturity().getPeriod()).atTime(11, 00).atZone(ZoneOffset.UTC);
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_periodicZeroDeposit = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final PeriodicZeroDepositSecurity depositSecurity = getPeriodicZeroDeposit(curveSpecification, strip, marketValues);
      return depositSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final PeriodicZeroDepositSecurity depositSecurity = (PeriodicZeroDepositSecurity) security;
      return depositSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static final InstrumentHandler s_basisSwap = new InstrumentHandler() {

    @Override
    public Security getSecurity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification, final SnapshotDataBundle marketValues,
        final FixedIncomeStripWithIdentifier strip) {
      final SwapSecurity basisSwapSecurity = self.getBasisSwap(curveSpecification, strip, marketValues);
      if (basisSwapSecurity == null) {
        throw new OpenGammaRuntimeException("Could not resolve basis swap curve instrument " + strip.getSecurity() + " from strip " + strip + " in " + curveSpecification);
      }
      return basisSwapSecurity;
    }

    @Override
    public ZonedDateTime getMaturity(final FixedIncomeStripIdentifierAndMaturityBuilder self, final LocalDate curveDate, final FixedIncomeStripWithIdentifier strip, final Security security) {
      final SwapSecurity basisSwapSecurity = (SwapSecurity) security;
      return basisSwapSecurity.getMaturityDate();
    }

    @Override
    public Set<ValueRequirement> getRequirements(final FixedIncomeStripIdentifierAndMaturityBuilder self, final InterpolatedYieldCurveSpecification curveSpecification,
        final FixedIncomeStripWithIdentifier strip) {
      // TODO: Implement this
      throw new UnsupportedOperationException("TODO");
    }

  };

  private static InstrumentHandler getInstrumentHandler(final FixedIncomeStripWithIdentifier strip) {
    switch (strip.getInstrumentType()) {
      case CASH:
        return s_cash;
      case FRA_3M:
        return s_fra3m;
      case FRA_6M:
        return s_fra6m;
      case FRA:
        return s_fra;
      case FUTURE:
        return s_future;
      case LIBOR:
        return s_libor;
      case EURIBOR:
        return s_euribor;
      case CDOR:
        return s_cdor;
      case CIBOR:
        return s_cibor;
      case STIBOR:
        return s_stibor;
      case SWAP:
        return s_swap;
      case SWAP_3M:
        return s_swap3m;
      case SWAP_6M:
        return s_swap6m;
      case SWAP_12M:
        return s_swap12m;
      case SWAP_28D:
        return s_swap28d;
      case TENOR_SWAP:
        return s_tenorSwap;
      case OIS_SWAP:
        return s_oisSwap;
      case PERIODIC_ZERO_DEPOSIT:
        return s_periodicZeroDeposit;
      case BASIS_SWAP:
        return s_basisSwap;
      default:
        throw new OpenGammaRuntimeException("Unhandled type of instrument in curve definition " + strip.getInstrumentType());
    }
  }

  private CashSecurity getCash(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ConventionBundle cashConvention = _conventionBundleSource.getConventionBundle(strip.getSecurity());
    if (cashConvention == null) {
      throw new OpenGammaRuntimeException("No convention for cash " + strip.getSecurity() + " so can't establish business day convention");
    }
    if (cashConvention.getRegion() == null) {
      throw new OpenGammaRuntimeException("Region for strip " + strip + " was null");
    }
    final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, cashConvention.getRegion());
    if (calendar == null) {
      throw new OpenGammaRuntimeException("Calendar was null");
    }
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final ZonedDateTime startDate = ScheduleCalculator.getAdjustedDate(curveDate, cashConvention.getSettlementDays(), calendar);
    final ZonedDateTime endDate = ScheduleCalculator.getAdjustedDate(startDate, cashConvention.getPeriod(), cashConvention.getBusinessDayConvention(), calendar, cashConvention.isEOMConvention());
    final Double rate = marketValues.getDataPoint(strip.getSecurity());
    if (rate == null) {
      throw new OpenGammaRuntimeException("No market data for " + strip.getSecurity());
    }
    final CashSecurity sec = new CashSecurity(spec.getCurrency(), spec.getRegion(), startDate, endDate, cashConvention.getDayCount(), rate, 1.0d);
    sec.setExternalIdBundle(ExternalIdBundle.of(strip.getSecurity()));
    return sec;
  }

  private FRASecurity getFRA(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues, final Tenor tenor) {
    final ExternalId fraIdentifier = strip.getSecurity();
    final int months = tenor.getPeriod().getMonths();
    final ExternalId underlyingId = getUnderlyingId(spec, strip);
    Period fraPeriod;
    final Currency ccy = spec.getCurrency();
    BusinessDayConvention businessDayConvention;
    boolean eom;
    Calendar calendar;
    ExternalId underlyingIdentifier;
    int settlementDays;
    if (underlyingId == null) {
      s_logger.info("Could not get convention for underlying from {}; trying tenor-based convention", strip);
      final ConventionBundle fraConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_" + months
          + "M_FRA"));
      if (fraConvention == null) {
        throw new OpenGammaRuntimeException("Could not get convention for " + fraIdentifier + ": tried "
            + ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_" + months + "M_FRA"));
      }
      underlyingIdentifier = fraConvention.getSwapFloatingLegInitialRate();
      final ConventionBundle iborConvention = _conventionBundleSource.getConventionBundle(underlyingIdentifier);
      underlyingIdentifier = fraConvention.getSwapFloatingLegInitialRate();
      fraPeriod = iborConvention.getPeriod();
      businessDayConvention = iborConvention.getBusinessDayConvention();
      eom = iborConvention.isEOMConvention();
      calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, fraConvention.getSwapFloatingLegRegion());
      settlementDays = iborConvention.getSettlementDays();
    } else {
      ConventionBundle fraConvention = _conventionBundleSource.getConventionBundle(underlyingId);
      if (fraConvention == null || fraConvention.getIdentifiers().size() != 1) {
        s_logger.info("Could not get unique convention for underlying from {}; trying tenor-based convention", strip);
        fraConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_" + months
            + "M_FRA"));
        if (fraConvention == null) {
          throw new OpenGammaRuntimeException("Could not get convention for " + fraIdentifier + ": tried "
              + ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_" + months + "M_FRA"));
        }
        final ConventionBundle iborConvention = _conventionBundleSource.getConventionBundle(fraConvention.getSwapFloatingLegInitialRate());
        fraPeriod = iborConvention.getPeriod();
        businessDayConvention = fraConvention.getSwapFloatingLegBusinessDayConvention();
        eom = fraConvention.isEOMConvention();
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, fraConvention.getSwapFloatingLegRegion());
        underlyingIdentifier = underlyingId;
        settlementDays = fraConvention.getSwapFloatingLegSettlementDays();
      } else {
        fraPeriod = fraConvention.getPeriod();
        businessDayConvention = fraConvention.getBusinessDayConvention();
        eom = fraConvention.isEOMConvention();
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, fraConvention.getRegion());
        underlyingIdentifier = Iterables.getOnlyElement(fraConvention.getIdentifiers());
        settlementDays = fraConvention.getSettlementDays();
      }
    }
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC); // TODO: review?
    final ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(curveDate, settlementDays, calendar);
    final Period endPeriod = strip.getMaturity().getPeriod();
    final ZonedDateTime endDate = ScheduleCalculator.getAdjustedDate(spotDate, endPeriod, businessDayConvention, calendar, eom);
    final Period startPeriod = endPeriod.minus(fraPeriod).normalized(); // TODO: check period >0?
    final ZonedDateTime startDate = ScheduleCalculator.getAdjustedDate(spotDate, startPeriod, businessDayConvention, calendar, eom);
    final ZonedDateTime fixingDate = ScheduleCalculator.getAdjustedDate(startDate, -settlementDays, calendar);
    if (marketValues.getDataPoint(strip.getSecurity()) == null) {
      throw new OpenGammaRuntimeException("Could not get market data for " + strip);
    }
    return new FRASecurity(ccy, spec.getRegion(), startDate, endDate, marketValues.getDataPoint(strip.getSecurity()), 1.0d, underlyingIdentifier, fixingDate);
  }

  private FutureSecurity getFuture(final FixedIncomeStripWithIdentifier strip) {
    return (FutureSecurity) _secSource.getSingle(ExternalIdBundle.of(strip.getSecurity()));
  }

  private SwapSecurity getSwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues, final Tenor resetTenor) {
    if (spec.getCurrency().equals(Currency.BRL)) {
      return getBRLSwap(spec, strip, marketValues);
    }
    final ExternalId swapIdentifier = strip.getSecurity();
    final Double rate = marketValues.getDataPoint(swapIdentifier);
    if (rate == null) {
      throw new OpenGammaRuntimeException("No market data for " + swapIdentifier);
    }
    final long months = resetTenor.getPeriod().toTotalMonths();
    final ConventionBundle fixedLegConvention = getFixedLegConvention(spec, strip, swapIdentifier);
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final String counterparty = "";
    Calendar calendar;
    ExternalId floatingRateId;
    FloatingInterestRateLeg iborLeg;
    final ExternalId underlyingId = getUnderlyingId(spec, strip);
    if (underlyingId == null) {
      s_logger.info("Could not get convention for underlying from {}; trying tenor-based convention", strip);
      final ExternalId id = ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_" + months + "M_SWAP");
      ConventionBundle floatingLegConvention = _conventionBundleSource.getConventionBundle(id);
      if (floatingLegConvention == null) {
        floatingLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_" + months + "_SWAP"));
        if (floatingLegConvention == null) {
          throw new OpenGammaRuntimeException("Could not get floating leg convention for swap strip " + strip);
        }
      }
      calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, floatingLegConvention.getSwapFloatingLegRegion());
      floatingRateId = floatingLegConvention.getSwapFloatingLegInitialRate();
      if (floatingRateId == null) {
        throw new OpenGammaRuntimeException("Could not get floating rate id from convention");
      }
      iborLeg = new FloatingInterestRateLeg(floatingLegConvention.getSwapFloatingLegDayCount(), floatingLegConvention.getSwapFloatingLegFrequency(),
          floatingLegConvention.getSwapFloatingLegRegion(), floatingLegConvention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, floatingRateId,
          FloatingRateType.IBOR);
    } else {
      final ConventionBundle underlyingConvention = _conventionBundleSource.getConventionBundle(underlyingId);
      if (underlyingConvention == null || underlyingConvention.getIdentifiers().size() != 1) {
        s_logger.info("Could not get unique convention for underlying from {}; trying tenor-based convention", strip);
        ConventionBundle floatingLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_" + months + "M_SWAP"));
        if (floatingLegConvention == null) {
          floatingLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
              spec.getCurrency().getCode() + "_" + months + "_SWAP"));
          if (floatingLegConvention == null) {
            throw new OpenGammaRuntimeException("Could not get floating leg convention for swap strip " + strip);
          }
        }
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, floatingLegConvention.getSwapFloatingLegRegion());
        floatingRateId = floatingLegConvention.getSwapFloatingLegInitialRate();
        if (floatingRateId == null) {
          throw new OpenGammaRuntimeException("Could not get floating rate id from convention");
        }
        iborLeg = new FloatingInterestRateLeg(floatingLegConvention.getSwapFloatingLegDayCount(), floatingLegConvention.getSwapFloatingLegFrequency(),
            floatingLegConvention.getSwapFloatingLegRegion(), floatingLegConvention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, floatingRateId,
            FloatingRateType.IBOR);
      } else {
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, underlyingConvention.getRegion());
        final ExternalId underlyingTicker = Iterables.getOnlyElement(underlyingConvention.getIdentifiers());
        iborLeg = new FloatingInterestRateLeg(underlyingConvention.getDayCount(), PeriodFrequency.of(underlyingConvention.getPeriod()),
            underlyingConvention.getRegion(), underlyingConvention.getBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, underlyingTicker,
            FloatingRateType.IBOR);
      }
    }
    final ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(curveDate, fixedLegConvention.getSwapFixedLegSettlementDays(), calendar);
    final ZonedDateTime maturityDate = spotDate.plus(strip.getMaturity().getPeriod());
    final FixedInterestRateLeg fixedLeg = new FixedInterestRateLeg(fixedLegConvention.getSwapFixedLegDayCount(), fixedLegConvention.getSwapFixedLegFrequency(),
        fixedLegConvention.getSwapFixedLegRegion(), fixedLegConvention.getSwapFixedLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, rate);
    final SwapSecurity swap = new SwapSecurity(curveDate, spotDate, maturityDate, counterparty, iborLeg, fixedLeg);
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private SwapSecurity getBRLSwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ExternalId swapIdentifier = strip.getSecurity();
    final Double rate = marketValues.getDataPoint(swapIdentifier);
    if (rate == null) {
      throw new OpenGammaRuntimeException("No market data for " + swapIdentifier);
    }
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final ConventionBundle convention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, "BRL_DI_SWAP"));
    final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, convention.getSwapFloatingLegRegion());
    final ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(curveDate, convention.getSwapFixedLegSettlementDays(), calendar);
    final ZonedDateTime maturityDate = spotDate.plus(strip.getMaturity().getPeriod());
    final FixedInterestRateLeg fixedLeg = new FixedInterestRateLeg(convention.getSwapFixedLegDayCount(), convention.getSwapFixedLegFrequency(),
        convention.getSwapFixedLegRegion(), convention.getSwapFixedLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, rate);
    final FloatingInterestRateLeg iborLeg = new FloatingInterestRateLeg(convention.getSwapFloatingLegDayCount(), convention.getSwapFloatingLegFrequency(),
        convention.getSwapFloatingLegRegion(), convention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, convention.getSwapFloatingLegInitialRate(),
        FloatingRateType.OIS); //convention type is wrong but it's ignored in the converter anyway.
    final String counterparty = "";
    final SwapSecurity swap = new SwapSecurity(curveDate, spotDate, maturityDate, counterparty, iborLeg, fixedLeg);
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private SwapSecurity get28DaySwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ExternalId swapIdentifier = strip.getSecurity();
    final Double rate = marketValues.getDataPoint(swapIdentifier);
    if (rate == null) {
      throw new OpenGammaRuntimeException("No market data for " + swapIdentifier);
    }
    final ConventionBundle fixedLegConvention =
        _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_28D_SWAP"));
    if (fixedLegConvention == null) {
      throw new OpenGammaRuntimeException("Could not get fixed leg convention for " + swapIdentifier);
    }
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final String counterparty = "";
    Calendar calendar;
    ExternalId floatingRateId;
    FloatingInterestRateLeg iborLeg;
    final ExternalId underlyingId = getUnderlyingId(spec, strip);
    if (underlyingId == null) {
      s_logger.info("Could not get convention for underlying from {}; trying tenor-based convention", strip);
      final ExternalId id = ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_28D_SWAP");
      final ConventionBundle floatingLegConvention = _conventionBundleSource.getConventionBundle(id);
      if (floatingLegConvention == null) {
        throw new OpenGammaRuntimeException("Could not get floating leg convention for swap strip " + strip);
      }
      calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, floatingLegConvention.getSwapFloatingLegRegion());
      floatingRateId = floatingLegConvention.getSwapFloatingLegInitialRate();
      if (floatingRateId == null) {
        throw new OpenGammaRuntimeException("Could not get floating rate id from convention");
      }
      iborLeg = new FloatingInterestRateLeg(floatingLegConvention.getSwapFloatingLegDayCount(), floatingLegConvention.getSwapFloatingLegFrequency(),
          floatingLegConvention.getSwapFloatingLegRegion(), floatingLegConvention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, floatingRateId,
          FloatingRateType.IBOR);
    } else {
      final ConventionBundle underlyingConvention = _conventionBundleSource.getConventionBundle(underlyingId);
      if (underlyingConvention == null || underlyingConvention.getIdentifiers().size() != 1) {
        s_logger.info("Could not get unique convention for underlying from {}; trying tenor-based convention", strip);
        final ConventionBundle floatingLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_28D_SWAP"));
        if (floatingLegConvention == null) {
          throw new OpenGammaRuntimeException("Could not get floating leg convention for swap strip " + strip);
        }
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, floatingLegConvention.getSwapFloatingLegRegion());
        floatingRateId = floatingLegConvention.getSwapFloatingLegInitialRate();
        if (floatingRateId == null) {
          throw new OpenGammaRuntimeException("Could not get floating rate id from convention");
        }
        iborLeg = new FloatingInterestRateLeg(floatingLegConvention.getSwapFloatingLegDayCount(), floatingLegConvention.getSwapFloatingLegFrequency(),
            floatingLegConvention.getSwapFloatingLegRegion(), floatingLegConvention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, floatingRateId,
            FloatingRateType.IBOR);
      } else {
        calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, underlyingConvention.getRegion());
        final ExternalId underlyingTicker = Iterables.getOnlyElement(underlyingConvention.getIdentifiers());
        iborLeg = new FloatingInterestRateLeg(underlyingConvention.getDayCount(), PeriodFrequency.of(underlyingConvention.getPeriod()),
            underlyingConvention.getRegion(), underlyingConvention.getBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, underlyingTicker,
            FloatingRateType.IBOR);
      }
    }
    final ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(curveDate, fixedLegConvention.getSwapFixedLegSettlementDays(), calendar);
    final ZonedDateTime maturityDate = spotDate.plus(strip.getMaturity().getPeriod());
    final FixedInterestRateLeg fixedLeg = new FixedInterestRateLeg(fixedLegConvention.getSwapFixedLegDayCount(), fixedLegConvention.getSwapFixedLegFrequency(),
        fixedLegConvention.getSwapFixedLegRegion(), fixedLegConvention.getSwapFixedLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, rate);
    final SwapSecurity swap = new SwapSecurity(curveDate, spotDate, maturityDate, counterparty, iborLeg, fixedLeg);
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private SwapSecurity getBasisSwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ExternalId swapIdentifier = strip.getSecurity();
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final FixedIncomeStrip fixedIncomeStrip = strip.getStrip();
    final IndexType payIndexType = fixedIncomeStrip.getPayIndexType();
    final Tenor payTenor = fixedIncomeStrip.getPayTenor();
    final IndexType receiveIndexType = fixedIncomeStrip.getReceiveIndexType();
    final Tenor receiveTenor = fixedIncomeStrip.getReceiveTenor();
    final String ccy = spec.getCurrency().getCode();
    final ExternalId payFloatingReferenceRateId = ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, payIndexType + "_" + ccy + "_" + payTenor.getPeriod().toString());
    final ExternalId receiveFloatingReferenceRateId = ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, receiveIndexType + "_" + ccy + "_" + receiveTenor.getPeriod().toString());
    final ConventionBundle payConvention = _conventionBundleSource.getConventionBundle(payFloatingReferenceRateId);
    final ConventionBundle receiveConvention = _conventionBundleSource.getConventionBundle(receiveFloatingReferenceRateId);
    final Calendar payCalendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, payConvention.getRegion());
    final ZonedDateTime paySpotDate = ScheduleCalculator.getAdjustedDate(curveDate, payConvention.getSettlementDays(), payCalendar);
    final ZonedDateTime payMaturityDate = paySpotDate.plus(strip.getMaturity().getPeriod());
    final String counterparty = "";
    final InterestRateNotional notional = new InterestRateNotional(spec.getCurrency(), 1);
    final ExternalId payRegionIdentifier = payConvention.getRegion();
    final DayCount payDayCount = payConvention.getDayCount();
    final Frequency payFrequency = PeriodFrequency.of(fixedIncomeStrip.getPayTenor().getPeriod());
    final BusinessDayConvention payBusinessDayConvention = payConvention.getBusinessDayConvention();
    final FloatingRateType payFloatingRateType = getFloatingTypeFromIndexType(fixedIncomeStrip.getPayIndexType());
    final ExternalId receiveRegionIdentifier = receiveConvention.getRegion();
    final DayCount receiveDayCount = receiveConvention.getDayCount();
    final Frequency receiveFrequency = PeriodFrequency.of(fixedIncomeStrip.getReceiveTenor().getPeriod());
    final BusinessDayConvention receiveBusinessDayConvention = receiveConvention.getBusinessDayConvention();
    final FloatingRateType receiveFloatingRateType = getFloatingTypeFromIndexType(fixedIncomeStrip.getReceiveIndexType());
    final double spread = marketValues.getDataPoint(swapIdentifier);
    // Implementation note: By convention the spread is on the first leg (shorter tenor)
    final FloatingSpreadIRLeg payLeg = new FloatingSpreadIRLeg(payDayCount, payFrequency, payRegionIdentifier, payBusinessDayConvention, notional, false, payFloatingReferenceRateId,
        payFloatingRateType, spread);
    final FloatingInterestRateLeg receiveLeg = new FloatingInterestRateLeg(receiveDayCount, receiveFrequency, receiveRegionIdentifier, receiveBusinessDayConvention, notional, false,
        receiveFloatingReferenceRateId, receiveFloatingRateType);
    //TODO don't use pay spot date and maturity date automatically
    final SwapSecurity swap = new SwapSecurity(curveDate, paySpotDate, payMaturityDate, counterparty, payLeg, receiveLeg);
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private SwapSecurity getTenorSwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ExternalId swapIdentifier = strip.getSecurity();
    final Double rate = marketValues.getDataPoint(swapIdentifier);
    final LocalDate curveDate = spec.getCurveDate();
    final ZonedDateTime tradeDate = curveDate.atTime(11, 00).atZone(ZoneOffset.UTC);
    final ZonedDateTime effectiveDate = DateUtils.previousWeekDay(curveDate.plusDays(3)).atTime(11, 00).atZone(ZoneOffset.UTC);
    final ZonedDateTime maturityDate = curveDate.plus(strip.getMaturity().getPeriod()).atTime(11, 00).atZone(ZoneOffset.UTC);
    final ConventionBundle convention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_TENOR_SWAP"));
    final String counterparty = "";
    final ConventionBundle payLegFloatRateConvention = _conventionBundleSource.getConventionBundle(convention.getBasisSwapPayFloatingLegInitialRate());
    final ConventionBundle receiveLegFloatRateConvention = _conventionBundleSource.getConventionBundle(convention.getBasisSwapReceiveFloatingLegInitialRate());
    final ExternalId payLegFloatRateBloombergTicker = payLegFloatRateConvention.getIdentifiers().getExternalId(ExternalSchemes.BLOOMBERG_TICKER);
    final ExternalId receiveLegFloatRateBloombergTicker = receiveLegFloatRateConvention.getIdentifiers().getExternalId(ExternalSchemes.BLOOMBERG_TICKER);
    if (rate == null) {
      throw new OpenGammaRuntimeException("Could not get spread; was trying " + swapIdentifier);
    }
    final double spread = rate;
    // REVIEW: jim 25-Aug-2010 -- we need to change the swap to take settlement days.

    final SwapSecurity swap = new SwapSecurity(tradeDate, effectiveDate, maturityDate, counterparty, new FloatingInterestRateLeg(convention.getBasisSwapPayFloatingLegDayCount(),
        convention.getBasisSwapPayFloatingLegFrequency(), convention.getBasisSwapPayFloatingLegRegion(), convention.getBasisSwapPayFloatingLegBusinessDayConvention(), new InterestRateNotional(
            spec.getCurrency(), 1), false, payLegFloatRateBloombergTicker, FloatingRateType.IBOR), new FloatingSpreadIRLeg(convention.getBasisSwapReceiveFloatingLegDayCount(),
                convention.getBasisSwapReceiveFloatingLegFrequency(), convention.getBasisSwapReceiveFloatingLegRegion(), convention.getBasisSwapReceiveFloatingLegBusinessDayConvention(),
                new InterestRateNotional(spec.getCurrency(), 1), false, receiveLegFloatRateBloombergTicker, FloatingRateType.IBOR, spread));
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private SwapSecurity getOISSwap(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final FixedIncomeStrip underlyingStrip = strip.getStrip();
    final ExternalId swapIdentifier = strip.getSecurity();
    final ConventionBundle swapConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_OIS_SWAP"));
    if (swapConvention == null) {
      throw new OpenGammaRuntimeException("Could not get convention for id " + ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, spec.getCurrency().getCode() + "_OIS_SWAP"));
    }
    if (!swapConvention.getSwapFloatingLegFrequency().equals(swapConvention.getSwapFixedLegFrequency())) {
      throw new OpenGammaRuntimeException("Payment frequencies for the fixed and floating legs did not match");
    }
    final Calendar calendar = CalendarUtils.getCalendar(_regionSource, _holidaySource, swapConvention.getSwapFloatingLegRegion());
    final ZonedDateTime curveDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(curveDate, swapConvention.getSwapFixedLegSettlementDays(), calendar);
    final ZonedDateTime maturityDate = spotDate.plus(strip.getMaturity().getPeriod());
    final String counterparty = "";
    final Double rate = marketValues.getDataPoint(swapIdentifier);
    if (rate == null) {
      throw new OpenGammaRuntimeException("rate was null on " + strip + " from " + spec);
    }
    Frequency floatingFrequency;
    final ExternalId floatingReferenceRateId;
    if (underlyingStrip.getResetTenor() != null) {
      final Period resetTenor = underlyingStrip.getResetTenor().getPeriod();
      floatingFrequency = PeriodFrequency.of(resetTenor);
      final IndexType indexType = underlyingStrip.getIndexType();
      floatingReferenceRateId = ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, indexType + "_" + resetTenor.toString());
    } else {
      floatingFrequency = swapConvention.getSwapFloatingLegFrequency();
      if (floatingFrequency == null) {
        throw new OpenGammaRuntimeException("Could not get floating leg frequency from convention");
      }
      floatingReferenceRateId = swapConvention.getSwapFloatingLegInitialRate();
      if (floatingReferenceRateId == null) {
        throw new OpenGammaRuntimeException("Could not get floating reference rate from convention");
      }
    }
    final FloatingInterestRateLeg oisLeg = new FloatingInterestRateLeg(swapConvention.getSwapFloatingLegDayCount(), floatingFrequency,
        swapConvention.getSwapFloatingLegRegion(), swapConvention.getSwapFloatingLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, floatingReferenceRateId,
        FloatingRateType.OIS);
    final FixedInterestRateLeg fixedLeg = new FixedInterestRateLeg(swapConvention.getSwapFixedLegDayCount(), swapConvention.getSwapFixedLegFrequency(), swapConvention.getSwapFixedLegRegion(),
        swapConvention.getSwapFixedLegBusinessDayConvention(), new InterestRateNotional(spec.getCurrency(), 1), false, rate);
    final SwapSecurity swap = new SwapSecurity(curveDate, spotDate, maturityDate, counterparty, oisLeg, fixedLeg);
    swap.setExternalIdBundle(ExternalIdBundle.of(swapIdentifier));
    return swap;
  }

  private static PeriodicZeroDepositSecurity getPeriodicZeroDeposit(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip, final SnapshotDataBundle marketValues) {
    final ExternalId id = strip.getSecurity();
    final Currency currency = spec.getCurrency();
    final ZonedDateTime startDate = spec.getCurveDate().atStartOfDay(ZoneOffset.UTC);
    final ZonedDateTime maturityDate = startDate.plus(strip.getMaturity().getPeriod());
    final double rate = marketValues.getDataPoint(id);
    final int compoundingPeriodsPerYear = strip.getStrip().getPeriodsPerYear();
    final ExternalId region = spec.getRegion();
    final PeriodicZeroDepositSecurity deposit = new PeriodicZeroDepositSecurity(currency, startDate, maturityDate, rate, compoundingPeriodsPerYear, region);
    deposit.setExternalIdBundle(ExternalIdBundle.of(id));
    return deposit;
  }

  private static ZoneId ensureZone(final ZoneId zone) {
    if (zone != null) {
      return zone;
    }
    return ZoneOffset.UTC;
  }

  private static FloatingRateType getFloatingTypeFromIndexType(final IndexType indexType) {
    switch (indexType) {
      case Libor:
        return FloatingRateType.IBOR;
      case Euribor:
        return FloatingRateType.IBOR;
      case BBSW:
        return FloatingRateType.IBOR;
    }
    throw new OpenGammaRuntimeException("Cannot handle index type " + indexType);
  }

  private static ExternalId getUnderlyingId(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip) {
    if (strip.getStrip().getIndexType() == null) {
      return null;
    }
    final String tenorString = strip.getStrip().getResetTenor().getPeriod().toTotalMonths() + "m";
    final String fixingRateName = spec.getCurrency().getCode() + " " + strip.getStrip().getIndexType().name().toUpperCase() + " " + tenorString;
    return ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME, fixingRateName);
  }

  private ConventionBundle getFixedLegConvention(final InterpolatedYieldCurveSpecification spec, final FixedIncomeStripWithIdentifier strip,
      final ExternalId swapIdentifier) {
    ConventionBundle fixedLegConvention;
    switch (strip.getStrip().getInstrumentType()) {
      case SWAP_3M:
        fixedLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_3M_SWAP"));
        if (fixedLegConvention != null) {
          return fixedLegConvention;
        }
      case SWAP_6M:
        fixedLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_6M_SWAP"));
        if (fixedLegConvention != null) {
          return fixedLegConvention;
        }
      case SWAP_12M:
        fixedLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_12M_SWAP"));
        if (fixedLegConvention != null) {
          return fixedLegConvention;
        }
      default:
        fixedLegConvention = _conventionBundleSource.getConventionBundle(ExternalId.of(InMemoryConventionBundleMaster.SIMPLE_NAME_SCHEME,
            spec.getCurrency().getCode() + "_SWAP"));
        if (fixedLegConvention != null) {
          return fixedLegConvention;
        }
    }
    throw new OpenGammaRuntimeException("Could not get fixed leg convention for " + swapIdentifier);
  }

}
TOP

Related Classes of com.opengamma.financial.analytics.ircurve.FixedIncomeStripIdentifierAndMaturityBuilder$InstrumentHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.