Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/main/java/net/finmath/tree/AbstractTreeProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package net.finmath.tree;

import net.finmath.stochastic.RandomVariable;

/**
* Base class for products that can be priced on a (recombining) with TreeModel.
* This abstraction provides a small template:
* getValue(TreeModel) returns the scalar time–0 price.
* getValue(double, TreeModel) returns the value as a RandomVariable at a given evaluation time.
* getValues(double, TreeModel) must be implemented by subclasses and
* should return the full vector of values (per state) at each time level,
* produced by a backward induction. By convention the element at index
* 0 corresponds to time 0.
* Subclasses (e.g. European, American, Asian ) implement their
* payoff logic and early–exercise features within getValues(double, TreeModel).
*/

public abstract class AbstractTreeProduct implements TreeProduct {

/** Contract maturity (in model time units). */
private final double maturity;

/**
* Creates a tree-priced product with the given maturity.
*
* @param maturity The contract maturity
* must be compatible with the model time grid.
*/
public AbstractTreeProduct(double maturity){
this.maturity = maturity;
}

/**
* Returns the time–0 present value under the given model
* This is a convenience method delegating to getValue(double, TreeModel)}ù
* with evaluationTime = 0.0 and extracting the scalar value from
* the returned RandomVariable.
*
* @param model The tree model to use (providing discounting and conditional expectations).
* @return The time–0 price.
* @throws IllegalArgumentException If model is null or the evaluation fails.
*/
@Override
public double getValue(TreeModel model ){
RandomVariable v0 = getValue(0.0,model);
return v0.get(0);
}
/**
* Returns the product value at a given evaluation time as a RandomVariable.
* The default implementation calls getValues(double, TreeModel) and
* returns the first component (time–level 0). Subclasses should ensure
* their {@link #getValues(double, TreeModel)} respects this convention.
*
* @param evaluationTime The time at which the value is requested (must be >= 0).
* @param model The tree model to use.
* @return The value at evalutationTime as a random variable on the tree.
* @throws IllegalArgumentException If the inputs are invalid (see validate(double, TreeModel)).
*/
public RandomVariable getValue(double evaluationTime ,TreeModel model) {
RandomVariable[] levels = getValues(evaluationTime,model);
return levels[0];
}

/**
* Computes the vector of values at each time/state on the tree (via backward induction)
* Implementations should:
* Validate inputs via validate(double, TreeModel).
* Return an array whose element at index k is a RandomVariable
* representing the value at time level k (with length equal to the number of states at that level).
*
* @param evaluationTime The time at which valuation is performed
* @param model The tree model (spot lattice, discounting, conditional expectation).
* @return An array of value random variables, one per time level, indexed from 0 to maturity level.
*/
public abstract RandomVariable[] getValues(double evaluationTime, TreeModel model);

/**
* Basic input validation helper used by implementations.
*
* @param t The evaluation time (must be >= 0).
* @param m The model (must not be null).
* @throws IllegalArgumentException If {@code m == null} or {@code t < 0}.
*/
protected void validate(double t, TreeModel m) {
if(m == null) throw new IllegalArgumentException("model null");
if(t < 0) throw new IllegalArgumentException("evaluationTime < 0");
}


/**
* Returns the contract maturity.
*
* @return The maturity T.
*/
protected double getMaturity(){
return maturity;
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
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, Alessandro Gnoatto
*/
public abstract class OneDimensionalRiskFactorTreeModel implements TreeModel {

/** Cache of level spot S_k */
private final List<RandomVariable> riskFactorLevels = new ArrayList<>();

/**
* Return number of states at level k (binomial: k+1; trinomial: 2k+1)
* @param k
* @return number of states at level k
*/
public abstract int statesAt(int k);

/**
* Builds all the realizations X_k[i]
* @param k
* @return
*/
protected abstract RandomVariable buildSpotLevel(int k);


/**
* Discounted Conditional expectation: from v_{k+1} (array) to v_k (array)
* @param vNext
* @param k
* @return the conditonal expectation
*/
protected abstract RandomVariable conditionalExpectation(RandomVariable vNext, int k);


/**
* Builds (if missing) and return X_k as array, using cache.
* @param k
* @return the risk factor at level k
*/
protected final RandomVariable ensureRiskFactorLevelArray(int k) {
while(riskFactorLevels.size() <= k) {
int next = riskFactorLevels.size();
riskFactorLevels.add(buildSpotLevel(next));
}
return riskFactorLevels.get(k);
}

@Override
public RandomVariable getTransformedValuesAtGivenTimeRV(double time, 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;

RandomVariable sRV = ensureRiskFactorLevelArray(k);
double[] s = sRV.getRealizations();
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(RandomVariable vNext, int k) {
RandomVariable vK = conditionalExpectation(vNext, k); // hook
return new RandomVariableFromDoubleArray(k * getTimeStep(), vK.getRealizations());
}

@Override
public RandomVariable getSpotAtGivenTimeIndexRV(int k) {
RandomVariable sRV = ensureRiskFactorLevelArray(k);
return new RandomVariableFromDoubleArray(k * getTimeStep(), sRV.getRealizations());
}

}
59 changes: 59 additions & 0 deletions src/main/java/net/finmath/tree/TreeModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package net.finmath.tree;

import net.finmath.modelling.Model;
import net.finmath.stochastic.RandomVariable;
import java.util.function.DoubleUnaryOperator;

/**
* General interface rappresenting a tree model with all the common methods
*
* @author Carlo Andrea Tramentozzi
* @version 1.0
*/

public interface TreeModel extends Model {

double getTimeStep();
int getNumberOfTimes();


/**
* 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 (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);


/** Getter */
//double getInitialPrice();
//double getRiskFreeRate();
//double getVolatility();
double getLastTime();


}
23 changes: 23 additions & 0 deletions src/main/java/net/finmath/tree/TreeProduct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.finmath.tree;

/**
* Contract for a product that can be priced on a (recombining) tree model.
* Implementations encapsulate the payoff and exercise style
* (e.g. European, American, path-dependent) and use the TreeModel's
* risk-neutral dynamics and discounting to compute a present value.
* */

public interface TreeProduct {

/**
* Prices this product under the given tree model.
*
* @param model
* The tree model providing spot levels, discounting and
* conditional expectations (e.g. CRR, Jarrow–Rudd, Leisen–Reimer,
* or a trinomial model); must not be {@code null}.
* @return The present value (time 0) of the product under {@code model},
* in the same currency units as the model’s numéraire.
*/
double getValue(TreeModel model );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package net.finmath.tree.assetderivativevaluation;

import net.finmath.montecarlo.RandomVariableFromDoubleArray;
import net.finmath.stochastic.RandomVariable;
import net.finmath.tree.OneDimensionalRiskFactorTreeModel;
import java.util.ArrayList;
import java.util.List;

/**
*
* This class represent the recombining tree model, a general abstract class which collect the common properties
* about recombining trees.
*
* @author Carlo Andrea Tramentozzi
* @version 1.0
*/

public abstract class AbstractRecombiningTreeModel extends OneDimensionalRiskFactorTreeModel implements OneDimensionalAssetTreeModel {

/** Common parameters of the model */
private final double initialPrice;
private final double riskFreeRate;
private final double volatility;

/** Temporal discretization */
private final double timeStep;
private final double lastTime;
private final int numberOfTimes;
/** Cache of level spot S_k */
private final List<RandomVariable> spotLevels = new ArrayList<>();

/**
* Constructs a recombining tree model on an equidistant time grid by
* specifying the time step.
* The constructor sets the common model parameters, computes
* the number of time points and initializes the level-0 cache of
* spot values with S_0.
* @param initialPrice The initial asset price S0
* @param riskFreeRate The continuously compounded risk-free rate r used consistently with df().
* @param volatility The volatility.
* @param lastTime The final time T of the grid.
* @param timeStep The time step Δt between consecutive grid points
*/
public AbstractRecombiningTreeModel(double initialPrice, double riskFreeRate, double volatility, double lastTime, double timeStep) {
this.initialPrice = initialPrice;
this.riskFreeRate = riskFreeRate;
this.volatility = volatility;
this.lastTime = lastTime;
this.timeStep = timeStep;
int steps = (int)Math.round(lastTime / timeStep);
this.numberOfTimes = steps + 1;
spotLevels.add(new RandomVariableFromDoubleArray(0.0, new double[] { initialPrice }));
}

/**
* Constructs a recombining tree model on an equidistant time grid by
* specifying the time step.
* The constructor sets the common model parameters , computes
* the number of time points and initializes the level-0 cache of
* spot values with S_0.
* @param initialPrice The initial asset price S₀.
* @param riskFreeRate The continuously compounded risk-free rate r used consistently with df().
* @param volatility The (log) volatility σ.
* @param lastTime The final time T of the grid.
* @param numberOfTimes The total number of grid points N (must be ≥ 2). The number of steps is N−1.
*/
public AbstractRecombiningTreeModel(double initialPrice, double riskFreeRate, double volatility, double lastTime, int numberOfTimes) {
this.initialPrice = initialPrice;
this.riskFreeRate = riskFreeRate;
this.volatility = volatility;
this.lastTime = lastTime;
this.numberOfTimes = numberOfTimes;
this.timeStep = lastTime / (numberOfTimes - 1);

spotLevels.add(new RandomVariableFromDoubleArray(0.0, new double[] { initialPrice }));
}


/** One step discount factor(according to q): continuous */
protected final double df() {
return Math.exp(-riskFreeRate * timeStep);
}



/** Getter */
@Override
public double getInitialPrice() { return initialPrice; }
@Override
public double getRiskFreeRate() { return riskFreeRate; }
@Override
public double getVolatility() { return volatility; }

public double getTimeStep() { return timeStep; }
public double getLastTime() { return lastTime; }
public int getNumberOfTimes() { return numberOfTimes; }
public double getSpot() {return getInitialPrice(); } //Redefinition


}
Loading