FloatingStrikeAsianOption.java
package net.finmath.tree.assetderivativevaluation.products;
/**
* Floating-strike Asian option (CALL) on a full non-recombining tree (exponential growth).
*
* Payoff at maturity:
* <pre>
* max(S(T) - A, 0)
* </pre>
* where A is the arithmetic average of the spot over the fixingTimeIndices.
*
* State variables:
* <ul>
* <li>state[0] = running sum of fixing spots</li>
* <li>state[1] = fixing count</li>
* </ul>
*
* No recombination / compression:
* <ul>
* <li>Number of nodes at step j is B^j (B = branching factor of the model).</li>
* </ul>
*
* @author Alessandro Gnoatto
*/
public class FloatingStrikeAsianOption extends AbstractPathDependentProduct {
/**
* @param maturity Maturity in model time units.
* @param fixingTimeIndices Subset of model time indices included in the average.
*/
public FloatingStrikeAsianOption(
final double maturity,
final int[] fixingTimeIndices) {
super(maturity, fixingTimeIndices);
}
@Override
protected int getNumberOfStateVariables() {
return 2; // running sum, fixing count
}
@Override
protected void initializeState(
final double spotAtNode,
final int timeIndex,
final boolean isFixing,
final double[] stateOut) {
stateOut[0] = isFixing ? spotAtNode : 0.0; // sum
stateOut[1] = isFixing ? 1.0 : 0.0; // count (stored as double)
}
@Override
protected void evolveState(
final double[] parentState,
final double spotAtChild,
final int timeIndexChild,
final boolean isFixingChild,
final double[] childStateOut) {
childStateOut[0] = parentState[0] + (isFixingChild ? spotAtChild : 0.0);
childStateOut[1] = parentState[1] + (isFixingChild ? 1.0 : 0.0);
}
@Override
protected double payoff(
final double[] terminalState,
final double spotAtMaturity) {
final double sum = terminalState[0];
final double cnt = terminalState[1];
// Defensive guard: empty fixing set.
final double average = (cnt > 0.0) ? (sum / cnt) : 0.0;
// Floating-strike CALL payoff.
return Math.max(spotAtMaturity - average, 0.0);
}
}