Exemple #1
0
 @Test
 public void testGetters() {
   assertEquals(SURFACE.getName(), NAME1);
   assertEquals(SURFACE.getFunction(), F1);
   assertEquals(SURFACE.getZValue(1., 2.), F1.evaluate(1., 2.), 0);
   assertEquals(SURFACE.getZValue(DoublesPair.of(1., 4.)), F1.evaluate(1., 4.), 0);
 }
  /**
   * Get the coefficients (a, b and c) for the PDE governing the evolution of the transition density
   * for a single underlying (i.e. 1 spatial dimension). The PDE is of the form $frac{\partial
   * V}{\partial t} + a(x,t)\frac{\partial^2V}{\partial x^2}+b(x,t)\frac{\partial V}{\partial x}
   * +c(x,t)V=0$ where $V(x,t)$ is the density
   *
   * @param forward the forward curve
   * @param localVol the local volatility surface (parameterised by strike)
   * @return The coefficients a, b & c - which are all functions of time and asset value (space)
   */
  public static ConvectionDiffusionPDE1DCoefficients getStandardCoefficients(
      final ForwardCurve forward, final LocalVolatilitySurfaceStrike localVol) {

    final Function<Double, Double> a =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            final double sigma = localVol.getVolatility(t, s) * s;
            return -0.5 * sigma * sigma;
          }
        };

    final Function<Double, Double> b =
        new Function<Double, Double>() {
          @SuppressWarnings("synthetic-access")
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            final double lvDiv = getLocalVolFirstDiv(localVol, t, s);
            final double lv = localVol.getVolatility(t, s);
            return s * (forward.getDrift(t) - 2 * lv * (s * lvDiv + lv));
          }
        };

    final Function<Double, Double> c =
        new Function<Double, Double>() {
          @SuppressWarnings("synthetic-access")
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            final double lv1Div = getLocalVolFirstDiv(localVol, t, s);
            final double lv2Div = getLocalVolSecondDiv(localVol, t, s);
            final double lv = localVol.getVolatility(t, s);
            final double temp1 = (lv + s * lv1Div);
            final double temp2 = lv * s * (s * lv2Div + 2 * lv1Div);

            return forward.getDrift(t) - temp1 * temp1 - temp2;
          }
        };

    //    //using a log-normal distribution with a very small Standard deviation as a proxy for a
    // Dirac delta

    return new ConvectionDiffusionPDE1DStandardCoefficients(
        FunctionalDoublesSurface.from(a),
        FunctionalDoublesSurface.from(b),
        FunctionalDoublesSurface.from(c));
  }
Exemple #3
0
 @Test
 public void testStaticConstruction() {
   FunctionalDoublesSurface surface = new FunctionalDoublesSurface(F1);
   FunctionalDoublesSurface other = FunctionalDoublesSurface.from(F1);
   assertEquals(surface.getFunction(), other.getFunction());
   assertFalse(surface.equals(other));
   surface = new FunctionalDoublesSurface(F1, NAME1);
   other = FunctionalDoublesSurface.from(F1, NAME1);
   assertEquals(surface, other);
 }
  @Test
  public void ImpliedTreeEuropeanRecoveryTest() {
    final double interest = 0.06;
    final YieldAndDiscountCurve yCrv = YieldCurve.from(ConstantDoublesCurve.from(interest));
    final double cost = 0.02;
    final double atmVol = 0.47;
    final ZonedDateTime date = DateUtils.getUTCDate(2010, 7, 1);
    final double spot = 100;
    final Function<Double, Double> smile =
        new Function<Double, Double>() {

          @Override
          public Double evaluate(final Double... tk) {
            ArgChecker.isTrue(tk.length == 2);
            final double k = tk[1];
            return atmVol + (spot - k) * 0.0005;
          }
        };

    final StandardOptionDataBundle data =
        new StandardOptionDataBundle(
            yCrv, cost, new VolatilitySurface(FunctionalDoublesSurface.from(smile)), spot, date);

    final double[] strikes = new double[] {spot * 0.9, spot, spot * 1.11};
    final int nSteps = 7;
    final double time = 1.;

    for (int i = 0; i < strikes.length; ++i) {
      final double strike = strikes[i];
      final boolean isCall = strike >= spot ? true : false;
      final OptionFunctionProvider1D function =
          new EuropeanVanillaOptionFunctionProvider(strike, time, nSteps, isCall);
      final double tree = _modelTrinomial.getPrice(function, data);
      final double black =
          BlackScholesFormulaRepository.price(
              spot, strike * 0.9, time, data.getVolatility(time, strike), interest, cost, isCall);
      assertEquals(tree, black, black * 0.2);
    }

    try {
      _model.getPrice(
          new EuropeanVanillaOptionFunctionProvider(strikes[2], time, nSteps, true), data);
      throw new RuntimeException();
    } catch (Exception e) {
      assertTrue(e instanceof IllegalArgumentException);
    }
  }
