AmericanNonPathDependent.java
package net.finmath.tree.assetderivativevaluation.products;
import java.util.function.DoubleUnaryOperator;
import net.finmath.stochastic.RandomVariable;
import net.finmath.tree.TreeModel;
/**
* American (non–path-dependent) option priced on a recombining TreeModel.
* The product allows early exercise at every lattice time prior to maturity.
* At each step k it compares:
* Continuation value: discounted conditional expectation
* E^Q[V_{k+1} | F_k] provided by the model, and
* Immediate exercise value: f(S_k).
* The option value is the pointwise maximum of the two (early exercise rule).
*/
public class AmericanNonPathDependent extends AbstractNonPathDependentProduct {
private final DoubleUnaryOperator payOffFunction;
/**
* Creates an American option with given maturity and payoff.
*
* @param maturity Contract maturity (model time units).
* @param payOffFunction Payoff function f(S) (e.g.,s -> Math.max(K - s, 0.0) for a put).
*/
public AmericanNonPathDependent(double maturity, DoubleUnaryOperator payOffFunction) {
super(maturity);
this.payOffFunction = payOffFunction;
}
/**
* Performs backward induction with early exercise:
* Set terminal values at maturity: levels[n-k0] = f(S_T).
* For k = n-1,...,k0:
* Continuation: continuation = DF * E^Q[ levels[k+1-k0] | F_k ] via getConditionalExpectationRV(RandomVariable, int)
* Exercise: exercise = f(S_k) via getSpotAtGivenTimeIndexRV(int).
* American rule: levels[k-k0] = max(continuation, exercise).
*
* @param evaluationTime The time at which the value is requested (typically 0.0).
* @param model The tree model (spot lattice, discounting, conditional expectations).
* @return Array of value random variables from index k0 to n;
*/
@Override
public RandomVariable[] getValues(double evaluationTime, TreeModel model) {
final int k0 = timeToIndex(evaluationTime, model);
final int n = model.getNumberOfTimes() - 1;
final RandomVariable[] levels = new RandomVariable[n - k0 + 1];
levels[n - k0] = model.getTransformedValuesAtGivenTimeRV(model.getLastTime(), getPayOffFunction());
for (int k = n - 1; k >= k0; --k) {
final RandomVariable continuation = model.getConditionalExpectationRV(levels[(k + 1) - k0], k);
final RandomVariable spotK = model.getSpotAtGivenTimeIndexRV(k);
final RandomVariable exercise = spotK.apply(getPayOffFunction());
levels[k -k0] = continuation.floor(exercise);
}
return levels;
}
@Override
public DoubleUnaryOperator getPayOffFunction() {
return this.payOffFunction;
}
}