docs: @Override
  	public RandomVariable getValue(final double evaluationTime, final LIBORModelMonteCarloSimulationModel model) throws CalculationException {
  
  		// Ignite asynchronous calculation if possible
  		ArrayList< Future<RandomVariable> > results = new ArrayList< >();
  		for(final MonteCarloProduct product : products) {
  			Future<RandomVariable> valueFuture;
  			try {
  				valueFuture = getExecutor().submit(
  						new Callable<RandomVariable>() {
  							@Override
  							public RandomVariable call() throws CalculationException {
  								return product.getValue(evaluationTime, model);
  							}
  						}
  						);
  			}
  			catch(RejectedExecutionException e) {
  				valueFuture = new FutureWrapper<>(product.getValue(evaluationTime, model));
  			}
  
  			results.add(valueFuture);
  		}
  
  		// Collect results
  		RandomVariable values = model.getRandomVariableForConstant(0.0);
  		try {
  			for(Future<RandomVariable> 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;
  	}