All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.finmath.montecarlo.interestrate.models.funding.FundingCapacityWithoutMemory Maven / Gradle / Ivy

package net.finmath.montecarlo.interestrate.models.funding;

import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

import net.finmath.exception.CalculationException;
import net.finmath.montecarlo.interestrate.TermStructureMonteCarloSimulationModel;
import net.finmath.montecarlo.interestrate.products.components.AbstractProductComponent;
import net.finmath.stochastic.RandomVariable;
import net.finmath.stochastic.Scalar;

/**
 * Models the notional dependent survival probability and default compensation
 * of a funding capacity (funding provider)
 * using a piecewise constant function for the instantaneous survival probability.
 *
 * The piecewise constant instantaneous survival probability has to be provided
 * by a SortedMap<Double, Double> instantaneouseSurvivalProbability.
 *
 * This map defines the mapping \( x_{i} \mapsto q_{i} \). Defining
 * \[ q(x) = q_{i} \text{\ for\ } x \in (x_{i-1}-x_{i}] \] the
 * getDefaultFactors method of this class calculates
 * for a given argument \( (t,x) \):
 * 
*
* the effective survival probability *
*
* \[ \frac{1}{x} \int_{a}^{a+x} q(\xi) \mathrm{d}\xi \], * * where a denotes the current level of fund provided by this capacity, and *
*
* the effective default compensation factor R, such that *
*
* \[ \frac{1}{x} \int_{a}^{a+R x} q(\xi) \mathrm{d}\xi \ = \ 1 \], *
*
* * Important: * *
    *
  • * Since the class keeps track of past fundings * used, it is mandatory that the factors are calculated in * time-sequential order. *
  • *
  • * The map instantaneouseSurvivalProbability \( x_{i} \mapsto q_{i} \) * defines the survival probability for \( (x_{i-1},x_{i} \). * * For funding above the last discretization point \( x_{n-1} \) a value of \( q_{n} = 0 \) * is used. * Hence, to avoid this extrapolation, set a very large value of \( x_{n-1} \), e.g. * Double.MAX_VALLUE *
  • *
* * @author Christian Fries */ public class FundingCapacityWithoutMemory extends AbstractProductComponent implements FundingCapacity { private static final long serialVersionUID = 6863200178588875665L; private final SortedMap instantaneousSurvivalProbability; private Double currentTime; private RandomVariable currentCapacity; public FundingCapacityWithoutMemory(String currency, RandomVariable intialCapacity, SortedMap instantaneouseSurvivalProbability) { super(currency); this.currentTime = 0.0; this.currentCapacity = intialCapacity; this.instantaneousSurvivalProbability = instantaneouseSurvivalProbability; } /** * Apply a new funding requirement to this funding capacity * and return the associated DefaultFactors. * * @param time The time at which the funding is required. * @param fundingRequirement The required funding. * @return A DefaultFactors that reflects the amount that has to be contracted to secure the funding. */ @Override public DefaultFactors getDefaultFactors(double time, RandomVariable fundingRequirement) { /* * Determine integral bounds (synchronized for thread safety) */ RandomVariable fundingIntervalLeft, fundingIntervalRight; synchronized (currentTime) { if(time < currentTime) { throw new IllegalStateException("The method must be called in time-successive order."); } currentTime = time; /* * The fundingRequirement may be negative, in which case funding is returned to the provider. * We first calculate the lower and upper integral bounds from the fundingRequirement. * The integral calculated is always positive, since we require only the factor. */ final RandomVariable newCapacity = currentCapacity.add(fundingRequirement); fundingIntervalLeft = currentCapacity.cap(newCapacity); // min(current,new) fundingIntervalRight = currentCapacity.floor(newCapacity); // max(current,new) } RandomVariable integratedSurvivalProbability = new Scalar(0.0); RandomVariable integratedDefaultCompensation = new Scalar(0.0); double previousFundingLevel = -Double.MAX_VALUE; double previousProvidedLevel = -Double.MAX_VALUE; for(final Map.Entry entry : instantaneousSurvivalProbability.entrySet()) { final double fundingLevel = entry.getKey(); final double survivalProbability = entry.getValue(); final double providedLevel = Math.max(previousProvidedLevel,0) + (fundingLevel-Math.max(previousFundingLevel,0)) * survivalProbability; integratedDefaultCompensation = integratedDefaultCompensation.add( fundingIntervalRight.cap(providedLevel) .sub(fundingIntervalLeft.floor(previousProvidedLevel)) .floor(0.0) .div(survivalProbability)); integratedSurvivalProbability = integratedSurvivalProbability.add( fundingIntervalRight.cap(fundingLevel) .sub(fundingIntervalLeft.floor(previousFundingLevel)) .floor(0.0) .mult(survivalProbability)); previousFundingLevel = fundingLevel; previousProvidedLevel = providedLevel; } // The cap is used to map to avoid 0*infty to zero. final RandomVariable oneOverFundingAmount = fundingIntervalRight.sub(fundingIntervalLeft).invert().cap(Double.MAX_VALUE); integratedSurvivalProbability = integratedSurvivalProbability.mult(oneOverFundingAmount); integratedDefaultCompensation = integratedDefaultCompensation.mult(oneOverFundingAmount); return new DefaultFactors(integratedSurvivalProbability, integratedDefaultCompensation); } public RandomVariable getCurrentFundingLevel() { return currentCapacity; } @Override public Set queryUnderlyings() { return null; } @Override public RandomVariable getValue(double evaluationTime, TermStructureMonteCarloSimulationModel model) throws CalculationException { throw new UnsupportedOperationException(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy