docs: @Override
  	public RandomVariable getValue(double evaluationTime, LIBORModelMonteCarloSimulationModel model) throws CalculationException {
  
  		final RandomVariable one	= model.getRandomVariableForConstant(1.0);
  		final RandomVariable zero	= model.getRandomVariableForConstant(0.0);
  
  		// TODO >=? -
  		if(evaluationTime > exerciseDate) {
  			return zero;
  		}
  
  		RandomVariable values = underlying.getValue(exerciseDate, model);
  		RandomVariable strike;
  		if(strikeProduct != null) {
  			strike = strikeProduct.getValue(exerciseDate, model);
  		} else {
  			strike = model.getRandomVariableForConstant(strikePrice);
  		}
  
  		RandomVariable exerciseTrigger = values.sub(strike).mult(isCall ? 1.0 : -1.0);
  
  		if(exerciseTrigger.getFiltrationTime() > exerciseDate) {
  			RandomVariable filterNaN = exerciseTrigger.isNaN().sub(1.0).mult(-1.0);
  			RandomVariable exerciseTriggerFiltered = exerciseTrigger.mult(filterNaN);
  
  			/*
  			 * Cut off two standard deviations from regression
  			 */
  			double exerciseTriggerMean		= exerciseTriggerFiltered.getAverage();
  			double exerciseTriggerStdDev	= exerciseTriggerFiltered.getStandardDeviation();
  			double exerciseTriggerFloor		= exerciseTriggerMean*(1.0-Math.signum(exerciseTriggerMean)*1E-5)-3.0*exerciseTriggerStdDev;
  			double exerciseTriggerCap		= exerciseTriggerMean*(1.0+Math.signum(exerciseTriggerMean)*1E-5)+3.0*exerciseTriggerStdDev;
  			RandomVariable filter = exerciseTrigger.sub(exerciseTriggerFloor).choose(one, zero)
  					.mult(exerciseTrigger.sub(exerciseTriggerCap).mult(-1.0).choose(one, zero));
  			filter = filter.mult(filterNaN);
  			// Filter exerciseTrigger and regressionBasisFunctions
  			exerciseTrigger = exerciseTrigger.mult(filter);
  
  			RandomVariable[] regressionBasisFunctions			= regressionBasisFunctionsProvider != null ? regressionBasisFunctionsProvider.getBasisFunctions(evaluationTime, model) : getBasisFunctions(exerciseDate, model);
  			RandomVariable[] filteredRegressionBasisFunctions	= new RandomVariable[regressionBasisFunctions.length];
  			for(int i=0; i<regressionBasisFunctions.length; i++) {
  				filteredRegressionBasisFunctions[i] = regressionBasisFunctions[i].mult(filter);
  			}
  
  			// Remove foresight through conditional expectation
  			ConditionalExpectationEstimator conditionalExpectationOperator = new MonteCarloConditionalExpectationRegression(filteredRegressionBasisFunctions, regressionBasisFunctions);
  
  			// Calculate cond. expectation. Note that no discounting (numeraire division) is required!
  			exerciseTrigger         = exerciseTrigger.getConditionalExpectation(conditionalExpectationOperator);
  		}
  
  		// Apply exercise criteria
  		if(strikeProduct != null) {
  			values = exerciseTrigger.choose(values, strikeProduct.getValue(exerciseDate, model));
  		} else {
  			values = exerciseTrigger.choose(values, new Scalar(strikePrice));
  		}
  
  		// Discount to evaluation time
  		if(evaluationTime != exerciseDate) {
  			RandomVariable	numeraireAtEval			= model.getNumeraire(evaluationTime);
  			RandomVariable	numeraire				= model.getNumeraire(exerciseDate);
  			values = values.div(numeraire).mult(numeraireAtEval);
  		}
  
  		// Return values
  		return values;
  	}