Package com.opengamma.analytics.financial.montecarlo.provider

Source Code of com.opengamma.analytics.financial.montecarlo.provider.HullWhiteMonteCarloMethod

/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.montecarlo.provider;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.model.interestrate.HullWhiteOneFactorPiecewiseConstantInterestRateModel;
import com.opengamma.analytics.financial.model.interestrate.definition.HullWhiteOneFactorPiecewiseConstantParameters;
import com.opengamma.analytics.financial.montecarlo.DecisionSchedule;
import com.opengamma.analytics.financial.montecarlo.MonteCarloDiscountFactorCalculator;
import com.opengamma.analytics.financial.montecarlo.MonteCarloDiscountFactorDataBundle;
import com.opengamma.analytics.financial.montecarlo.MonteCarloDiscountFactorDerivativeCalculator;
import com.opengamma.analytics.financial.montecarlo.MonteCarloDiscountFactorDerivativeDataBundle;
import com.opengamma.analytics.financial.provider.description.interestrate.HullWhiteOneFactorProviderInterface;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
import com.opengamma.analytics.math.linearalgebra.CholeskyDecompositionCommons;
import com.opengamma.analytics.math.linearalgebra.CholeskyDecompositionResult;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.random.RandomNumberGenerator;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.tuple.DoublesPair;

/**
* Monte Carlo pricing method in the hull-White one factor model.
* The Monte Carlo is on the solution of the discount factor (not on the equation of the short rate).
*/
public class HullWhiteMonteCarloMethod extends MonteCarloMethod {

  /**
   * The decision schedule calculator (calculate the exercise dates, the cash flow dates and the reference amounts).
   */
  private static final DecisionScheduleCalculator DC = DecisionScheduleCalculator.getInstance();
  /**
   * The decision schedule derivative calculator (calculate the exercise dates, the cash flow dates, the reference amounts and the sensitivity of the reference amount to the curves).
   */
  private static final DecisionScheduleDerivativeCalculator DDC = DecisionScheduleDerivativeCalculator.getInstance();
  /**
   * The calculator from discount factors (calculate the price from simulated discount factors and the reference amounts).
   */
  private static final MonteCarloDiscountFactorCalculator MCC = MonteCarloDiscountFactorCalculator.getInstance();
  /**
   * The calculator of price and derivatives from discount factors and reference amounts.
   */
  private static final MonteCarloDiscountFactorDerivativeCalculator MCDC = MonteCarloDiscountFactorDerivativeCalculator.getInstance();
  /**
   * The Hull-White one factor model.
   */
  private static final HullWhiteOneFactorPiecewiseConstantInterestRateModel MODEL = new HullWhiteOneFactorPiecewiseConstantInterestRateModel();
  /**
   * The number of paths in one block.
   */
  private static final int BLOCK_SIZE = 1000;

  /**
   * @param numberGenerator The random number generator.
   * @param nbPath The number of paths.
   */
  public HullWhiteMonteCarloMethod(final RandomNumberGenerator numberGenerator, final int nbPath) {
    super(numberGenerator, nbPath);
  }

