docs: @Override
  	public RandomVariableInterface getValue(final double evaluationTime, final LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
  
  		// Ignite asynchronous calculation if possible
  		ArrayList< Future<RandomVariableInterface> > results = new ArrayList< Future<RandomVariableInterface> >();
  		for(final AbstractMonteCarloProduct product : products) {
  			Future<RandomVariableInterface> valueFuture;
  			try {
  				valueFuture = executor.submit(
  						new Callable<RandomVariableInterface>() {
  							public RandomVariableInterface call() throws CalculationException {
  								return product.getValue(evaluationTime, model);
  							}
  						}
  						);
  			}
  			catch(RejectedExecutionException e) {
  				valueFuture = new FutureWrapper<RandomVariableInterface>(product.getValue(evaluationTime, model));
  			}
  
  			results.add(valueFuture);
  		}
  
  		// Collect results
  		RandomVariableInterface values = model.getRandomVariableForConstant(0.0);
  		try {
  			for(Future<RandomVariableInterface> valueFuture : results) {
  				values = values.add(valueFuture.get());
  			}
  		} catch (InterruptedException e) {
  			throw e.getCause() instanceof CalculationException ? (CalculationException)(e.getCause()) : new CalculationException(e.getCause());
  		} catch (ExecutionException e) {
  			if(CalculationException.class.isInstance(e.getCause())) {
  				throw (CalculationException)(e.getCause());
  			}
  			else if(RuntimeException.class.isInstance(e.getCause())) {
  				throw (RuntimeException)(e.getCause());
  			}
  			else {
  				throw new CalculationException(e.getCause());
  			}
  		}
  
  		// Return values
  		return values;
  	}