public static YieldCurveBundle createCurvesUSD() { final String discountingCurvename = "USD Discounting"; final String forward3MCurveName = "Forward USDLIBOR3M"; final String forward6MCurveName = "Forward USDLIBOR6M"; final InterpolatedDoublesCurve dscC = new InterpolatedDoublesCurve( new double[] {0.05, 1.0, 2.0, 5.0, 10.0, 20.0}, new double[] {0.0050, 0.0100, 0.0150, 0.0200, 0.0200, 0.0300}, CombinedInterpolatorExtrapolatorFactory.getInterpolator( Interpolator1DFactory.DOUBLE_QUADRATIC, Interpolator1DFactory.LINEAR_EXTRAPOLATOR), true, discountingCurvename); final InterpolatedDoublesCurve fwd3C = new InterpolatedDoublesCurve( new double[] {0.05, 1.0, 2.0, 5.0, 10.0, 25.0}, new double[] {0.0070, 0.0120, 0.0165, 0.0215, 0.0210, 0.0310}, CombinedInterpolatorExtrapolatorFactory.getInterpolator( Interpolator1DFactory.DOUBLE_QUADRATIC, Interpolator1DFactory.LINEAR_EXTRAPOLATOR), true, forward3MCurveName); final InterpolatedDoublesCurve fwd6C = new InterpolatedDoublesCurve( new double[] {0.05, 1.0, 2.0, 5.0, 10.0, 30.0}, new double[] {0.0075, 0.0125, 0.0170, 0.0220, 0.0212, 0.0312}, CombinedInterpolatorExtrapolatorFactory.getInterpolator( Interpolator1DFactory.DOUBLE_QUADRATIC, Interpolator1DFactory.LINEAR_EXTRAPOLATOR), true, forward6MCurveName); final YieldCurveBundle curves = new YieldCurveBundle(); curves.setCurve(discountingCurvename, YieldCurve.from(dscC)); curves.setCurve(forward3MCurveName, YieldCurve.from(fwd3C)); curves.setCurve(forward6MCurveName, YieldCurve.from(fwd6C)); return curves; }
// TODO: review @Override public Double visitForexForward(final ForexForward fx, final YieldCurveBundle curves) { // TODO this is not a par rate, it is a forward FX rate final YieldAndDiscountCurve curve1 = curves.getCurve(fx.getPaymentCurrency1().getFundingCurveName()); final YieldAndDiscountCurve curve2 = curves.getCurve(fx.getPaymentCurrency2().getFundingCurveName()); final double t = fx.getPaymentTime(); return fx.getSpotForexRate() * curve2.getDiscountFactor(t) / curve1.getDiscountFactor(t); }
@Override public DoubleMatrix2D evaluate(final DoubleMatrix1D x) { YieldCurveBundle curves = _curveBuilderFunction.evaluate(x); final YieldCurveBundle knownCurves = _data.getKnownCurves(); // set any known (i.e. fixed) curves if (knownCurves != null) { curves.addAll(knownCurves); } final int totalNodes = _data.getTotalNodes(); final List<String> curveNames = _data.getCurveNames(); final double[][] res = new double[_data.getNumInstruments()][totalNodes]; for (int i = 0; i < _data.getNumInstruments(); i++) { // loop over all instruments InstrumentDerivative deriv = _data.getDerivative(i); final Map<String, List<DoublesPair>> senseMap = _calculator.visit(deriv, curves).getSensitivities(); int offset = 0; for (final String name : curveNames) { // loop over all curves (by name) if (senseMap.containsKey(name)) { final Curve<Double, Double> curve = curves.getCurve(name).getCurve(); if (!(curve instanceof InterpolatedDoublesCurve)) { throw new IllegalArgumentException("Can only handle InterpolatedDoublesCurve"); } final InterpolatedDoublesCurve interpolatedCurve = (InterpolatedDoublesCurve) curve; final Interpolator1DDataBundle data = interpolatedCurve.getDataBundle(); final Interpolator1D sensitivityCalculator = _data.getInterpolatorForCurve(name); final List<DoublesPair> senseList = senseMap.get(name); if (senseList.size() != 0) { final double[][] sensitivity = new double[senseList.size()][]; int k = 0; for (final DoublesPair timeAndDF : senseList) { sensitivity[k++] = sensitivityCalculator.getNodeSensitivitiesForValue( data, timeAndDF.getFirst(), _data.useFiniteDifferenceForNodeSensitivities()); } for (int j = 0; j < sensitivity[0].length; j++) { double temp = 0.0; k = 0; for (final DoublesPair timeAndDF : senseList) { temp += timeAndDF.getSecond() * sensitivity[k++][j]; } res[i][j + offset] = temp; } } } offset += _data.getCurveNodePointsForCurve(name).length; } } return new DoubleMatrix2D(res); }
@Override public Map<String, List<DoublesPair>> visitCouponIborSpread( final CouponIborSpread payment, final YieldCurveBundle data) { final String fundingCurveName = payment.getFundingCurveName(); final String liborCurveName = payment.getForwardCurveName(); final YieldAndDiscountCurve fundCurve = data.getCurve(fundingCurveName); final YieldAndDiscountCurve liborCurve = data.getCurve(liborCurveName); final double tPay = payment.getPaymentTime(); final double tStart = payment.getFixingPeriodStartTime(); final double tEnd = payment.getFixingPeriodEndTime(); final double dfPay = fundCurve.getDiscountFactor(tPay); final double dfStart = liborCurve.getDiscountFactor(tStart); final double dfEnd = liborCurve.getDiscountFactor(tEnd); final double forward = (dfStart / dfEnd - 1) / payment.getFixingYearFraction(); final double notional = payment.getNotional(); final Map<String, List<DoublesPair>> result = new HashMap<String, List<DoublesPair>>(); List<DoublesPair> temp = new ArrayList<DoublesPair>(); DoublesPair s; s = new DoublesPair( tPay, -tPay * dfPay * notional * (forward + payment.getSpread()) * payment.getPaymentYearFraction()); temp.add(s); if (!liborCurveName.equals(fundingCurveName)) { result.put(fundingCurveName, temp); temp = new ArrayList<DoublesPair>(); } final double ratio = notional * dfPay * dfStart / dfEnd * payment.getPaymentYearFraction() / payment.getFixingYearFraction(); s = new DoublesPair(tStart, -tStart * ratio); temp.add(s); s = new DoublesPair(tEnd, tEnd * ratio); temp.add(s); result.put(liborCurveName, temp); return result; }
/** * Create a yield curve bundle with three curves. One called "Credit" with a constant rate of 5%, * one called "Discounting" with a constant rate of 4%, and one called "Forward" with a constant * rate of 4.5%. * * @return The yield curve bundle. */ public static YieldCurveBundle createCurvesBond() { final String CREDIT_CURVE_NAME = "Credit"; final String DISCOUNTING_CURVE_NAME = "Repo"; final String FORWARD_CURVE_NAME = "Forward"; final YieldAndDiscountCurve CURVE_5 = YieldCurve.from(ConstantDoublesCurve.from(0.05)); final YieldAndDiscountCurve CURVE_4 = YieldCurve.from(ConstantDoublesCurve.from(0.04)); final YieldAndDiscountCurve CURVE_45 = YieldCurve.from(ConstantDoublesCurve.from(0.045)); final YieldCurveBundle curves = new YieldCurveBundle(); curves.setCurve(CREDIT_CURVE_NAME, CURVE_5); curves.setCurve(DISCOUNTING_CURVE_NAME, CURVE_4); curves.setCurve(FORWARD_CURVE_NAME, CURVE_45); return curves; }
@Override public Double visitCouponIborSpread(final CouponIborSpread payment, final YieldCurveBundle data) { final YieldAndDiscountCurve curve = data.getCurve(payment.getForwardCurveName()); return (curve.getDiscountFactor(payment.getFixingPeriodStartTime()) / curve.getDiscountFactor(payment.getFixingPeriodEndTime()) - 1.0) / payment.getFixingAccrualFactor(); }
/** * For swaps the ParSpread is the spread to be added on each coupon of the first leg to obtain a * present value of zero. It is computed as the opposite of the present value of the swap divided * by the present value of a basis point of the first leg (as computed by the * PresentValueBasisPointCalculator). * * @param swap The swap. * @param curves The yield curve bundle. * @return The par spread. */ @Override public Double visitSwap(final Swap<?, ?> swap, final YieldCurveBundle curves) { Validate.notNull(curves); Validate.notNull(swap); return -curves .getFxRates() .convert(swap.accept(PVMCC, curves), swap.getFirstLeg().getCurrency()) .getAmount() / swap.getFirstLeg().accept(PVBPC, curves); }
@Override public Map<String, List<DoublesPair>> visitFixedPayment( final PaymentFixed payment, final YieldCurveBundle data) { final String curveName = payment.getFundingCurveName(); final YieldAndDiscountCurve curve = data.getCurve(curveName); final double t = payment.getPaymentTime(); final DoublesPair s = new DoublesPair(t, -t * payment.getAmount() * curve.getDiscountFactor(t)); final List<DoublesPair> list = new ArrayList<DoublesPair>(); list.add(s); final Map<String, List<DoublesPair>> result = new HashMap<String, List<DoublesPair>>(); result.put(curveName, list); return result; }
// TODO: review @Override public Double visitCash(final Cash cash, final YieldCurveBundle curves) { final YieldAndDiscountCurve curve = curves.getCurve(cash.getYieldCurveName()); final double ta = cash.getStartTime(); final double tb = cash.getEndTime(); final double yearFrac = cash.getAccrualFactor(); // TODO need a getForwardRate method on YieldAndDiscountCurve if (yearFrac == 0.0) { if (!CompareUtils.closeEquals(ta, tb, 1e-16)) { throw new IllegalArgumentException( "Year fraction is zero, but payment time greater than trade time"); } final double eps = 1e-8; final double rate = curve.getInterestRate(ta); final double dRate = curve.getInterestRate(ta + eps); return rate + ta * (dRate - rate) / eps; } return (curve.getDiscountFactor(ta) / curve.getDiscountFactor(tb) - 1) / yearFrac; }