Exemple #5
0
 @Test
 public void testEqualsAndHashCode() {
   FunctionalDoublesSurface other = new FunctionalDoublesSurface(F1, NAME1);
   assertEquals(SURFACE, other);
   assertEquals(SURFACE.hashCode(), other.hashCode());
   other = new FunctionalDoublesSurface(F2, NAME1);
   assertFalse(SURFACE.equals(other));
   other = new FunctionalDoublesSurface(F1, NAME2);
   assertFalse(SURFACE.equals(other));
   other = new FunctionalDoublesSurface(F1);
   assertFalse(SURFACE.equals(other));
 }
Exemple #6
0
 @Test(expectedExceptions = IllegalArgumentException.class)
 public void testNullPair() {
   SURFACE.getZValue(null);
 }
Exemple #7
0
 @Test(expectedExceptions = UnsupportedOperationException.class)
 public void testGetSize() {
   SURFACE.size();
 }
  static {
    PURE_LOG_PAY_OFF =
        new Function1D<Double, Double>() {
          final double fT = DIV_CURVES.getF(EXPIRY);
          final double dT = DIV_CURVES.getD(EXPIRY);

          @Override
          public Double evaluate(final Double x) {
            final double s = (fT - dT) * Math.exp(x) + dT;
            return Math.log(s);
          }
        };

    final Function<Double, Double> localVol =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            final double t = ts[0];
            final double s = ts[1];
            final double d = DIV_CURVES.getD(t);
            if (s < d) {
              return 0.0;
            }
            return PURE_VOL * (s - d) / s;
          }
        };

    LOCAL_VOL = new LocalVolatilitySurfaceStrike(FunctionalDoublesSurface.from(localVol));

    final Function<Double, Double> localVolSpecial =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... tf) {
            final double t = tf[0];
            final double f = tf[1];
            final double rtT = DIV_CURVES.getR(t);
            final double dtT = DIV_CURVES.getD(t);
            final double ftT = DIV_CURVES.getF(t);
            //        if (f < d) {
            //          return 0.0;
            //        }
            final double x = f / rtT / (ftT - dtT);
            return PURE_LOCAL_VOL.getVolatility(t, x);
          }
        };

    LOCAL_VOL_SPECIAL =
        new LocalVolatilitySurfaceStrike(FunctionalDoublesSurface.from(localVolSpecial));

    final Function<Double, Double> pureLocalVol =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... tx) {
            final double t = tx[0];
            final double x = tx[1];
            final double f = DIV_CURVES.getF(t);
            final double d = DIV_CURVES.getD(t);
            return VOL * ((f - d) * x + d) / (f - d) / x;
          }
        };

    PURE_LOCAL_VOL =
        new LocalVolatilitySurfaceMoneyness(
            FunctionalDoublesSurface.from(pureLocalVol), new ForwardCurve(1.0));

    PURE_LOCAL_VOL_FLAT =
        new LocalVolatilitySurfaceMoneyness(
            ConstantDoublesSurface.from(PURE_VOL), new ForwardCurve(1.0));
    LOCAL_VOL_FLAT = new LocalVolatilitySurfaceStrike(ConstantDoublesSurface.from(VOL));
  }
  public static ExtendedCoupledPDEDataBundle getExtendedCoupledPDEDataBundle(
      final ForwardCurve forward,
      final LocalVolatilitySurfaceStrike localVol,
      final double lambda1,
      final double lambda2,
      final double initialProb) {

    final Function<Double, Double> a =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            return -1.0;
          }
        };

    final Function<Double, Double> alpha =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            final double temp = s * localVol.getVolatility(t, s);

            return 0.5 * temp * temp;
          }
        };

    final Function<Double, Double> b =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            return s * forward.getDrift(t);
          }
        };

    final Function<Double, Double> beta =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            return 1.0;
          }
        };

    final Function<Double, Double> c =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];

            return forward.getDrift(t) + lambda1;
          }
        };

    // using a log-normal distribution with a very small Standard deviation as a proxy for a Dirac
    // delta
    final Function1D<Double, Double> initialCondition =
        new Function1D<Double, Double>() {
          private final double _volRootTOffset = 0.01;

          @Override
          public Double evaluate(final Double s) {
            if (s == 0) {
              return 0.0;
            }
            final double x = Math.log(s / forward.getSpot());
            final NormalDistribution dist = new NormalDistribution(0, _volRootTOffset);
            return initialProb * dist.getPDF(x) / s;
          }
        };

    return new ExtendedCoupledPDEDataBundle(
        FunctionalDoublesSurface.from(a),
        FunctionalDoublesSurface.from(b),
        FunctionalDoublesSurface.from(c),
        FunctionalDoublesSurface.from(alpha),
        FunctionalDoublesSurface.from(beta),
        lambda2,
        initialCondition);
  }
  /**
   * Get the coefficients (a, b, c, $\alpha$ & $\beta$) for the PDE governing the evolution of the
   * transition density for a single underlying (i.e. 1 spatial dimension). The PDE is of the form
   * $frac{\partial V}{\partial t} + a(x,t)\frac{\alpha(x,t)\partial^2V}{\partial
   * x^2}+b(x,t)\frac{\beta(x,t)\partial V}{\partial x} +c(x,t)V=0$ where $V(x,t)$ is the density
   *
   * @param forward the forward curve
   * @param localVol the local volatility surface (parameterised by strike)
   * @return The coefficients a, b, c, $\alpha$ & $\beta$ - which are all functions of time and
   *     asset value (space)
   */
  public static ConvectionDiffusionPDE1DFullCoefficients getFullCoefficients(
      final ForwardCurve forward, final LocalVolatilitySurfaceStrike localVol) {

    final Function<Double, Double> a =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            return -1.0;
          }
        };

    final Function<Double, Double> alpha =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            final double temp = s * localVol.getVolatility(t, s);

            return 0.5 * temp * temp;
          }
        };

    final Function<Double, Double> b =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];
            final double s = ts[1];
            return s * forward.getDrift(t);
          }
        };

    final Function<Double, Double> beta =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            return 1.0;
          }
        };

    final Function<Double, Double> c =
        new Function<Double, Double>() {
          @Override
          public Double evaluate(final Double... ts) {
            ArgChecker.isTrue(ts.length == 2);
            final double t = ts[0];

            return forward.getDrift(t);
          }
        };

    return new ConvectionDiffusionPDE1DFullCoefficients(
        FunctionalDoublesSurface.from(a),
        FunctionalDoublesSurface.from(b),
        FunctionalDoublesSurface.from(c),
        FunctionalDoublesSurface.from(alpha),
        FunctionalDoublesSurface.from(beta));
  }