  /**
   * Computes the present value in the Hull-White one factor model by Monte-Carlo.
   * Implementation note: The total number of paths is divided in blocks of maximum size BLOCK_SIZE=1000. The Monte Carlo is run on each block and the average of each
   * block price is the total price.
   * @param instrument The swaption.
   * @param ccy The currency.
   * @param hwData The Hull-White data (curves and Hull-White parameters).
   * @return The present value.
   */
  public MultipleCurrencyAmount presentValue(final InstrumentDerivative instrument, final Currency ccy, final HullWhiteOneFactorProviderInterface hwData) {
    // TODO: remove currency and dsc curve name (should be available from the instrument)
    final MulticurveProviderInterface multicurves = hwData.getMulticurveProvider();
    final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwData.getHullWhiteParameters();
    final DecisionSchedule decision = instrument.accept(DC, multicurves);
    final double[] decisionTime = decision.getDecisionTime();
    final double[][] impactTime = decision.getImpactTime();
    final int nbJump = decisionTime.length;
    final double numeraireTime = decisionTime[nbJump - 1];
    final double pDN = multicurves.getDiscountFactor(ccy, numeraireTime);
    // Discount factor to numeraire date for rebasing.
    final double[][] pDI = new double[nbJump][];
    // Initial discount factors to each impact date.
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      pDI[loopjump] = new double[impactTime[loopjump].length];
      for (int i = 0; i < impactTime[loopjump].length; i++) {
        pDI[loopjump][i] = multicurves.getDiscountFactor(ccy, impactTime[loopjump][i]) / pDN;
      }
    }
    final double[] gamma = new double[nbJump];
    final double[][] cov = new double[nbJump][nbJump];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      gamma[loopjump] = MODEL.beta(parameters, 0.0, decisionTime[loopjump]);
      gamma[loopjump] = gamma[loopjump] * gamma[loopjump];
      cov[loopjump][loopjump] = gamma[loopjump];
      for (int j = loopjump + 1; j < nbJump; j++) {
        cov[j][loopjump] = gamma[loopjump];
        cov[loopjump][j] = gamma[loopjump];
      }
    }
    final double[][] h = MODEL.volatilityMaturityPart(parameters, numeraireTime, impactTime); // jump/cf
    final double[][] h2 = new double[nbJump][];
    for (int i = 0; i < nbJump; i++) {
      h2[i] = new double[h[i].length];
      for (int j = 0; j < h[i].length; j++) {
        h2[i][j] = h[i][j] * h[i][j] / 2;
      }
    }
    // To remove the 0 (fixed coupons)
    int nbZero = 0;
    while (cov[nbZero][nbZero] < 1.0E-12) {
      nbZero++;
    }
    final double[][] cov2 = new double[nbJump - nbZero][nbJump - nbZero];
    for (int loopjump = 0; loopjump < nbJump - nbZero; loopjump++) {
      for (int loopjump2 = 0; loopjump2 < nbJump - nbZero; loopjump2++) {
        cov2[loopjump][loopjump2] = cov[loopjump + nbZero][loopjump2 + nbZero];
      }
    }
    final CholeskyDecompositionCommons cd = new CholeskyDecompositionCommons();
    final CholeskyDecompositionResult cdr2 = cd.evaluate(new DoubleMatrix2D(cov2));
    final double[][] covCD2 = cdr2.getL().toArray();
    final double[][] covCD = new double[nbJump][nbJump];
    for (int loopjump = 0; loopjump < nbJump - nbZero; loopjump++) {
      for (int loopjump2 = 0; loopjump2 < nbJump - nbZero; loopjump2++) {
        covCD[loopjump + nbZero][loopjump2 + nbZero] = covCD2[loopjump][loopjump2];
      }
    }
    final int nbBlock = (int) Math.round(Math.ceil(getNbPath() / ((double) BLOCK_SIZE)));
    final int[] nbPath2 = new int[nbBlock];
    for (int i = 0; i < nbBlock - 1; i++) {
      nbPath2[i] = BLOCK_SIZE;
    }
    nbPath2[nbBlock - 1] = getNbPath() - (nbBlock - 1) * BLOCK_SIZE;
    final double[][] impactAmount = decision.getImpactAmount();
    double pv = 0;
    for (int loopblock = 0; loopblock < nbBlock; loopblock++) {
      final double[][] x = getNormalArray(nbJump, nbPath2[loopblock]);
      final double[][] y = new double[nbJump][nbPath2[loopblock]]; // jump/path
      for (int looppath = 0; looppath < nbPath2[loopblock]; looppath++) {
        for (int i = 0; i < nbJump; i++) {
          for (int j = 0; j < nbJump; j++) {
            y[i][looppath] += x[j][looppath] * covCD[i][j];
          }
        }
      }
      final Double[][][] pD = pathGeneratorDiscount(pDI, y, h, h2, gamma);
      pv += instrument.accept(MCC, new MonteCarloDiscountFactorDataBundle(pD, impactAmount)) * nbPath2[loopblock];
    }
    pv *= pDN / getNbPath(); // Multiply by the numeraire.
    return MultipleCurrencyAmount.of(ccy, pv);
  }

  /**
   * Computes the present value curve sensitivity in the Hull-White one factor model by Monte-Carlo. The sensitivity is computed by Adjoint Algorithmic Differentiation.
   * Implementation note: The total number of paths is divided in blocks of maximum size BLOCK_SIZE=1000. The Monte Carlo is run on each block and the average of each
   * block price is the total price.
   * @param instrument The swaption.
   * @param ccy The currency.
   * @param hwData The Hull-White data (curves and Hull-White parameters).
   * @return The curve sensitivity.
   */
  public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final InstrumentDerivative instrument, final Currency ccy, final HullWhiteOneFactorProviderInterface hwData) {
    final MulticurveProviderInterface multicurves = hwData.getMulticurveProvider();
    final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwData.getHullWhiteParameters();
    // Forward sweep
    final DecisionScheduleDerivative decision = instrument.accept(DDC, multicurves);
    final double[] decisionTime = decision.getDecisionTime();
    final double[][] impactTime = decision.getImpactTime();
    final int nbJump = decisionTime.length;
    final double numeraireTime = decisionTime[nbJump - 1];
    final double pDN = multicurves.getDiscountFactor(ccy, numeraireTime);
    // Discount factor to numeraire date for rebasing.
    final double[][] pDI = new double[nbJump][];
    // Initial discount factors to each impact date.
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      pDI[loopjump] = new double[impactTime[loopjump].length];
      for (int i = 0; i < impactTime[loopjump].length; i++) {
        pDI[loopjump][i] = multicurves.getDiscountFactor(ccy, impactTime[loopjump][i]) / pDN;
      }
    }
    final double[] gamma = new double[nbJump];
    final double[][] cov = new double[nbJump][nbJump];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      gamma[loopjump] = MODEL.beta(parameters, 0.0, decisionTime[loopjump]);
      gamma[loopjump] = gamma[loopjump] * gamma[loopjump];
      cov[loopjump][loopjump] = gamma[loopjump];
      for (int j = loopjump + 1; j < nbJump; j++) {
        cov[j][loopjump] = gamma[loopjump];
        cov[loopjump][j] = gamma[loopjump];
      }
    }
    final double[][] h = MODEL.volatilityMaturityPart(parameters, numeraireTime, impactTime); // jump/cf
    final double[][] h2 = new double[nbJump][];
    for (int i = 0; i < nbJump; i++) {
      h2[i] = new double[h[i].length];
      for (int j = 0; j < h[i].length; j++) {
        h2[i][j] = h[i][j] * h[i][j] / 2;
      }
    }
    // To remove the 0 (fixed coupons)
    int nbZero = 0;
    while (cov[nbZero][nbZero] < 1.0E-12) {
      nbZero++;
    }
    final double[][] cov2 = new double[nbJump - nbZero][nbJump - nbZero];
    for (int loopjump = 0; loopjump < nbJump - nbZero; loopjump++) {
      for (int loopjump2 = 0; loopjump2 < nbJump - nbZero; loopjump2++) {
        cov2[loopjump][loopjump2] = cov[loopjump + nbZero][loopjump2 + nbZero];
      }
    }
    final CholeskyDecompositionCommons cd = new CholeskyDecompositionCommons();
    final CholeskyDecompositionResult cdr2 = cd.evaluate(new DoubleMatrix2D(cov2));
    final double[][] covCD2 = cdr2.getL().toArray();
    final double[][] covCD = new double[nbJump][nbJump];
    for (int loopjump = 0; loopjump < nbJump - nbZero; loopjump++) {
      for (int loopjump2 = 0; loopjump2 < nbJump - nbZero; loopjump2++) {
        covCD[loopjump + nbZero][loopjump2 + nbZero] = covCD2[loopjump][loopjump2];
      }
    }
    final int nbBlock = (int) Math.round(Math.ceil(getNbPath() / ((double) BLOCK_SIZE)));
    final int[] nbPath2 = new int[nbBlock];
    for (int i = 0; i < nbBlock - 1; i++) {
      nbPath2[i] = BLOCK_SIZE;
    }
    nbPath2[nbBlock - 1] = getNbPath() - (nbBlock - 1) * BLOCK_SIZE;
    final double[][] impactAmount = decision.getImpactAmount();
    double pv = 0;
    final double[] pvBlock = new double[nbBlock];
    // Backward sweep (init)
    final double pvBar = 1.0;
    final double[] pvBlockBar = new double[nbBlock];
    for (int loopblock = 0; loopblock < nbBlock; loopblock++) {
      pvBlockBar[loopblock] = pDN / getNbPath() * pvBar;
    }
    final double[][] impactAmountBar = new double[nbJump][];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      impactAmountBar[loopjump] = new double[impactAmount[loopjump].length];
    }
    // Forward sweep (end) and backward sweep (main)
    final double[][] pDIBar = new double[nbJump][];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      pDIBar[loopjump] = new double[impactAmount[loopjump].length];
    }
    for (int loopblock = 0; loopblock < nbBlock; loopblock++) {
      final double[][] x = getNormalArray(nbJump, nbPath2[loopblock]);
      final double[][] y = new double[nbJump][nbPath2[loopblock]]; // jump/path
      for (int looppath = 0; looppath < nbPath2[loopblock]; looppath++) {
        for (int i = 0; i < nbJump; i++) {
          for (int j = 0; j < nbJump; j++) {
            y[i][looppath] += x[j][looppath] * covCD[i][j];
          }
        }
      }
      final Double[][][] pD = pathGeneratorDiscount(pDI, y, h, h2, gamma);
      final MonteCarloDiscountFactorDerivativeDataBundle mcdDB = new MonteCarloDiscountFactorDerivativeDataBundle(pD, impactAmount);
      pvBlock[loopblock] = instrument.accept(MCDC, mcdDB) * nbPath2[loopblock];
      pv += pvBlock[loopblock];
      // Backward sweep (in block loop)
      for (int loopjump = 0; loopjump < nbJump; loopjump++) {
        for (int loopimp = 0; loopimp < impactAmount[loopjump].length; loopimp++) {
          impactAmountBar[loopjump][loopimp] += mcdDB.getImpactAmountDerivative()[loopjump][loopimp] * nbPath2[loopblock] * pvBlockBar[loopblock];
        }
      }
      final Double[][][] pDBar = new Double[nbPath2[loopblock]][nbJump][];
      for (int looppath = 0; looppath < nbPath2[loopblock]; looppath++) {
        for (int loopjump = 0; loopjump < nbJump; loopjump++) {
          pDBar[looppath][loopjump] = new Double[impactAmount[loopjump].length];
          for (int loopimp = 0; loopimp < impactAmount[loopjump].length; loopimp++) {
            pDBar[looppath][loopjump][loopimp] = mcdDB.getPathDiscountingFactorDerivative()[looppath][loopjump][loopimp] * nbPath2[loopblock] * pvBlockBar[loopblock];
          }
        }
      }
      final double[][] pDIBarTemp = pathGeneratorDiscountAdjointIDF(pDI, y, h, h2, gamma, pDBar);
      for (int loopjump = 0; loopjump < nbJump; loopjump++) {
        for (int loopimp = 0; loopimp < impactAmount[loopjump].length; loopimp++) {
          pDIBar[loopjump][loopimp] += pDIBarTemp[loopjump][loopimp];
        }
      }
    }
    pv *= pDN / getNbPath(); // Multiply by the numeraire.
    // Backward sweep (end)
    double pDNBar = pv / pDN * pvBar;
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      for (int loopimp = 0; loopimp < impactTime[loopjump].length; loopimp++) {
        pDNBar += -multicurves.getDiscountFactor(ccy, impactTime[loopjump][loopimp]) / (pDN * pDN) * pDIBar[loopjump][loopimp];
      }
    }
    final Map<String, List<DoublesPair>> resultMap = new HashMap<>();
    final List<DoublesPair> listDiscounting = new ArrayList<>();
    listDiscounting.add(new DoublesPair(numeraireTime, -numeraireTime * pDN * pDNBar));
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      for (int loopimp = 0; loopimp < impactTime[loopjump].length; loopimp++) {
        listDiscounting.add(new DoublesPair(impactTime[loopjump][loopimp], -impactTime[loopjump][loopimp] * pDI[loopjump][loopimp] * pDIBar[loopjump][loopimp]));
      }
    }
    resultMap.put(multicurves.getName(ccy), listDiscounting);
    MulticurveSensitivity result = MulticurveSensitivity.ofYieldDiscounting(resultMap);
    // Adding sensitivity due to cash flow equivalent sensitivity to curves.
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      final Map<Double, MulticurveSensitivity> impactAmountDerivative = decision.getImpactAmountDerivative().get(loopjump);
      for (int loopimp = 0; loopimp < impactTime[loopjump].length; loopimp++) {
        final MulticurveSensitivity sensiCfe = impactAmountDerivative.get(impactTime[loopjump][loopimp]);
        if (!(sensiCfe == null)) { // There is some sensitivity to that cfe.
          result = result.plus(sensiCfe.multipliedBy(impactAmountBar[loopjump][loopimp]));
        }
      }
    }
    result = result.cleaned();
    return MultipleCurrencyMulticurveSensitivity.of(ccy, result);
  }

  /**
   * Gets a 2D-array of independent normally distributed variables.
   * @param nbJump The number of jumps.
   * @param nbPath The number of paths.
   * @return The array of variables.
   */
  private double[][] getNormalArray(final int nbJump, final int nbPath) {
    final double[][] result = new double[nbJump][nbPath];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      result[loopjump] = getNumberGenerator().getVector(nbPath);
    }
    return result;
  }

  /**
   * Construct the discount factors on the simulated paths from the random variables and the model constants.
   * @param initDiscountFactor The initial discount factors.
   * @param y The correlated random variables. jump/path
   * @param h The H parameters. jump/cf
   * @param h2 The H^2 parameters.
   * @param gamma The gamma parameters.
   * @return The discount factor paths (path/jump/cf).
   */
  private Double[][][] pathGeneratorDiscount(final double[][] initDiscountFactor, final double[][] y, final double[][] h, final double[][] h2, final double[] gamma) {
    final int nbJump = y.length;
    final int nbPath = y[0].length;
    final Double[][][] pD = new Double[nbPath][nbJump][];
    double[] h2gamma;
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      final int nbCF = h[loopjump].length;
      h2gamma = new double[nbCF];
      for (int loopcf = 0; loopcf < nbCF; loopcf++) {
        h2gamma[loopcf] = h2[loopjump][loopcf] * gamma[loopjump];
      }
      for (int looppath = 0; looppath < nbPath; looppath++) {
        pD[looppath][loopjump] = new Double[nbCF];
        for (int loopcf = 0; loopcf < nbCF; loopcf++) {
          pD[looppath][loopjump][loopcf] = initDiscountFactor[loopjump][loopcf] * Math.exp(-h[loopjump][loopcf] * y[loopjump][looppath] - h2gamma[loopcf]);
        }
      }
    }
    return pD;
  }

  /**
   * Computes the initial discount factors adjoint values with respect to the initDiscountFactor.
   * @param initDiscountFactor The initial discount factors.
   * @param y The correlated random variables.
   * @param h The H parameters.
   * @param h2 The H^2 parameters.
   * @param gamma The gamma parameters.
   * @param pDBar The simulated discount factor adjoints (path/jump/cf).
   * @return The initial discount factor adjoints (jump/cf).
   */
  private double[][] pathGeneratorDiscountAdjointIDF(final double[][] initDiscountFactor, final double[][] y, final double[][] h, final double[][] h2, final double[] gamma, final Double[][][] pDBar) {
    final int nbJump = y.length;
    final int nbPath = y[0].length;
    double[] h2gamma;
    final double[][] initDiscountFactorBar = new double[nbJump][];
    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
      final int nbCF = h[loopjump].length;
      h2gamma = new double[nbCF];
      for (int loopcf = 0; loopcf < nbCF; loopcf++) {
        h2gamma[loopcf] = h2[loopjump][loopcf] * gamma[loopjump];
      }
      // Backward sweep
      initDiscountFactorBar[loopjump] = new double[nbCF];
      for (int looppath = 0; looppath < nbPath; looppath++) {
        for (int loopcf = 0; loopcf < nbCF; loopcf++) {
          initDiscountFactorBar[loopjump][loopcf] += Math.exp(-h[loopjump][loopcf] * y[loopjump][looppath] - h2gamma[loopcf]) * pDBar[looppath][loopjump][loopcf];
        }
      }
    }
    return initDiscountFactorBar;
  }

  //  /**
  //   * Computes the initial discount factors adjoint values with respect to y.
  //   * @param initDiscountFactor The initial discount factors.
  //   * @param y The correlated random variables.
  //   * @param h The H parameters.
  //   * @param h2 The H^2 parameters.
  //   * @param gamma The gamma parameters.
  //   * @param pDBar The simulated discount factor adjoints (path/jump/cf).
  //   * @return The y adjoints (jump/path).
  //   */
  //  private double[][] pathGeneratorDiscountAdjointY(double[][] initDiscountFactor, double[][] y, double[][] h, double[][] h2, double[] gamma, Double[][][] pDBar) {
  //    int nbJump = y.length;
  //    int nbPath = y[0].length;
  //    double[] h2gamma;
  //    double[][] yBar = new double[nbJump][nbPath];
  //    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
  //      int nbCF = h[loopjump].length;
  //      h2gamma = new double[nbCF];
  //      for (int loopcf = 0; loopcf < nbCF; loopcf++) {
  //        h2gamma[loopcf] = h2[loopjump][loopcf] * gamma[loopjump];
  //      }
  //      // Backward sweep
  //      for (int looppath = 0; looppath < nbPath; looppath++) {
  //        for (int loopcf = 0; loopcf < nbCF; loopcf++) {
  //          y[loopjump][looppath] += initDiscountFactor[loopjump][loopcf] * Math.exp(-h[loopjump][loopcf] * y[loopjump][looppath] - h2gamma[loopcf]) * -h[loopjump][loopcf]
  //              * pDBar[looppath][loopjump][loopcf];
  //        }
  //      }
  //    }
  //    return yBar;
  //  }
  //
  //  /**
  //   * Computes the initial discount factors adjoint values with respect to gamma.
  //   * @param initDiscountFactor The initial discount factors.
  //   * @param y The correlated random variables.
  //   * @param h The H parameters.
  //   * @param h2 The H^2 parameters.
  //   * @param gamma The gamma parameters.
  //   * @param pDBar The simulated discount factor adjoints (path/jump/cf).
  //   * @return The y adjoints (jump/path).
  //   */
  //  private double[] pathGeneratorDiscountAdjointGamma(double[][] initDiscountFactor, double[][] y, double[][] h, double[][] h2, double[] gamma, Double[][][] pDBar) {
  //    int nbJump = y.length;
  //    int nbPath = y[0].length;
  //    double[] h2gamma;
  //    double[] h2gammaBar;
  //    double[] gammaBar = new double[nbJump];
  //    for (int loopjump = 0; loopjump < nbJump; loopjump++) {
  //      int nbCF = h[loopjump].length;
  //      h2gamma = new double[nbCF];
  //      for (int loopcf = 0; loopcf < nbCF; loopcf++) {
  //        h2gamma[loopcf] = h2[loopjump][loopcf] * gamma[loopjump];
  //      }
  //      // Backward sweep
  //      h2gammaBar = new double[nbCF];
  //      for (int looppath = 0; looppath < nbPath; looppath++) {
  //        for (int loopcf = 0; loopcf < nbCF; loopcf++) {
  //          h2gammaBar[loopcf] += -initDiscountFactor[loopjump][loopcf] * Math.exp(-h[loopjump][loopcf] * y[loopjump][looppath] - h2gamma[loopcf]) * pDBar[looppath][loopjump][loopcf];
  //        }
  //      }
  //      for (int loopcf = 0; loopcf < nbCF; loopcf++) {
  //        gammaBar[loopjump] += h2[loopjump][loopcf] * h2gammaBar[loopcf];
  //      }
  //    }
  //    return gammaBar;
  //  }

}
TOP

Related Classes of com.opengamma.analytics.financial.montecarlo.provider.HullWhiteMonteCarloMethod

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.