public class ScenarioGeneratorTest {

  // ----------------------------------------------------------------------------------------------------------------------------------------

  // TODO :

  // ----------------------------------------------------------------------------------------------------------------------------------------

  // Flag to control if any test results are output to the console
  private static final boolean outputResults = false;

  // ----------------------------------------------------------------------------------------------------------------------------------------

  private static final int numberOfSimulations = 12;

  private static final int defaultSimulationSeed = 987654321;
  private static final int recoveryRateSimulationSeed = 987654321;

  private static final double simulationTimeHorizon = 1.0;

  private static final double homogeneousDefaultCorrelation = 0.5;
  private static final double homogeneousRecoveryCorrelation = 0.0;
  private static final double homogeneousDefaultProbability = 0.5;

  // Create a pool construction object
  private static final UnderlyingPoolDummyPool pool = new UnderlyingPoolDummyPool();

  // Build the underlying pool
  private static final UnderlyingPool obligorUniverse = pool.constructPool();

  // Extract the number of obligors in the simulation universe from the UnderlyingPool
  private static final int numberOfObligors = obligorUniverse.getNumberOfObligors();

  // ----------------------------------------------------------------------------------------------------------------------------------------

  private static final SimulationMethods simMethods = new SimulationMethods();

  private static final SimulationEngine simulationEngine = new SimulationEngine();

  private static final RecoveryRateModel[] recoveryRateModels =
      simMethods.constructRecoveryRateModels(numberOfObligors);

  private static final double[] defaultCorrelationVector =
      simMethods.constructCorrelationVector(numberOfObligors, homogeneousDefaultCorrelation);
  private static final double[] recoveryCorrelationVector =
      simMethods.constructCorrelationVector(numberOfObligors, homogeneousRecoveryCorrelation);
  private static final double[] defaultProbabilityVector =
      simMethods.constructCorrelationVector(numberOfObligors, homogeneousDefaultProbability);

  private static final ScenarioGenerator scenarioGenerator =
      new ScenarioGenerator(
          obligorUniverse,
          recoveryRateModels,
          numberOfSimulations,
          defaultSimulationSeed,
          recoveryRateSimulationSeed,
          simulationTimeHorizon,
          defaultCorrelationVector,
          recoveryCorrelationVector,
          defaultProbabilityVector);

  // ----------------------------------------------------------------------------------------------------------------------------------------

  @Test
  public void testCreditPortfolioLossModelScenarioGenerator() {

    simulationEngine.runSimulation(scenarioGenerator, outputResults);
  }

  // ----------------------------------------------------------------------------------------------------------------------------------------
}
  public double getRecRate01IndexCreditDefaultSwap(
      final ZonedDateTime valuationDate,
      final IndexCreditDefaultSwapDefinition indexCDS,
      final ISDADateCurve[] yieldCurves,
      final ZonedDateTime[] marketTenors,
      final double[][] marketSpreads,
      final double recoveryRateBump,
      final RecoveryRateBumpType recoveryRateBumpType) {

    // ------------------------------------------------------------------------------------------------------------------------------------------

    ArgumentChecker.notNull(valuationDate, "Valuation date");
    ArgumentChecker.notNull(indexCDS, "Index CDS");
    ArgumentChecker.notNull(yieldCurves, "YieldCurve");
    ArgumentChecker.notNull(marketTenors, "Market tenors");
    ArgumentChecker.notNull(marketSpreads, "Market spreads");
    ArgumentChecker.notNull(recoveryRateBumpType, "Recovery rate bump type");

    // ------------------------------------------------------------------------------------------------------------------------------------------

    int numberOfObligors = indexCDS.getUnderlyingPool().getNumberOfObligors();

    double[] breakevenSpreads = new double[numberOfObligors];

    for (int i = 0; i < numberOfObligors; i++) {
      breakevenSpreads[i] = marketSpreads[i][0];
    }

    // Calibrate the hazard rate term structures of each of the obligors in the pool underlying the
    // index to the unbumped credit spreads
    final HazardRateCurve[] hazardRateCurves =
        calibrateHazardRateCurves.getCalibratedHazardRateCurves(
            valuationDate, indexCDS, marketTenors, marketSpreads, yieldCurves);

    // Calculate the unbumped value of the index
    final double presentValue =
        indexPresentValue.getIntrinsicPresentValueIndexCreditDefaultSwap(
            valuationDate, indexCDS, breakevenSpreads, yieldCurves, hazardRateCurves);

    // Extract out the underlying pool from the index CDS
    UnderlyingPool modifiedPool = indexCDS.getUnderlyingPool();

    double[] recoveryRates = modifiedPool.getRecoveryRates();

    // final double recoveryRate = modifiedPool.getRecoveryRates()[i];

    final double[] bumpedRecoveryRates =
        recoveryRateBumper.getBumpedRecoveryRate(
            recoveryRates, recoveryRateBump, recoveryRateBumpType);

    // Modify the temp pool object to have the bumped recovery rate vector
    modifiedPool = modifiedPool.withRecoveryRates(bumpedRecoveryRates);

    // Construct a temporary index CDS
    IndexCreditDefaultSwapDefinition tempIndex = indexCDS;

    // Modify the temporary index to have the modified underlying pool
    tempIndex = tempIndex.withUnderlyingPool(modifiedPool);

    // Calibrate the hazard rate term structures of each of the obligors in the pool underlying the
    // index to the bumped recovery rates
    final HazardRateCurve[] bumpedHazardRateCurves =
        calibrateHazardRateCurves.getCalibratedHazardRateCurves(
            valuationDate, tempIndex, marketTenors, marketSpreads, yieldCurves);

    // Calculate the bumped value of the index
    final double bumpedPresentValue =
        indexPresentValue.getIntrinsicPresentValueIndexCreditDefaultSwap(
            valuationDate, tempIndex, breakevenSpreads, yieldCurves, bumpedHazardRateCurves);

    final double recRate01 = (bumpedPresentValue - presentValue) / recoveryRateBump;

    return recRate01;
  }