FiniteDifferenceEquityModel.java
package net.finmath.finitedifference.assetderivativevaluation.models;
import java.util.Optional;
import net.finmath.finitedifference.FiniteDifferenceModel;
import net.finmath.finitedifference.assetderivativevaluation.boundaries.FiniteDifferenceBoundary;
import net.finmath.finitedifference.grids.SpaceTimeDiscretization;
import net.finmath.marketdata.model.curves.DiscountCurve;
/**
* Interface for a finite-difference equity model.
*
* <p>
* Implementations provide the coefficients and market data required by the
* finite-difference solvers, in particular discount curves, drift coefficients,
* factor loadings, boundary conditions, and the initial state.
* </p>
*
* <p>
* The framework is formulated in terms of the <i>chosen PDE state
* variables</i>.
* It does <b>not</b> assume that the first spatial coordinate is necessarily
* the
* spot price {@code S}. It may instead be {@code S}, {@code log(S)}, or any
* other state variable for which the model provides consistent coefficients.
* </p>
*
* <p>
* Therefore, {@link #getDrift(double, double...)} and
* {@link #getFactorLoading(double, double...)} must return coefficients that
* are
* expressed in exactly the same coordinates as those used in the space-time
* discretization.
* </p>
*
* <p>
* Example:
* </p>
* <ul>
* <li>if the grid variable is {@code S}, then the drift and factor loadings
* should correspond to the SDE for {@code S},</li>
* <li>if the grid variable is {@code log(S)}, then the drift and factor
* loadings should correspond to the SDE for {@code log(S)}.</li>
* </ul>
*
* <p>
* The interface is dimension agnostic: it supports one-dimensional and
* multi-dimensional equity models alike. In particular, multi-asset models may
* provide one dividend-yield curve per underlying via
* {@link #getDividendYieldCurves()}.
* </p>
*
* @author Alessandro Gnoatto
*/
public interface FiniteDifferenceEquityModel extends FiniteDifferenceModel, FiniteDifferenceBoundary {
/**
* Returns the risk-free discount curve used for pricing.
*
* @return The risk-free discount curve.
*/
DiscountCurve getRiskFreeCurve();
/**
* Returns the dividend-yield discount curve.
*
* <p>
* This is the legacy single-asset accessor and remains part of the
* interface to
* preserve backward compatibility with the current code base.
* </p>
*
* <p>
* For true multi-asset models with one dividend curve per underlying,
* prefer
* {@link #getDividendYieldCurves()}. Such models may override this method
* with a
* convention suitable for backward compatibility.
* </p>
*
* @return The dividend-yield discount curve.
*/
DiscountCurve getDividendYieldCurve();
/**
* Returns the dividend-yield discount curves of the model.
*
* <p>
* The default implementation preserves backward compatibility with the
* current
* single-asset code base by wrapping {@link #getDividendYieldCurve()} into
* a
* one-element array.
* </p>
*
* <p>
* Multi-asset models should override this method and return one dividend-
* yield
* curve per underlying asset, ordered consistently with the model state
* vector.
* </p>
*
* @return The dividend-yield discount curves.
*/
default DiscountCurve[] getDividendYieldCurves() {
return new DiscountCurve[] {getDividendYieldCurve() };
}
/**
* Returns the drift vector of the model state variables.
*
* <p>
* The returned coefficients must be expressed in the same coordinates as
* the PDE
* state variables used by the finite-difference solver.
* </p>
*
* <p>
* If the state vector is {@code X = (X1, ..., Xn)}, then this method
* returns the
* vector {@code mu(t, X)} in
* </p>
*
* <p>
* {@code dX_i(t) = mu_i(t, X_t) dt + ...}.
* </p>
*
* @param time The evaluation time.
* @param stateVariables The current values of the model state variables.
* @return The drift vector.
*/
double[] getDrift(double time, double... stateVariables);
/**
* Returns the factor-loading matrix of the model state variables.
*
* <p>
* The returned coefficients must be expressed in the same coordinates as
* the PDE
* state variables used by the finite-difference solver.
* </p>
*
* <p>
* If the state vector is {@code X = (X1, ..., Xn)}, then this method
* returns the
* matrix {@code b(t, X)} in
* </p>
*
* <p>
* {@code dX_i(t) = mu_i(t, X_t) dt + sum_j b_{i,j}(t, X_t) dW_j(t)}.
* </p>
*
* @param time The evaluation time.
* @param stateVariables The current values of the model state variables.
* @return The factor-loading matrix.
*/
double[][] getFactorLoading(double time, double... stateVariables);
/**
* Returns the optional jump component of the infinitesimal generator.
*
* <p>
* The default implementation returns {@link Optional#empty()},
* corresponding to a
* purely diffusive model.
* </p>
*
* <p>
* If present, the returned {@link JumpComponent} provides the data needed
* to
* assemble the non-local jump part of the generator. The local coefficients
* returned by {@link #getDrift(double, double...)} and
* {@link #getFactorLoading(double, double...)} keep their current meaning
* and
* should remain consistent with the PDE state variables used by the
* finite-difference discretization.
* </p>
*
* <p>
* In particular, under the stock-coordinate convention intended for jump
* models in
* this framework, {@link #getDrift(double, double...)} should continue to
* return
* the drift of the local first-order term, while the jump component defines
* the
* non-local operator in compensated form.
* </p>
*
* <p>
* For a one-dimensional spot variable {@code S}, the jump contribution is
* understood in the form
* </p>
*
* <pre>
* integral [ f(S exp(y)) - f(S) - S (exp(y) - 1) f'(S) ] nu(dy).
* </pre>
*
* <p>
* The interpretation of the jump data must remain consistent with the
* chosen PDE
* state variables.
* </p>
*
* @return An {@link Optional} containing the jump component of the
* infinitesimal
* generator, or {@link Optional#empty()} if the model has no jump part.
*/
default Optional<JumpComponent> getJumpComponent() {
return Optional.empty();
}
/**
* Returns a clone of this model with a modified space-time discretization.
*
* <p>
* The returned model should represent the same stochastic dynamics and
* market
* data as the original one, but on the provided discretization.
* </p>
*
* @param newSpaceTimeDiscretization The new space-time discretization.
* @return A clone of this model with the modified discretization.
*/
FiniteDifferenceEquityModel getCloneWithModifiedSpaceTimeDiscretization(
SpaceTimeDiscretization newSpaceTimeDiscretization);
/**
* Returns the initial state vector of the model.
*
* <p>
* The returned values must be consistent with the state variables used by
* the
* PDE. For example, if the first spatial coordinate is {@code log(S)}, then
* the
* first component should be {@code log(S0)} rather than {@code S0}.
* </p>
*
* @return The initial state vector.
*/
double[] getInitialValue();
}