OneDimensionalRiskFactorTreeModel.java
package net.finmath.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.function.DoubleUnaryOperator;
import net.finmath.montecarlo.RandomVariableFromDoubleArray;
import net.finmath.stochastic.RandomVariable;
/**
* This abstract class encapsulates the logic of one-dimensional trees for the simulation of a risk factor.
* At this level, the class could be used for equities or interest rates (e.g. the Hull-White short rate model).
*
* @author Carlo Andrea Tramentozzi
* @author Alessandro Gnoatto
*/
public abstract class OneDimensionalRiskFactorTreeModel implements TreeModel {
/** Cache of level spot S_k. */
private final List<RandomVariable> riskFactorLevels = new ArrayList<>();
/**
* Returns the number of states at level {@code k} (binomial: {@code k + 1}; trinomial: {@code 2k + 1}).
*
* @param k The level index.
* @return The number of states at level {@code k}.
*/
public abstract int statesAt(int k);
/**
* Builds all the realizations {@code X_k[i]}.
*
* @param k The level index.
* @return The spot (risk factor) values at level {@code k}.
*/
protected abstract RandomVariable buildSpotLevel(int k);
/**
* Discounted conditional expectation: from {@code v_{k+1}} to {@code v_k}.
*
* @param vNext The values at the next level.
* @param k The current level index.
* @return The conditional expectation.
*/
protected abstract RandomVariable conditionalExpectation(RandomVariable vNext, int k);
/**
* Builds (if missing) and returns {@code X_k} using the cache.
*
* @param k The level index.
* @return The risk factor at level {@code k}.
*/
protected final RandomVariable ensureRiskFactorLevelArray(int k) {
while(riskFactorLevels.size() <= k) {
final int next = riskFactorLevels.size();
riskFactorLevels.add(buildSpotLevel(next));
}
return riskFactorLevels.get(k);
}
@Override
public RandomVariable getTransformedValuesAtGivenTimeRV(final double time, final DoubleUnaryOperator transformFunction) {
int k = (int) Math.round(time / getTimeStep());
// Checking param to avoid out of bound exception.
if(k < 0) {
k = 0;
}
if(k > getNumberOfTimes() - 1) {
k = getNumberOfTimes() - 1;
}
final RandomVariable sRV = ensureRiskFactorLevelArray(k);
final double[] s = sRV.getRealizations();
final double[] v = new double[s.length];
for(int i = 0; i < s.length; i++) {
v[i] = transformFunction.applyAsDouble(s[i]);
}
return new RandomVariableFromDoubleArray(k * getTimeStep(), v);
}
@Override
public RandomVariable getConditionalExpectationRV(final RandomVariable vNext, final int k) {
final RandomVariable vK = conditionalExpectation(vNext, k); // hook
return new RandomVariableFromDoubleArray(k * getTimeStep(), vK.getRealizations());
}
@Override
public RandomVariable getSpotAtGivenTimeIndexRV(final int k) {
final RandomVariable sRV = ensureRiskFactorLevelArray(k);
return new RandomVariableFromDoubleArray(k * getTimeStep(), sRV.getRealizations());
}
}