public virtual void test_trade() { FraCurveNode node = FraCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); LocalDate valuationDate = LocalDate.of(2015, 1, 22); double rate = 0.035; ImmutableMarketData marketData = ImmutableMarketData.builder(valuationDate).addValue(QUOTE_ID, rate).build(); FraTrade trade = node.trade(1d, marketData, REF_DATA); LocalDate startDateExpected = BDA_MOD_FOLLOW.adjust(OFFSET.adjust(valuationDate, REF_DATA).plus(PERIOD_TO_START), REF_DATA); LocalDate endDateExpected = BDA_MOD_FOLLOW.adjust(OFFSET.adjust(valuationDate, REF_DATA).plus(PERIOD_TO_END), REF_DATA); Fra productExpected = Fra.builder().buySell(BuySell.SELL).currency(GBP).dayCount(ACT_365F).startDate(startDateExpected).endDate(endDateExpected).paymentDate(AdjustableDate.of(startDateExpected)).notional(1.0d).index(GBP_LIBOR_3M).fixedRate(rate + SPREAD).build(); TradeInfo tradeInfoExpected = TradeInfo.builder().tradeDate(valuationDate).build(); assertEquals(trade.Product, productExpected); assertEquals(trade.Info, tradeInfoExpected); }
public virtual void test_volatilities() { BlackFxOptionInterpolatedNodalSurfaceVolatilitiesSpecification @base = BlackFxOptionInterpolatedNodalSurfaceVolatilitiesSpecification.builder().name(VOL_NAME).currencyPair(GBP_USD).dayCount(ACT_365F).nodes(NODES).timeInterpolator(PCHIP).strikeInterpolator(DOUBLE_QUADRATIC).build(); LocalDate date = LocalDate.of(2017, 9, 25); ZonedDateTime dateTime = date.atStartOfDay().atZone(ZoneId.of("Europe/London")); DoubleArray parameters = DoubleArray.of(0.19, 0.15, 0.13, 0.14, 0.14, 0.11, 0.09, 0.09, 0.11, 0.09, 0.07, 0.07); BlackFxOptionSurfaceVolatilities computed = @base.volatilities(dateTime, parameters, REF_DATA); DaysAdjustment expOffset = DaysAdjustment.ofBusinessDays(-2, NY_LO); double[] expiries = new double[STRIKES.Count * TENORS.Count]; double[] strikes = new double[STRIKES.Count * TENORS.Count]; ImmutableList.Builder <ParameterMetadata> paramMetadata = ImmutableList.builder(); for (int i = 0; i < TENORS.Count; ++i) { double expiry = ACT_365F.relativeYearFraction(date, expOffset.adjust(BDA.adjust(SPOT_OFFSET.adjust(date, REF_DATA).plus(TENORS[i]), REF_DATA), REF_DATA)); for (int j = 0; j < STRIKES.Count; ++j) { paramMetadata.add(FxVolatilitySurfaceYearFractionParameterMetadata.of(expiry, SimpleStrike.of(STRIKES[j]), GBP_USD)); expiries[STRIKES.Count * i + j] = expiry; strikes[STRIKES.Count * i + j] = STRIKES[j]; } } InterpolatedNodalSurface surface = InterpolatedNodalSurface.ofUnsorted(Surfaces.blackVolatilityByExpiryStrike(VOL_NAME.Name, ACT_365F).withParameterMetadata(paramMetadata.build()), DoubleArray.ofUnsafe(expiries), DoubleArray.ofUnsafe(strikes), parameters, GridSurfaceInterpolator.of(PCHIP, DOUBLE_QUADRATIC)); BlackFxOptionSurfaceVolatilities expected = BlackFxOptionSurfaceVolatilities.of(VOL_NAME, GBP_USD, dateTime, surface); assertEquals(computed, expected); }
public virtual void test_trade() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); double rate = 0.035; MarketData marketData = ImmutableMarketData.builder(VAL_DATE).addValue(QUOTE_ID, rate).build(); TermDepositTrade trade = node.trade(1d, marketData, REF_DATA); LocalDate startDateExpected = PLUS_TWO_DAYS.adjust(VAL_DATE, REF_DATA); LocalDate endDateExpected = startDateExpected.plus(DEPOSIT_PERIOD); TermDeposit depositExpected = TermDeposit.builder().buySell(BuySell.BUY).currency(EUR).dayCount(ACT_360).startDate(startDateExpected).endDate(endDateExpected).notional(1.0d).businessDayAdjustment(BDA_MOD_FOLLOW).rate(rate + SPREAD).build(); TradeInfo tradeInfoExpected = TradeInfo.builder().tradeDate(VAL_DATE).build(); assertEquals(trade.Product, depositExpected); assertEquals(trade.Info, tradeInfoExpected); }
public virtual void test_resolve() { CapitalIndexedBond @base = sut(); LocalDate[] unAdjDates = new LocalDate[] { LocalDate.of(2008, 1, 13), LocalDate.of(2008, 7, 13), LocalDate.of(2009, 1, 13), LocalDate.of(2009, 7, 13), LocalDate.of(2010, 1, 13) }; CapitalIndexedBondPaymentPeriod[] periodic = new CapitalIndexedBondPaymentPeriod[4]; for (int i = 0; i < 4; ++i) { LocalDate start = SCHEDULE_ADJ.adjust(unAdjDates[i], REF_DATA); LocalDate end = SCHEDULE_ADJ.adjust(unAdjDates[i + 1], REF_DATA); LocalDate detachment = EX_COUPON.adjust(end, REF_DATA); RateComputation comp = RATE_CALC.createRateComputation(end); periodic[i] = CapitalIndexedBondPaymentPeriod.builder().currency(USD).startDate(start).endDate(end).unadjustedStartDate(unAdjDates[i]).unadjustedEndDate(unAdjDates[i + 1]).detachmentDate(detachment).realCoupon(COUPONS[i]).rateComputation(comp).notional(NOTIONAL).build(); } CapitalIndexedBondPaymentPeriod nominalExp = periodic[3].withUnitCoupon(periodic[0].StartDate, periodic[0].UnadjustedStartDate); ResolvedCapitalIndexedBond expected = ResolvedCapitalIndexedBond.builder().securityId(SECURITY_ID).dayCount(ACT_ACT_ISDA).legalEntityId(LEGAL_ENTITY).nominalPayment(nominalExp).periodicPayments(periodic).frequency(SCHEDULE.Frequency).rollConvention(SCHEDULE.calculatedRollConvention()).settlementDateOffset(SETTLE_OFFSET).yieldConvention(US_IL_REAL).rateCalculation(@base.RateCalculation).build(); assertEquals(@base.resolve(REF_DATA), expected); }
public virtual void test_resolve() { CmsLeg baseFloor = CmsLeg.builder().floorSchedule(FLOOR).index(INDEX).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).build(); ResolvedCmsLeg resolvedFloor = baseFloor.resolve(REF_DATA); LocalDate end1 = LocalDate.of(2016, 10, 21); LocalDate fixing1 = EUR_EURIBOR_6M.calculateFixingFromEffective(START, REF_DATA); LocalDate fixing2 = EUR_EURIBOR_6M.calculateFixingFromEffective(end1, REF_DATA); LocalDate fixing3 = EUR_EURIBOR_6M.calculateFixingFromEffective(END, REF_DATA); LocalDate endDate = SCHEDULE_EUR.calculatedEndDate().adjusted(REF_DATA); CmsPeriod period1 = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.InitialValue).notional(-NOTIONAL.InitialValue).index(INDEX).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing1).paymentDate(end1).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing1)).build(); CmsPeriod period2 = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.Steps[0].Value.ModifyingValue).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing2).paymentDate(endDate).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build(); assertEquals(resolvedFloor.Currency, EUR); assertEquals(resolvedFloor.StartDate, baseFloor.StartDate.adjusted(REF_DATA)); assertEquals(resolvedFloor.EndDate, baseFloor.EndDate.adjusted(REF_DATA)); assertEquals(resolvedFloor.Index, INDEX); assertEquals(resolvedFloor.PayReceive, PAY); assertEquals(resolvedFloor.CmsPeriods.size(), 2); assertEquals(resolvedFloor.CmsPeriods.get(0), period1); assertEquals(resolvedFloor.CmsPeriods.get(1), period2); CmsLeg baseFloorEnd = CmsLeg.builder().floorSchedule(FLOOR).fixingRelativeTo(FixingRelativeTo.PERIOD_END).index(INDEX).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).build(); ResolvedCmsLeg resolvedFloorEnd = baseFloorEnd.resolve(REF_DATA); CmsPeriod period1End = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.InitialValue).notional(-NOTIONAL.InitialValue).index(INDEX).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing2).paymentDate(end1).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build(); CmsPeriod period2End = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.Steps[0].Value.ModifyingValue).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing3).paymentDate(endDate).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing3)).build(); assertEquals(resolvedFloorEnd.Currency, EUR); assertEquals(resolvedFloorEnd.StartDate, baseFloor.StartDate.adjusted(REF_DATA)); assertEquals(resolvedFloorEnd.EndDate, baseFloor.EndDate.adjusted(REF_DATA)); assertEquals(resolvedFloorEnd.Index, INDEX); assertEquals(resolvedFloorEnd.PayReceive, PAY); assertEquals(resolvedFloorEnd.CmsPeriods.size(), 2); assertEquals(resolvedFloorEnd.CmsPeriods.get(0), period1End); assertEquals(resolvedFloorEnd.CmsPeriods.get(1), period2End); CmsLeg baseCap = CmsLeg.builder().index(INDEX).capSchedule(CAP).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).paymentDateOffset(PAYMENT_OFFSET).build(); ResolvedCmsLeg resolvedCap = baseCap.resolve(REF_DATA); CmsPeriod periodCap1 = CmsPeriod.builder().currency(EUR).notional(-NOTIONAL.InitialValue).index(INDEX).caplet(CAP.InitialValue).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing1).paymentDate(PAYMENT_OFFSET.adjust(end1, REF_DATA)).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing1)).build(); CmsPeriod periodCap2 = CmsPeriod.builder().currency(EUR).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).caplet(CAP.InitialValue).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing2).paymentDate(PAYMENT_OFFSET.adjust(endDate, REF_DATA)).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build(); assertEquals(resolvedCap.Currency, EUR); assertEquals(resolvedCap.StartDate, baseCap.StartDate.adjusted(REF_DATA)); assertEquals(resolvedCap.EndDate, baseCap.EndDate.adjusted(REF_DATA)); assertEquals(resolvedCap.Index, INDEX); assertEquals(resolvedCap.PayReceive, PAY); assertEquals(resolvedCap.CmsPeriods.size(), 2); assertEquals(resolvedCap.CmsPeriods.get(0), periodCap1); assertEquals(resolvedCap.CmsPeriods.get(1), periodCap2); }
public virtual void test_resolve_cap() { IborRateCalculation rateCalc = IborRateCalculation.builder().index(EUR_EURIBOR_3M).fixingRelativeTo(FixingRelativeTo.PERIOD_END).fixingDateOffset(EUR_EURIBOR_3M.FixingDateOffset).build(); IborCapFloorLeg @base = IborCapFloorLeg.builder().calculation(rateCalc).capSchedule(CAP).notional(NOTIONAL).paymentDateOffset(PAYMENT_OFFSET).paymentSchedule(SCHEDULE).payReceive(RECEIVE).build(); LocalDate[] unadjustedDates = new LocalDate[] { START, START.plusMonths(3), START.plusMonths(6), START.plusMonths(9), START.plusMonths(12) }; IborCapletFloorletPeriod[] periods = new IborCapletFloorletPeriod[4]; for (int i = 0; i < 4; ++i) { LocalDate start = BUSS_ADJ.adjust(unadjustedDates[i], REF_DATA); LocalDate end = BUSS_ADJ.adjust(unadjustedDates[i + 1], REF_DATA); double yearFraction = EUR_EURIBOR_3M.DayCount.relativeYearFraction(start, end); periods[i] = IborCapletFloorletPeriod.builder().caplet(CAP.InitialValue).currency(EUR).startDate(start).endDate(end).unadjustedStartDate(unadjustedDates[i]).unadjustedEndDate(unadjustedDates[i + 1]).paymentDate(PAYMENT_OFFSET.adjust(end, REF_DATA)).notional(NOTIONALS[i]).iborRate(IborRateComputation.of(EUR_EURIBOR_3M, rateCalc.FixingDateOffset.adjust(end, REF_DATA), REF_DATA)).yearFraction(yearFraction).build(); } ResolvedIborCapFloorLeg expected = ResolvedIborCapFloorLeg.builder().capletFloorletPeriods(periods).payReceive(RECEIVE).build(); ResolvedIborCapFloorLeg computed = @base.resolve(REF_DATA); assertEquals(computed, expected); }
static FxOptionVolatilitiesMarketDataFunctionTest() { ImmutableList.Builder <FxOptionVolatilitiesNode> volNodeBuilder = ImmutableList.builder(); ImmutableMap.Builder <QuoteId, double> marketQuoteBuilder = ImmutableMap.builder(); ImmutableMap.Builder <QuoteId, MarketDataBox <double> > scenarioMarketQuoteBuilder = ImmutableMap.builder(); ImmutableList.Builder <FixedOvernightSwapCurveNode> usdNodeBuilder = ImmutableList.builder(); ImmutableList.Builder <FxSwapCurveNode> gbpNodeBuilder = ImmutableList.builder(); for (int i = 0; i < VOL_TENORS.Count; ++i) { for (int j = 0; j < STRIKES.Count; ++j) { QuoteId quoteId = QuoteId.of(StandardId.of("OG", VOL_TENORS[i].ToString() + "_" + STRIKES[j].Label + "_" + VALUE_TYPES[j].ToString())); volNodeBuilder.add(FxOptionVolatilitiesNode.of(GBP_USD, SPOT_OFFSET, BDA, VALUE_TYPES[j], quoteId, VOL_TENORS[i], STRIKES[j])); marketQuoteBuilder.put(quoteId, VOL_QUOTES[i][j]); scenarioMarketQuoteBuilder.put(quoteId, MarketDataBox.ofScenarioValues(VOL_QUOTES[i][j], VOL_QUOTES_1[i][j])); } } for (int i = 0; i < USD_QUOTES.Count; ++i) { QuoteId quoteId = QuoteId.of(StandardId.of("OG", USD.ToString() + "-OIS-" + USD_TENORS[i].ToString())); usdNodeBuilder.add(FixedOvernightSwapCurveNode.of(FixedOvernightSwapTemplate.of(USD_TENORS[i], FixedOvernightSwapConventions.USD_FIXED_TERM_FED_FUND_OIS), quoteId)); marketQuoteBuilder.put(quoteId, USD_QUOTES[i]); scenarioMarketQuoteBuilder.put(quoteId, MarketDataBox.ofScenarioValues(USD_QUOTES[i], USD_QUOTES_1[i])); } for (int i = 0; i < GBP_QUOTES.Count; ++i) { QuoteId quoteId = QuoteId.of(StandardId.of("OG", GBP_USD.ToString() + "-FX-" + GBP_PERIODS[i].ToString())); gbpNodeBuilder.add(FxSwapCurveNode.of(FxSwapTemplate.of(GBP_PERIODS[i], FxSwapConventions.GBP_USD), quoteId)); marketQuoteBuilder.put(quoteId, GBP_QUOTES[i]); scenarioMarketQuoteBuilder.put(quoteId, MarketDataBox.ofScenarioValues(GBP_QUOTES[i], GBP_QUOTES_1[i])); } VOL_NODES = volNodeBuilder.build(); USD_NODES = usdNodeBuilder.build(); GBP_NODES = gbpNodeBuilder.build(); MARKET_QUOTES = marketQuoteBuilder.build(); SCENARIO_MARKET_QUOTES = scenarioMarketQuoteBuilder.build(); IList <double> expiry = VOL_TENORS.Select(t => ACT_365F.relativeYearFraction(VALUATION_DATE, BDA.adjust(SPOT_OFFSET.adjust(VALUATION_DATE, REF_DATA).plus(t), REF_DATA))).ToList(); int nSmiles = expiry.Count; double[] atm = new double[nSmiles]; //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] rr = new double[nSmiles][2]; double[][] rr = RectangularArrays.ReturnRectangularDoubleArray(nSmiles, 2); //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] str = new double[nSmiles][2]; double[][] str = RectangularArrays.ReturnRectangularDoubleArray(nSmiles, 2); for (int i = 0; i < nSmiles; ++i) { atm[i] = VOL_QUOTES[i][0]; rr[i][0] = VOL_QUOTES[i][1]; rr[i][1] = VOL_QUOTES[i][3]; str[i][0] = VOL_QUOTES[i][2]; str[i][1] = VOL_QUOTES[i][4]; } InterpolatedStrikeSmileDeltaTermStructure term = InterpolatedStrikeSmileDeltaTermStructure.of(DoubleArray.copyOf(expiry), DoubleArray.of(0.1, 0.25), DoubleArray.copyOf(atm), DoubleMatrix.copyOf(rr), DoubleMatrix.copyOf(str), ACT_365F, LINEAR, FLAT, FLAT, PCHIP, FLAT, FLAT); EXP_VOLS = BlackFxOptionSmileVolatilities.of(VOL_NAME, GBP_USD, VALUATION_DATE.atTime(VALUATION_TIME).atZone(ZONE), term); for (int i = 0; i < nSmiles; ++i) { atm[i] = VOL_QUOTES_1[i][0]; rr[i][0] = VOL_QUOTES_1[i][1]; rr[i][1] = VOL_QUOTES_1[i][3]; str[i][0] = VOL_QUOTES_1[i][2]; str[i][1] = VOL_QUOTES_1[i][4]; } InterpolatedStrikeSmileDeltaTermStructure term1 = InterpolatedStrikeSmileDeltaTermStructure.of(DoubleArray.copyOf(expiry), DoubleArray.of(0.1, 0.25), DoubleArray.copyOf(atm), DoubleMatrix.copyOf(rr), DoubleMatrix.copyOf(str), ACT_365F, LINEAR, FLAT, FLAT, PCHIP, FLAT, FLAT); EXP_VOLS_1 = BlackFxOptionSmileVolatilities.of(VOL_NAME, GBP_USD, VALUATION_DATE_1.atTime(VALUATION_TIME_1).atZone(ZONE), term1); ImmutableList.Builder <FxOptionVolatilitiesNode> nodeBuilder = ImmutableList.builder(); ImmutableMap.Builder <QuoteId, double> quoteBuilder = ImmutableMap.builder(); for (int i = 0; i < SURFACE_TENORS.Count; ++i) { for (int j = 0; j < SURFACE_STRIKES.Count; ++j) { QuoteId quoteId = QuoteId.of(StandardId.of("OG", GBP_USD.ToString() + "_" + SURFACE_TENORS[i].ToString() + "_" + SURFACE_STRIKES[j])); quoteBuilder.put(quoteId, SURFACE_VOL_QUOTES[i][j]); nodeBuilder.add(FxOptionVolatilitiesNode.of(GBP_USD, SPOT_OFFSET, BDA, ValueType.BLACK_VOLATILITY, quoteId, SURFACE_TENORS[i], SimpleStrike.of(SURFACE_STRIKES[j]))); } } SURFACE_NODES = nodeBuilder.build(); SURFACE_QUOTES = quoteBuilder.build(); IList <double> expiry = new List <double>(); IList <double> strike = new List <double>(); IList <double> vols = new List <double>(); for (int i = 0; i < SURFACE_TENORS.Count; ++i) { for (int j = 0; j < SURFACE_STRIKES.Count; ++j) { double yearFraction = ACT_365F.relativeYearFraction(VALUATION_DATE, BDA.adjust(SPOT_OFFSET.adjust(VALUATION_DATE, REF_DATA).plus(SURFACE_TENORS[i]), REF_DATA)); expiry.Add(yearFraction); strike.Add(SURFACE_STRIKES[j]); vols.Add(SURFACE_VOL_QUOTES[i][j]); } } SurfaceInterpolator interp = GridSurfaceInterpolator.of(LINEAR, PCHIP); InterpolatedNodalSurface surface = InterpolatedNodalSurface.ofUnsorted(Surfaces.blackVolatilityByExpiryStrike(VOL_NAME.Name, ACT_365F), DoubleArray.copyOf(expiry), DoubleArray.copyOf(strike), DoubleArray.copyOf(vols), interp); SURFACE_EXP_VOLS = BlackFxOptionSurfaceVolatilities.of(VOL_NAME, GBP_USD, VALUATION_DATE.atTime(VALUATION_TIME).atZone(ZONE), surface); }