TreeModel.java

package net.finmath.tree;

import java.util.function.DoubleUnaryOperator;

import net.finmath.modelling.Model;
import net.finmath.stochastic.RandomVariable;

/**
 * General interface rappresenting a tree model with all the common methods
 *
 * @author Carlo Andrea Tramentozzi
 * @author Alessandro Gnoatto
 * @author Andrea Mazzon
 * @version 1.0
 */
public interface TreeModel extends Model {

	double getTimeStep();
	int getNumberOfTimes();
	double getLastTime();

	/**
	 * Returns the spot process at a given time transformed pointwise by a function.
	 * Equivalent to getSpotAtGivenTimeIndexRV(k).apply(transformFunction), but accepts a physical time.
	 *
	 * @param timeindex  Physical time t; the model maps it to the nearest lattice index k (e.g. round(t/dt)).
	 * @param transformFunction  Function f(s) applied element-wise to S_k.
	 * @return A RandomVariable at time k with length = number of states at level k
	 *         (binomial: k+1; trinomial: 2k+1), containing f(S_k) pathwise.
	 */
	RandomVariable getTransformedValuesAtGivenTimeRV(double timeindex, DoubleUnaryOperator transformFunction);

	/**
	 * One-step risk-neutral discounted conditional expectation operator.
	 * Takes values defined at level k+1 and projects them back to level k:
	 *   V_k = E^Q[ V_{k+1} | F_k ] * DF  (DF is the one-step discount factor).
	 *
	 * @param optionValues  RandomVariable living at level k+1.
	 * @param timeindex     Level k to which the conditional expectation is taken ({@code 0 ≤ k < n}).
	 * @return A RandomVariable at level k with length matching the number of states at k.
	 */
	RandomVariable getConditionalExpectationRV(RandomVariable optionValues, int timeindex);

	/**
	 * Returns the spot vector S_k as a RandomVariable at lattice level k.
	 *
	 * @param timeindex  Level index k (0…n).
	 * @return A RandomVariable carrying S_k pathwise; length = number of states at level k
	 *         (binomial: k+1; trinomial: 2k+1). The time stamp is typically t_k = k*dt.
	 */
	RandomVariable getSpotAtGivenTimeIndexRV(int timeindex);

	/**
	 * Returns the number of outgoing branches from a node at time index k.
	 * <p>
	 * This method is intentionally defined per node to allow state-dependent branching
	 * (e.g. for trinomial with pruning, multinomial with barriers, etc.). For standard
	 * binomial / trinomial recombining trees this is constant (2 / 3) and independent
	 * of {@code stateIndex}.
	 *
	 * @param timeIndex  The time index k ({@code 0 ≤ k < n}).
	 * @param stateIndex The node / state index at time k (model-defined).
	 * @return The number of branches from that node to time k+1.
	 */
	default int getNumberOfBranches(int timeIndex, int stateIndex) {
		throw new UnsupportedOperationException("Transition API not implemented by this TreeModel.");
	}

	/**
	 * Returns the risk-neutral transition probability for a branch.
	 * Branch indices are model-defined but should be consistent with how the model
	 * evolves the risk factor (e.g. for binomial: 0=up,1=down; for trinomial: 0=up,1=mid,2=down).
	 *
	 * @param timeIndex   The time index k ({@code 0 ≤ k < n}).
	 * @param stateIndex  The node / state index at time k (model-defined).
	 * @param branchIndex The branch index in {@code [0, getNumberOfBranches(k,i))}.
	 * @return Transition probability to the corresponding child on level k+1.
	 */
	default double getTransitionProbability(int timeIndex, int stateIndex, int branchIndex) {
		throw new UnsupportedOperationException("Transition API not implemented by this TreeModel.");
	}

	/**
	 * One-step discount factor from time k to k+1 (applied when taking the conditional expectation).
	 * For example, for a constant short rate r and step dt, DF = exp(-r*dt).
	 *
	 * @param timeIndex The time index k ({@code 0 ≤ k < n}).
	 * @return One-step discount factor DF(k,k+1).
	 */
	default double getOneStepDiscountFactor(int timeIndex) {
		throw new UnsupportedOperationException("Transition API not implemented by this TreeModel.");
	}


	/**
	 * Returns the model's child-index shift convention for recombining state indices.
	 *
	 * Convention: childIndex = parentIndex + shift[branchIndex].
	 *
	 * Examples:
	 *  - Binomial CRR/JR: {0, 1} interpreted as {up, down}
	 *  - Trinomial Boyle: {0, 1, 2} interpreted as {up, mid, down}
	 *
	 * Path-dependent products that build a full non-recombining tree (exponential growth)
	 * can use this to map their parent recombining state index to the child's recombining
	 * state index when querying model spots.
	 *
	 * Default throws: models supporting path-dependent products should override this.
	 *
	 * @return shift array of length = number of branches.
	 */
	default int[] getChildStateIndexShift() {
		throw new UnsupportedOperationException("Child state index shift not implemented by this TreeModel.");
	}

}