finmath lib

repository·main·Indexed 20 days ago

https://github.com/finmath/finmath-lib

A comprehensive mathematical finance library for the JVM providing implementations for stochastic modeling, derivative valuation, curve calibration, and numerical algorithms. It supports analytic formulas, Fourier transforms, finite difference methods, and Monte-Carlo simulations. Key features include Stochastic Automatic Differentiation (AAD), GPGPU acceleration via CUDA, and climate modeling via the DICE model. The library supports Java 11, Java 8, and Java 6, and is distributed through Maven Central.

Tokens
9.5K
Snippets
22
Records
55
Agent score
67%

What's inside finmath-lib

  1. Overview of finmath lib capabilities

    main

    finmath lib is a mathematical finance library providing JVM implementations of various financial methodologies. Key capabilities include:

    • Analytic Formulas: Distributions (Normal, Gamma, etc.) and Models (Black Scholes, Bachelier, SABR, ZABR, CEV).
    • Numerical Algorithms: Random number generation and optimization (Levenberg–Marquardt).
    • Valuation Methods:
      • Fourier transforms / characteristic functions: Black-Scholes, Heston, Bates, Merton, and Variance Gamma models.
      • Finite difference methods: Theta-scheme for Black-Scholes and CEV models.
      • Monte-Carlo simulation: Multi-dimensional SDEs (Hull-White, LIBOR Market Model, Heston, etc.) and American Monte-Carlo.
    • Calibration: Interest rate curves (OIS, basis-swaps), bond curves, and volatility surfaces (SABR smile, Swaption cubes).
    • Advanced Features:
      • Stochastic Automatic Differentiation (AAD): Located in net.finmath.montecarlo.automaticdifferentiation.
      • GPGPU Acceleration: Monte-Carlo simulations via CUDA (requires finmath-lib-cuda-extensions).
      • Climate Modeling: DICE model via net.finmath.climate.
  2. Use DescribedModel and DescribedProduct for construction

    main

    In version 3.2.10, the library introduced dedicated interfaces for constructing models and products from descriptors. This follows the 'separation of product and model' concept.

    • DescribedModel<T extends ModelDescriptor>
    • DescribedProduct<T extends ProductDescriptor>

    These allow for more structured construction of complex financial instruments and models using their respective descriptor types.

  3. Use the Model interface for market descriptions

    main

    The Model interface is a marker interface used to represent different market environments and numerical frameworks. Depending on the required valuation method, you will interact with specific sub-interfaces:

    Monte Carlo Models

    • MonteCarloSimulationModel: Provides discretization parameters, number of paths, random variable generators, and weights via getTimeDiscretization(), getNumberOfPaths(), getRandomVariableForConstant(), and getMonteCarloWeights().
    • AssetModelMonteCarloSimulationModel: An extension for equity models providing getNumeraire() and getAsset().
    • TermStructureMonteCarloSimulationModel: An extension for interest rate models providing getNumeraire() and getLIBOR(double, double, double).

    Fourier Transform Models

    • CharacteristicFunctionModel (in package net.finmath.fouriermethod): Provides the apply(double) method which returns a CharacteristicFunction.
  4. Implement against interfaces in finmath-lib

    main

    To ensure flexibility and allow for easy implementation changes, always write code against interfaces rather than concrete implementations. This means the left-hand side of an assignment, method arguments, and return types should ideally be interface types.

    Note on Type Inference: While Java's var keyword is available, it is currently avoided in this library. Explicitly specifying the interface type improves readability by allowing developers to understand the object's contract without needing to infer the specific implementation from the constructor.

    // Recommended: Use interface on the left-hand side
    List<Double> list = new ArrayList<Double>();
    
    // Avoid: Using concrete implementation on the left-hand side
    ArrayList<Double> list = new ArrayList<Double>();
    
    // Avoid: Using 'var' (type inference)
    var list = new ArrayList<Double>();
  5. Extend finmath lib with CUDA or AAD

    main

    You can extend the library's functionality using specialized extensions:

    • CUDA GPU Acceleration: Use finmath-lib-cuda-extensions to implement the RandomVariable interface via CUDA. This allows Monte-Carlo simulations to run on GPUs by replacing the random variable factory.
    • Automatic Differentiation (AAD): Use finmath-lib-automaticdifferentiation-extensions to implement RandomVariableInterface with AAD enabled. (Note: Since version 3.3.1, AAD is included in the core finmath-lib package).
  6. Understand the Java 11 and Java 8 source structure

    main

    The library provides two versions of the codebase to support different environments:

    • Java 11 (Default): Located in src/main/java. This is the primary version and will receive new features first.
    • Java 8: Located in src/main/java8. This version is maintained for compatibility where possible.

    When working with the source code, ensure you are targeting the correct directory based on your required Java runtime version.

  7. Follow naming conventions for classes and variables

    main

    Names should be as descriptive as possible, using camel notation from general to specific properties, appending implementation details at the end.

    Naming Patterns

    • Interfaces: Use names describing the core concept (e.g., BrownianMotion, RandomVariable).
    • Implementations: Use the interface name followed by the implementation aspect (e.g., RandomVariableFromDoubleArray).
    • Collections: Use the plural of the item (e.g., periods) or the collection type as a suffix for clarity (e.g., sensitivityMap).
    • Arguments: When constructor or setter arguments are used to set fields, use the same name for both the field and the argument.

    Avoid Reassignment

    Do not reassign a reference in a way that alters its semantic meaning. If a calculation requires a different meaning, use a new variable name.

    // Correct: Using distinct names for different meanings
    var forwardBond = (1 + forwardRate * periodLength);
    var discountFactor = 1.0 / forwardBond;
    
    // Wrong: Reassigning a variable to a different meaning
    var discountFactor = (1 + forwardRate * periodLength);
    discountFactor = 1.0 / discountFactor;
  8. How automatic tracking of measurability works

    main

    Automatic tracking of measurability is a feature in finmath-lib that allows random variables to inspect when they become measurable with respect to a filtration $\mathcal{F}_t$.

    Concept

    For any random variable $X$, there exists a filtration time $T(X)$ such that for all $t \ge T(X)$, $X$ is guaranteed to be $\mathcal{F}_t$-measurable. This is implemented using a mechanism similar to forward-mode automatic differentiation, where every operator on random variables is augmented with an operation that tracks the filtration time.

    Rules for Filtration Time $T(X)$:

    • Constants (Deterministic): $T(C) = -\infty$
    • Brownian Increments: For $W(t+\Delta t) - W(t)$, the filtration time is $t+\Delta t$.
    • Operators: For an operator $f(X_1, ..., X_n) = Z$, the filtration time is $T(Z) = \max(T(X_1), ..., T(X_n))$.

    Optimization Benefit

    This tracking allows for optimizations in stochastic automatic differentiation. Specifically, it can detect when the computationally expensive conditional expectation operator can be bypassed using the identity: $$E(X | \mathcal{F}_t) = X \text{ if } t \ge T(X)$$ If the current time $t$ is already greater than or equal to the tracked filtration time of $X$, the conditional expectation is simply $X$ itself.

  9. How Models and Products are separated in finmath-lib

    main

    The library uses a decoupled architecture to separate the mathematical description of a market (the Model) from the financial instrument being valued (the Product).

    This separation allows for a combinatorial approach to valuation:

    1. Models define asset classes (e.g., single asset, interest rate term structures), numerical methods (e.g., Monte Carlo, Fourier Transform, Finite Difference), and specific modeling assumptions.
    2. Products define the payoff structure and use double-dispatch via the getValue(Model<?> model) method. This means a product implementation will inspect the type of the provided model (e.g., casting to a MonteCarloSimulationModel) to determine the appropriate valuation logic.

    Common pairings include:

    • Analytic: AnalyticModel + AnalyticProduct
    • Monte Carlo (Equity): AssetModelMonteCarloSimulationModel + AssetMonteCarloProduct
    • Monte Carlo (Interest Rates): TermStructureMonteCarloSimulationModel + TermStructureMonteCarloProduct
    • Fourier Transform: CharacteristicFunctionModel + FourierTransformProduct
  10. How stochastic automatic differentiation (AAD) works in finmath-lib

    main

    The library implements stochastic automatic differentiation (AAD) by extending the standard RandomVariable interface with RandomVariableDifferentiable. This allows for fast, memory-efficient, and thread-safe automatic differentiation of conditional expectations (e.g., in American Monte-Carlo contexts).

    Key Abstractions

    • RandomVariableDifferentiable: An interface that extends RandomVariable. It supports standard arithmetic operations (like add, mult, exp) and provides methods to retrieve gradients.
    • RandomVariableDifferentiableAADFactory: A factory used to create RandomVariableDifferentiable instances using the backward (adjoint) method.
    • RandomVariableDifferentiableAAD: The implementation class containing the backward automatic differentiation logic.

    Retrieving Gradients

    To obtain the first-order differentiation of a random variable with respect to all its input leaf nodes, use getGradient(). To find the derivative with respect to a specific input, use the input's unique ID.

    /* Get the gradient of X with respect to all its leaf nodes */
    Map<Long, RandomVariable> gradientOfX = X.getGradient();
    
    /* Get the derivative of X with respect to Y */
    RandomVariable derivative = gradientOfX.get(Y.getID());
    /* Get the gradient of X with respect to all its leaf nodes: */
    Map<Long, RandomVariable> gradientOfX = X.getGradient();
    
    /* Get the derivative of X with respect to Y: */
    RandomVariable derivative = gradientOfX.get(Y.getID());