/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.irs;
import static com.opengamma.sesame.config.ConfigBuilder.argument;
import static com.opengamma.sesame.config.ConfigBuilder.arguments;
import static com.opengamma.sesame.config.ConfigBuilder.config;
import static com.opengamma.sesame.config.ConfigBuilder.function;
import static com.opengamma.sesame.config.ConfigBuilder.implementations;
import static com.opengamma.util.result.ResultTestUtils.assertSuccess;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.core.IsNull.notNullValue;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.fudgemsg.FudgeMsg;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetTime;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.opengamma.analytics.financial.instrument.annuity.CompoundingMethod;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.util.amount.ReferenceAmount;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.core.link.ConfigLink;
import com.opengamma.core.position.Counterparty;
import com.opengamma.core.position.Trade;
import com.opengamma.core.position.impl.SimpleCounterparty;
import com.opengamma.core.position.impl.SimpleTrade;
import com.opengamma.engine.marketdata.spec.LiveMarketDataSpecification;
import com.opengamma.financial.analytics.DoubleLabelledMatrix1D;
import com.opengamma.financial.analytics.DoubleLabelledMatrix2D;
import com.opengamma.financial.analytics.model.fixedincome.BucketedCrossSensitivities;
import com.opengamma.financial.analytics.model.fixedincome.BucketedCurveSensitivities;
import com.opengamma.financial.analytics.model.fixedincome.CashFlowFormatter;
import com.opengamma.financial.analytics.model.fixedincome.FixedLegCashFlows;
import com.opengamma.financial.analytics.model.fixedincome.FloatingLegCashFlows;
import com.opengamma.financial.analytics.model.fixedincome.SwapLegCashFlows;
import com.opengamma.financial.convention.businessday.BusinessDayConventions;
import com.opengamma.financial.convention.daycount.DayCounts;
import com.opengamma.financial.convention.frequency.PeriodFrequency;
import com.opengamma.financial.convention.frequency.SimpleFrequency;
import com.opengamma.financial.convention.rolldate.RollConvention;
import com.opengamma.financial.currency.CurrencyMatrix;
import com.opengamma.financial.security.irs.FixedInterestRateSwapLeg;
import com.opengamma.financial.security.irs.FloatingInterestRateSwapLeg;
import com.opengamma.financial.security.irs.InterestRateSwapLeg;
import com.opengamma.financial.security.irs.InterestRateSwapNotional;
import com.opengamma.financial.security.irs.InterestRateSwapSecurity;
import com.opengamma.financial.security.irs.PayReceiveType;
import com.opengamma.financial.security.irs.Rate;
import com.opengamma.financial.security.swap.FloatingRateType;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.service.ServiceContext;
import com.opengamma.service.ThreadLocalServiceContext;
import com.opengamma.service.VersionCorrectionProvider;
import com.opengamma.sesame.CurrencyPairsFn;
import com.opengamma.sesame.CurveDefinitionCurveLabellingFn;
import com.opengamma.sesame.CurveDefinitionFn;
import com.opengamma.sesame.CurveLabellingFn;
import com.opengamma.sesame.CurveSelector;
import com.opengamma.sesame.CurveSelectorMulticurveBundleFn;
import com.opengamma.sesame.DefaultCurrencyPairsFn;
import com.opengamma.sesame.DefaultCurveDefinitionFn;
import com.opengamma.sesame.DefaultFXMatrixFn;
import com.opengamma.sesame.DefaultFixingsFn;
import com.opengamma.sesame.DiscountingMulticurveCombinerFn;
import com.opengamma.sesame.Environment;
import com.opengamma.sesame.FXMatrixFn;
import com.opengamma.sesame.FixingsFn;
import com.opengamma.sesame.MarketExposureSelector;
import com.opengamma.sesame.TestMarketDataFactory;
import com.opengamma.sesame.cache.FunctionCache;
import com.opengamma.sesame.cache.NoOpFunctionCache;
import com.opengamma.sesame.config.FunctionModelConfig;
import com.opengamma.sesame.engine.CalculationArguments;
import com.opengamma.sesame.engine.ComponentMap;
import com.opengamma.sesame.engine.FixedInstantVersionCorrectionProvider;
import com.opengamma.sesame.engine.FunctionRunner;
import com.opengamma.sesame.graph.FunctionModel;
import com.opengamma.sesame.interestrate.InterestRateMockSources;
import com.opengamma.sesame.marketdata.DefaultHistoricalMarketDataFn;
import com.opengamma.sesame.marketdata.DefaultMarketDataFn;
import com.opengamma.sesame.marketdata.HistoricalMarketDataFn;
import com.opengamma.sesame.marketdata.MarketDataFn;
import com.opengamma.sesame.marketdata.MarketDataSource;
import com.opengamma.sesame.marketdata.builders.MarketDataBuilder;
import com.opengamma.sesame.marketdata.builders.MarketDataBuilders;
import com.opengamma.sesame.marketdata.builders.MarketDataEnvironmentFactory;
import com.opengamma.sesame.trade.InterestRateSwapTrade;
import com.opengamma.util.GUIDGenerator;
import com.opengamma.util.fudgemsg.OpenGammaFudgeContext;
import com.opengamma.util.function.Function;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.CurrencyAmount;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.result.Result;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
* Tests pricing of an interest rate swap.
*/
@Test(groups = TestGroup.UNIT)
public class SwapPricingTest {
private static final double STD_TOLERANCE_PV = 1.0E-3;
private static final double STD_TOLERANCE_RATE = 1.0E-8;
private static final double STD_TOLERANCE_PV01 = 1.0E-4;
private static final double STD_TOLERANCE_AMOUNT = 1.0E-3;
private static final double EXPECTED_ON_PV = -9723.264518929138;
private static final double EXPECTED_ON_PAR_RATE = 6.560723881400023E-4;
private static final double EXPECTED_ON_PV01 = 0.0000; //TODO What is the correct PV here
private static final double EXPECTED_ON_PAR_SPREAD = -5.739276118599975E-4;
private static final double EXPECTED_3M_PV = 7170391.798257509;
private static final double EXPECTED_3M_PAY_LEG_PV = -9872297.749650199;
private static final double EXPECTED_3M_RECEIVE_LEG_PV = 1.70426895485912E7;
private static final double EXPECTED_3M_PAR_RATE = 0.025894715668195054;
private static final double EXPECTED_3M_PAR_SPREAD = 0.01089471566819499;
private static final Map<Pair<String, Currency>, DoubleMatrix1D> EXPECTED_3M_BUCKETED_PV01 =
ImmutableMap
.<Pair<String, Currency>, DoubleMatrix1D>builder()
.put(Pairs.of(InterestRateMockSources.USD_OIS_CURVE_NAME, Currency.USD),
new DoubleMatrix1D(-2.006128288990294, -2.0061296821289525, -8.674474462036337E-5, 0.0011745459584018116,
1.4847039748268902, -56.94910798756204, 1.1272953905008014, -86.07354103199485,
-166.96224130769323, -242.22201141057718, -314.1940601301674, -385.90291779006617,
-463.27621838407424, -979.7315579072819, -243.35533454746522, 243.5314116731397,
139.99052668955744))
.put(Pairs.of(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, Currency.USD),
new DoubleMatrix1D(-2604.935862485561, -2632.099517240145, -1176.1264079088776, 27.132459445836727,
-34.13622855060674, -8.299063014960922, -10.516911339441654, 0.5088197267155414,
56648.04062946332, 15520.134985387911, 1.1803422588258187E-10, -2.746886018748557E-10,
1.2282414271537867E-10, 2.5897954580662176E-11, -1.309540899491159E-10))
.build();
private static final Map<String, DoubleMatrix2D> EXPECTED_GAMMA_MATRICES =
ImmutableMap
.<String, DoubleMatrix2D>builder()
.put(InterestRateMockSources.USD_OIS_CURVE_NAME, new DoubleMatrix2D(new Double[][]{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.470280338813609E-4, 1.4077152180252598E-4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.4077165762500955E-4, -0.007456320513703395, -0.0033097195258364083, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0033097164901555514, -0.01355057176372502, 1.615302160847932E-4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.612358005018905E-4, 0.026413837803015486, 0.020029691934678705, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.020028590691415594, 0.1374526014545001, 0.0583700166426599, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.058367602225206795, 0.30006630666088313, 0.10196047788131982, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.10195677781384438, 0.5120836880965158, 0.17673465215992182, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.17672831718735396, 0.7511702746618539, 0.1515385192984715, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.15154896985031666, 0.11752356408755295, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}))
.put(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, new DoubleMatrix2D(new Double[][]{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.08491699237264692, -0.022732929956167935, -0.13483121754825114, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.022733349884301424, 0.1865955676935613, -0.1897421255119145, -0.05941171474568546, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.1348363017704338, -0.1897522333882749, 0.7758628909118473, -0.3919226937150583, -0.0626560432035476, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, -0.05941339259296656, -0.39194367357343435, 1.7776091872775928, -1.1804905211776495, -0.13879084831327201, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, -0.0626576256632805, -1.1805700485050679, 3.753088279853389, -2.2627387903124094, -0.23516786169409754, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, -0.13879608166217805, -2.2629449343800547, 6.434090918292106, -3.8289437281906604, -0.17787922930717467, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, -0.23517950696945192, -3.8293765265464783, 7.782344527318329, -3.550780664610863, -0.10705596312582492, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17788728263378142, -3.5510713120937347, 5.467482300460339, -0.36894027436971666, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.10705980734825135, -0.3689649176836014, 0.8297389947146178, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}))
.build();
private static final double EXPECTED_FIXING_PV = -2434639.5774440686;
private static final double NOTIONAL = 100_000_000;
private static final ZonedDateTime VALUATION_TIME = DateUtils.getUTCDate(2014, 1, 22);
private static final LocalDate MARKET_DATA_DATE = LocalDate.of(2014, 2, 18);
private static final CalculationArguments ARGS =
CalculationArguments.builder()
.valuationTime(VALUATION_TIME)
.marketDataSpecification(LiveMarketDataSpecification.LIVE_SPEC)
.build();
private InterestRateSwapFn _swapFunction;
private InterestRateSwapSecurity _fixedVsOnCompoundedSwapSecurity = createFixedVsOnCompoundedSwap();
private InterestRateSwapSecurity _fixedVsLibor3mSwapSecurity = createFixedVsLibor3mSwap();
private InterestRateSwapSecurity _fixedVsLiborWithFixingSwapSecurity = createFixedVsLiborWithFixingSwap();
private InterestRateSwapSecurity _fixedVsLibor3mZcSwapSecurity = createFixedVsLibor3mZcSwap();
private FunctionRunner _functionRunner;
@BeforeClass
public void setUpClass() throws IOException {
FunctionModelConfig engineFunctionConfig =
config(
arguments(
function(
MarketExposureSelector.class,
argument("exposureFunctions", ConfigLink.resolved(InterestRateMockSources.mockExposureFunctions())))),
implementations(
InterestRateSwapFn.class, DiscountingInterestRateSwapFn.class,
CurrencyPairsFn.class, DefaultCurrencyPairsFn.class,
InterestRateSwapCalculatorFactory.class, DiscountingInterestRateSwapCalculatorFactory.class,
InterestRateSwapCalculator.class, DiscountingInterestRateSwapCalculator.class,
CurveSelector.class, MarketExposureSelector.class,
CurveDefinitionFn.class, DefaultCurveDefinitionFn.class,
FXMatrixFn.class, DefaultFXMatrixFn.class,
CurveLabellingFn.class, CurveDefinitionCurveLabellingFn.class,
MarketDataFn.class, DefaultMarketDataFn.class,
FixingsFn.class, DefaultFixingsFn.class,
InterestRateSwapConverterFn.class, DefaultInterestRateSwapConverterFn.class,
HistoricalMarketDataFn.class, DefaultHistoricalMarketDataFn.class,
FunctionCache.class, NoOpFunctionCache.class,
DiscountingMulticurveCombinerFn.class, CurveSelectorMulticurveBundleFn.class));
ImmutableMap<Class<?>, Object> components = InterestRateMockSources.generateBaseComponents();
VersionCorrectionProvider vcProvider = new FixedInstantVersionCorrectionProvider(Instant.now());
ServiceContext serviceContext = ServiceContext.of(components).with(VersionCorrectionProvider.class, vcProvider);
ThreadLocalServiceContext.init(serviceContext);
ComponentMap componentMap = ComponentMap.of(components);
MarketDataSource marketDataSource = InterestRateMockSources.createMarketDataSource(MARKET_DATA_DATE, true);
TestMarketDataFactory marketDataFactory = new TestMarketDataFactory(marketDataSource);
ConfigLink<CurrencyMatrix> currencyMatrixLink = ConfigLink.resolved(componentMap.getComponent(CurrencyMatrix.class));
List<MarketDataBuilder> builders = MarketDataBuilders.standard(componentMap, "dataSource", currencyMatrixLink);
MarketDataEnvironmentFactory environmentFactory = new MarketDataEnvironmentFactory(marketDataFactory, builders);
_functionRunner = new FunctionRunner(environmentFactory);
_swapFunction = FunctionModel.build(InterestRateSwapFn.class, engineFunctionConfig, componentMap);
}
private InterestRateSwapSecurity createFixedVsLiborWithFixingSwap() {
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, NOTIONAL);
List<InterestRateSwapLeg> legs = new ArrayList<>();
PeriodFrequency freq6m = PeriodFrequency.of(Period.ofMonths(6));
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUsNy = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FixedInterestRateSwapLeg payLeg = new FixedInterestRateSwapLeg();
payLeg.setNotional(notional);
payLeg.setDayCountConvention(DayCounts.THIRTY_U_360);
payLeg.setPaymentDateFrequency(freq6m);
payLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setPaymentDateCalendars(calendarUsNy);
payLeg.setAccrualPeriodFrequency(freq6m);
payLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setAccrualPeriodCalendars(calendarUsNy);
payLeg.setRate(new Rate(0.02));
payLeg.setPayReceiveType(PayReceiveType.PAY);
legs.add(payLeg);
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUsNy);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUsNy);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUsNy);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUsNy);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(InterestRateMockSources.getLiborIndexId());
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setRollConvention(RollConvention.EOM);
legs.add(receiveLeg);
return new InterestRateSwapSecurity(
ExternalIdBundle.of(ExternalId.of("UUID", GUIDGenerator.generate().toString())),
"Fixed vs Libor with fixing",
LocalDate.of(2013, 3, 19), // effective date
LocalDate.of(2015, 3, 18), // maturity date,
legs);
}
private InterestRateSwapSecurity createFixedVsOnCompoundedSwap() {
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, NOTIONAL);
List<InterestRateSwapLeg> legs = new ArrayList<>();
PeriodFrequency freq1y = PeriodFrequency.of(Period.ofYears(1));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FixedInterestRateSwapLeg payLeg = new FixedInterestRateSwapLeg();
payLeg.setNotional(notional);
payLeg.setDayCountConvention(DayCounts.ACT_360);
payLeg.setPaymentDateFrequency(freq1y);
payLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setPaymentDateCalendars(calendarUSNY);
payLeg.setAccrualPeriodFrequency(freq1y);
payLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setAccrualPeriodCalendars(calendarUSNY);
payLeg.setPaymentOffset(2);
payLeg.setRate(new Rate(0.00123));
payLeg.setPayReceiveType(PayReceiveType.PAY);
legs.add(payLeg);
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq1y);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(PeriodFrequency.DAILY);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq1y);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setPaymentOffset(2);
receiveLeg.setFloatingRateType(FloatingRateType.OIS);
receiveLeg.setFloatingReferenceRateId(InterestRateMockSources.getOvernightIndexId());
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setCompoundingMethod(CompoundingMethod.FLAT);
legs.add(receiveLeg);
return new InterestRateSwapSecurity(
ExternalIdBundle.of(ExternalId.of("UUID", GUIDGenerator.generate().toString())),
"Fixed vs ON compounded",
LocalDate.of(2014, 2, 5),
LocalDate.of(2014, 4, 7), // maturity date,
legs);
}
private InterestRateSwapSecurity createFixedVsLibor3mSwap() {
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, NOTIONAL);
PeriodFrequency freq6m = PeriodFrequency.of(Period.ofMonths(6));
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
List<InterestRateSwapLeg> legs = new ArrayList<>();
FixedInterestRateSwapLeg payLeg = new FixedInterestRateSwapLeg();
payLeg.setNotional(notional);
payLeg.setDayCountConvention(DayCounts.THIRTY_U_360);
payLeg.setPaymentDateFrequency(freq6m);
payLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setPaymentDateCalendars(calendarUSNY);
payLeg.setAccrualPeriodFrequency(freq6m);
payLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setAccrualPeriodCalendars(calendarUSNY);
payLeg.setMaturityDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setMaturityDateCalendars(calendarUSNY);
payLeg.setRate(new Rate(0.0150));
payLeg.setPayReceiveType(PayReceiveType.PAY);
legs.add(payLeg);
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setMaturityDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setMaturityDateCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(InterestRateMockSources.getLiborIndexId());
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
legs.add(receiveLeg);
return new InterestRateSwapSecurity(
ExternalIdBundle.of(ExternalId.of("UUID", GUIDGenerator.generate().toString())),
"Fixed vs Libor 3m",
LocalDate.of(2014, 9, 12), // effective date
LocalDate.of(2021, 9, 12), // maturity date,
legs);
}
private InterestRateSwapSecurity createFixedVsLibor3mZcSwap() {
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, NOTIONAL);
PeriodFrequency freq6m = PeriodFrequency.of(Period.ofMonths(6));
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
List<InterestRateSwapLeg> legs = new ArrayList<>();
FixedInterestRateSwapLeg payLeg = new FixedInterestRateSwapLeg();
payLeg.setNotional(notional);
payLeg.setDayCountConvention(DayCounts.THIRTY_U_360);
payLeg.setPaymentDateFrequency(freq6m);
payLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setPaymentDateCalendars(calendarUSNY);
payLeg.setAccrualPeriodFrequency(SimpleFrequency.NEVER);
payLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
payLeg.setAccrualPeriodCalendars(calendarUSNY);
payLeg.setRate(new Rate(0.0150));
payLeg.setPayReceiveType(PayReceiveType.PAY);
legs.add(payLeg);
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(SimpleFrequency.NEVER);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(InterestRateMockSources.getLiborIndexId());
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
legs.add(receiveLeg);
return new InterestRateSwapSecurity(
ExternalIdBundle.of(ExternalId.of("UUID", GUIDGenerator.generate().toString())),
"Fixed vs Libor 3m zc",
LocalDate.of(2013, 1, 1), // effective date
LocalDate.of(2021, 9, 12), // maturity date,
legs);
}
private InterestRateSwapTrade wrapInTrade(InterestRateSwapSecurity security) {
Trade trade = new SimpleTrade(security,
BigDecimal.ONE,
new SimpleCounterparty(ExternalId.of(Counterparty.DEFAULT_SCHEME, "CPARTY")),
LocalDate.now(),
OffsetTime.now());
return new InterestRateSwapTrade(trade);
}
@Test
public void fixedVsLiborSwapWithFixingLegDetails() {
Result<SwapLegCashFlows> payFullResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateFullPayLegCashFlows(
env,
_fixedVsLiborWithFixingSwapSecurity);
}
});
Result<SwapLegCashFlows> receiveFullResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateFullReceiveLegCashFlows(
env,
_fixedVsLiborWithFixingSwapSecurity);
}
});
Result<SwapLegCashFlows> payResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculatePayLegCashFlows(
env,
_fixedVsLiborWithFixingSwapSecurity);
}
});
Result<SwapLegCashFlows> receiveResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateReceiveLegCashFlows(
env,
_fixedVsLiborWithFixingSwapSecurity);
}
});
assertSuccess(receiveResult);
assertSuccess(payResult);
assertSuccess(receiveFullResult);
assertSuccess(payFullResult);
assertThat(payResult.getValue(), is((instanceOf(FixedLegCashFlows.class))));
assertThat(payFullResult.getValue(), is((instanceOf(FixedLegCashFlows.class))));
assertThat(receiveResult.getValue(), is((instanceOf(FloatingLegCashFlows.class))));
assertThat(receiveFullResult.getValue(), is((instanceOf(FloatingLegCashFlows.class))));
FixedLegCashFlows pay = (FixedLegCashFlows) payResult.getValue();
FixedLegCashFlows payFull = (FixedLegCashFlows) payFullResult.getValue();
FloatingLegCashFlows receive = (FloatingLegCashFlows) receiveResult.getValue();
FloatingLegCashFlows receiveFull = (FloatingLegCashFlows) receiveFullResult.getValue();
assertThat(pay.getNotionals().size(), is(3));
assertThat(payFull.getNotionals().size(), is(4));
assertThat(receive.getNotionals().size(), is(5));
assertThat(receiveFull.getNotionals().size(), is(8));
List flows = ImmutableList.of(payResult.getValue(),
receiveResult.getValue(),
payFullResult.getValue(),
receiveFullResult.getValue());
CashFlowFormatter.asciiFormatter().formatSwapCashflows(flows);
CashFlowFormatter.csvFormatter().formatSwapCashflows(flows);
}
@Test
public void fixedVsLibor3mSwapLegDetails() {
Result<SwapLegCashFlows> payResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculatePayLegCashFlows(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(payResult);
SwapLegCashFlows payDetails = payResult.getValue();
assertThat(payDetails, is((instanceOf(FixedLegCashFlows.class))));
FixedLegCashFlows fixedLegCashFlows = (FixedLegCashFlows) payDetails;
FudgeMsg fixedFudge = OpenGammaFudgeContext.getInstance().toFudgeMsg(fixedLegCashFlows).getMessage();
OpenGammaFudgeContext.getInstance().fromFudgeMsg(fixedFudge);
List<CurrencyAmount> actualPaymentAmounts = fixedLegCashFlows.getPaymentAmounts();
List<CurrencyAmount> expectedPaymentAmounts =
Lists.newArrayList(
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -758333.3333333333),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -741666.6666666667),
CurrencyAmount.of("USD", -754166.6666666666),
CurrencyAmount.of("USD", -745833.3333333334),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -750000.0),
CurrencyAmount.of("USD", -758333.3333333333),
CurrencyAmount.of("USD", -741666.6666666667),
CurrencyAmount.of("USD", -754166.6666666666));
int i = 0;
for (CurrencyAmount amount : expectedPaymentAmounts) {
assertThat(amount.getAmount(), is(closeTo(actualPaymentAmounts.get(i).getAmount(), STD_TOLERANCE_AMOUNT)));
i++;
}
List<LocalDate> actualAccrualStart = fixedLegCashFlows.getAccrualStart();
List<LocalDate> expectedAccrualStart =
Lists.newArrayList(
LocalDate.of(2014, 9, 12),
LocalDate.of(2015, 3, 12),
LocalDate.of(2015, 9, 14),
LocalDate.of(2016, 3, 14),
LocalDate.of(2016, 9, 12),
LocalDate.of(2017, 3, 13),
LocalDate.of(2017, 9, 12),
LocalDate.of(2018, 3, 12),
LocalDate.of(2018, 9, 12),
LocalDate.of(2019, 3, 12),
LocalDate.of(2019, 9, 12),
LocalDate.of(2020, 3, 12),
LocalDate.of(2020, 9, 14),
LocalDate.of(2021, 3, 12));
i = 0;
for (LocalDate date : expectedAccrualStart) {
assertThat(date, is(actualAccrualStart.get(i)));
i++;
}
Result<SwapLegCashFlows> receiveResult = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateReceiveLegCashFlows(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(receiveResult);
SwapLegCashFlows receiveDetails = receiveResult.getValue();
assertThat(receiveDetails, is((instanceOf(FloatingLegCashFlows.class))));
FloatingLegCashFlows floatingLegCashFlows = (FloatingLegCashFlows) receiveDetails;
FudgeMsg floatingFudge = OpenGammaFudgeContext.getInstance().toFudgeMsg(floatingLegCashFlows).getMessage();
OpenGammaFudgeContext.getInstance().fromFudgeMsg(floatingFudge);
List<Double> expectedForwardRates = floatingLegCashFlows.getForwardRates();
List<Double> actualForwardRates = Lists.newArrayList(
0.002830776043127479, 0.003889725581109005, 0.00534820864384384, 0.006272357544524368, 0.007191464409902153,
0.01010956533411408, 0.013521579956778747, 0.015318507913146722, 0.01710597237713002, 0.019924700484298726,
0.02285929744200523, 0.024965464562180496, 0.027083323913778736, 0.028774171062606158, 0.03044395193791545,
0.03248279019018542, 0.03450994398725367, 0.03441329882138877, 0.0342129941075707, 0.03585838813458806,
0.03749357371138418, 0.03903671874199058, 0.04064520492792625, 0.04230705788571235, 0.04394811214893466,
0.04127235310120026, 0.038531753356691775, 0.03959796966266573);
i = 0;
for (Double rate : expectedForwardRates) {
assertThat(rate, is(closeTo(actualForwardRates.get(i), STD_TOLERANCE_RATE)));
i++;
}
List<LocalDate> actualAccrualEnd = floatingLegCashFlows.getAccrualEnd();
List<LocalDate> expectedAccrualEnd =
Lists.newArrayList(
LocalDate.of(2014, 12, 12),
LocalDate.of(2015, 3, 12),
LocalDate.of(2015, 6, 12),
LocalDate.of(2015, 9, 14),
LocalDate.of(2015, 12, 14),
LocalDate.of(2016, 3, 14),
LocalDate.of(2016, 6, 13),
LocalDate.of(2016, 9, 12),
LocalDate.of(2016, 12, 12),
LocalDate.of(2017, 3, 13),
LocalDate.of(2017, 6, 12),
LocalDate.of(2017, 9, 12),
LocalDate.of(2017, 12, 12),
LocalDate.of(2018, 3, 12),
LocalDate.of(2018, 6, 12),
LocalDate.of(2018, 9, 12),
LocalDate.of(2018, 12, 12),
LocalDate.of(2019, 3, 12),
LocalDate.of(2019, 6, 12),
LocalDate.of(2019, 9, 12),
LocalDate.of(2019, 12, 12),
LocalDate.of(2020, 3, 12),
LocalDate.of(2020, 6, 12),
LocalDate.of(2020, 9, 14),
LocalDate.of(2020, 12, 14),
LocalDate.of(2021, 3, 12),
LocalDate.of(2021, 6, 14),
LocalDate.of(2021, 9, 13));
i = 0;
for (LocalDate date : expectedAccrualEnd) {
assertThat(date, is(actualAccrualEnd.get(i)));
i++;
}
}
public void fixedVsOnCompoundedSwapLegDetails() {
Result<SwapLegCashFlows> payResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculatePayLegCashFlows(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertSuccess(payResult);
SwapLegCashFlows payDetails = payResult.getValue();
assertThat(payDetails, is((instanceOf(FixedLegCashFlows.class))));
Result<SwapLegCashFlows> receiveResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateReceiveLegCashFlows(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertSuccess(receiveResult);
SwapLegCashFlows receiveDetails = receiveResult.getValue();
assertThat(receiveDetails, is((instanceOf(FloatingLegCashFlows.class))));
}
public void fixedVsLiborWithFixingSwapLegDetails() {
Result<SwapLegCashFlows> payResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculatePayLegCashFlows(env, _fixedVsLiborWithFixingSwapSecurity);
}
});
assertSuccess(payResult);
SwapLegCashFlows payDetails = payResult.getValue();
assertThat(payDetails, is((instanceOf(FixedLegCashFlows.class))));
Result<SwapLegCashFlows> receiveResult = _functionRunner.runFunction(ARGS, new Function<Environment, Result<SwapLegCashFlows>>() {
@Override
public Result<SwapLegCashFlows> apply(Environment env) {
return _swapFunction.calculateReceiveLegCashFlows(env, _fixedVsLiborWithFixingSwapSecurity);
}
});
assertSuccess(receiveResult);
SwapLegCashFlows receiveDetails = receiveResult.getValue();
assertThat(receiveDetails, is((instanceOf(FloatingLegCashFlows.class))));
}
@Test
public void fixedVsOnCompoundedSwapPv() {
Result<MultipleCurrencyAmount> resultPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePV(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertSuccess(resultPv);
MultipleCurrencyAmount mca = resultPv.getValue();
assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_ON_PV, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mSwapPv() {
Result<MultipleCurrencyAmount> resultPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePV(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(resultPv);
MultipleCurrencyAmount mca = resultPv.getValue();
assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_3M_PV, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mSwapSecurityLegPv() {
Result<MultipleCurrencyAmount> payLegPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePayLegPv(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(payLegPv);
double payLeg = payLegPv.getValue().getCurrencyAmount(Currency.USD).getAmount();
assertThat(payLeg, is(closeTo(EXPECTED_3M_PAY_LEG_PV, STD_TOLERANCE_PV)));
Result<MultipleCurrencyAmount> recLegPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculateReceiveLegPv(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(recLegPv);
double recLeg = recLegPv.getValue().getCurrencyAmount(Currency.USD).getAmount();
assertThat(recLeg, is(closeTo(EXPECTED_3M_RECEIVE_LEG_PV, STD_TOLERANCE_PV)));
assertThat(payLeg + recLeg, is(closeTo(EXPECTED_3M_PV, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mSwapTradeLegPv() {
Result<MultipleCurrencyAmount> payLegPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePayLegPv(env, wrapInTrade(_fixedVsLibor3mSwapSecurity));
}
});
assertSuccess(payLegPv);
double payLeg = payLegPv.getValue().getCurrencyAmount(Currency.USD).getAmount();
assertThat(payLeg, is(closeTo(EXPECTED_3M_PAY_LEG_PV, STD_TOLERANCE_PV)));
Result<MultipleCurrencyAmount> recLegPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculateReceiveLegPv(env, wrapInTrade(_fixedVsLibor3mSwapSecurity));
}
});
assertSuccess(recLegPv);
double recLeg = recLegPv.getValue().getCurrencyAmount(Currency.USD).getAmount();
assertThat(recLeg, is(closeTo(EXPECTED_3M_RECEIVE_LEG_PV, STD_TOLERANCE_PV)));
assertThat(payLeg + recLeg, is(closeTo(EXPECTED_3M_PV, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mZcSwapPv() {
Result<MultipleCurrencyAmount> resultPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePV(env, _fixedVsLibor3mZcSwapSecurity);
}
});
assertSuccess(resultPv);
MultipleCurrencyAmount mca = resultPv.getValue();
assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(-3444569.0628772983, STD_TOLERANCE_PV)));
}
//TODO when converting a swap to derivative and then getting the par rate via the ParRateDiscounting Calculator,
//par rate is not available as the converted swap is not of type SwapFixedCoupon
@Test
public void fixedVsOnCompoundedSwapParRate() {
Result<Double> resultParRate = _functionRunner.runFunction(ARGS, new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _swapFunction.calculateParRate(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertSuccess(resultParRate);
Double parRate = resultParRate.getValue();
assertThat(parRate, is(closeTo(EXPECTED_ON_PAR_RATE, STD_TOLERANCE_RATE)));
}
@Test
public void fixedVsOnCompoundedSwapParSpreadMarketQuote() {
Result<Double> resultParRate = _functionRunner.runFunction(ARGS, new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _swapFunction.calculateParSpread(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertSuccess(resultParRate);
Double parRate = resultParRate.getValue();
assertThat(parRate, is(closeTo(EXPECTED_ON_PAR_SPREAD, STD_TOLERANCE_RATE)));
}
@Test
public void fixedVsLibor3mWithFixingSwapPv() {
// the number in this test has not been validated from first principles
Result<MultipleCurrencyAmount> resultPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePV(env, _fixedVsLiborWithFixingSwapSecurity);
}
});
assertSuccess(resultPv);
MultipleCurrencyAmount mca = resultPv.getValue();
assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_FIXING_PV, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mForwardStarting() { // check swaps starting far in the future price
// the number in this test has not been validated from first principles
final InterestRateSwapSecurity swap = _fixedVsLibor3mSwapSecurity.clone();
swap.setEffectiveDate(VALUATION_TIME.toLocalDate().plusYears(10));
swap.setUnadjustedMaturityDate(VALUATION_TIME.toLocalDate().plusYears(20));
Result<MultipleCurrencyAmount> resultPv = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _swapFunction.calculatePV(env, swap);
}
});
assertSuccess(resultPv);
MultipleCurrencyAmount mca = resultPv.getValue();
assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(2.0014489075151995E7, STD_TOLERANCE_PV)));
}
@Test
public void fixedVsLibor3mSwapParRate() {
Result<Double> resultParRate = _functionRunner.runFunction(ARGS, new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _swapFunction.calculateParRate(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(resultParRate);
Double parRate = resultParRate.getValue();
assertThat(parRate, is(closeTo(EXPECTED_3M_PAR_RATE, STD_TOLERANCE_RATE)));
}
@Test
public void fixedVsLibor3mSwapParSpreadMarketQuote() {
Result<Double> resultParRate = _functionRunner.runFunction(ARGS, new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _swapFunction.calculateParSpread(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(resultParRate);
Double parRate = resultParRate.getValue();
assertThat(parRate, is(closeTo(EXPECTED_3M_PAR_SPREAD, STD_TOLERANCE_RATE)));
}
//TODO enable test when PV01 expected is available
@Test(enabled = false)
public void interestRateSwapPv01() {
Result<ReferenceAmount<Pair<String,Currency>>> resultPv01 = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<ReferenceAmount<Pair<String, Currency>>>>() {
@Override
public Result<ReferenceAmount<Pair<String, Currency>>> apply(Environment env) {
return _swapFunction.calculatePV01(env, _fixedVsOnCompoundedSwapSecurity);
}
});
assertThat(resultPv01.isSuccess(), is(true));
ReferenceAmount<Pair<String,Currency>> pv01s = resultPv01.getValue();
double pv01 = 0;
for (final Map.Entry<Pair<String, Currency>, Double> entry : pv01s.getMap().entrySet()) {
if (entry.getKey().getSecond().equals(Currency.USD)) {
pv01 += entry.getValue();
}
}
assertThat(pv01, is(closeTo(EXPECTED_ON_PV01, STD_TOLERANCE_PV01)));
}
@Test
public void interestRateSwapBucketedPv01() {
Result<BucketedCurveSensitivities> resultPv01 = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<BucketedCurveSensitivities>>() {
@Override
public Result<BucketedCurveSensitivities> apply(Environment env) {
return _swapFunction.calculateBucketedPV01(env, _fixedVsLibor3mSwapSecurity);
}
});
assertSuccess(resultPv01);
Map<Pair<String, Currency>, DoubleLabelledMatrix1D> pv01s = resultPv01.getValue().getSensitivities();
assertThat(pv01s.size(), is(EXPECTED_3M_BUCKETED_PV01.size()));
for (Map.Entry<Pair<String, Currency>, DoubleLabelledMatrix1D> sensitivity : pv01s.entrySet()) {
DoubleMatrix1D expectedSensitivities = EXPECTED_3M_BUCKETED_PV01.get(sensitivity.getKey());
assertThat(sensitivity.getKey() + " not an expected sensitivity", expectedSensitivities, is(notNullValue()));
assertThat(sensitivity.getValue().size(), is(expectedSensitivities.getNumberOfElements()));
for (int i = 0; i < expectedSensitivities.getNumberOfElements(); i++) {
assertThat(sensitivity.getValue().getValues()[i], is(closeTo(expectedSensitivities.getEntry(i), STD_TOLERANCE_PV01)));
}
}
}
@Test
public void interestRateSwapBucketedGamma() {
Result<BucketedCrossSensitivities> resultCrossGamma = _functionRunner.runFunction(
ARGS, new Function<Environment, Result<BucketedCrossSensitivities>>() {
@Override
public Result<BucketedCrossSensitivities> apply(Environment env) {
return _swapFunction.calculateBucketedCrossGamma(env, _fixedVsLibor3mSwapSecurity);
}
});
assertThat(resultCrossGamma.isSuccess(), is(true));
Map<String, DoubleLabelledMatrix2D> bucketedGamma = resultCrossGamma.getValue().getCrossSensitivities();
assertThat(bucketedGamma.size(), is(EXPECTED_GAMMA_MATRICES.size()));
for (Map.Entry<String, DoubleLabelledMatrix2D> sensitivity : bucketedGamma.entrySet()) {
DoubleMatrix2D expectedSensitivities = new DoubleMatrix2D(EXPECTED_GAMMA_MATRICES.get(sensitivity.getKey()).getData());
assertThat(sensitivity.getValue().getXKeys().length, is(expectedSensitivities.getNumberOfColumns()));
assertThat(sensitivity.getValue().getYKeys().length, is(expectedSensitivities.getNumberOfRows()));
for (int i = 0; i < expectedSensitivities.getNumberOfColumns(); i++) {
for (int j = 0; j < expectedSensitivities.getNumberOfRows(); j++) {
assertThat(expectedSensitivities.getData()[i][j], is(closeTo(sensitivity.getValue().getValues()[i][j], STD_TOLERANCE_PV01)));
}
}
}
}
}