Skip to content

Code refactoring #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package net.finmath.fouriermethod.calibration.models;

import java.time.LocalDate;
import java.util.Arrays;

import net.finmath.fouriermethod.calibration.ScalarParameterInformation;
import net.finmath.fouriermethod.calibration.ScalarParameterInformationImplementation;
import net.finmath.fouriermethod.calibration.Unconstrained;
import net.finmath.fouriermethod.models.MertonModel;
import net.finmath.marketdata.model.curves.DiscountCurve;
import net.finmath.modelling.ModelDescriptor;
import net.finmath.modelling.descriptor.MertonModelDescriptor;

Expand Down Expand Up @@ -100,10 +102,18 @@ public ModelDescriptor getModelDescriptor() {

@Override
public MertonModel getCharacteristicFunctionModel() {
return new MertonModel(descriptor.getReferenceDate(),descriptor.getInitialValue(),descriptor.getDiscountCurveForForwardRate(),
descriptor.getDiscountCurveForDiscountRate(),descriptor.getVolatility(),
descriptor.getJumpIntensity(),descriptor.getJumpSizeMean(),descriptor.getJumpSizeStdDev());
}
final LocalDate referenceDate = descriptor.getReferenceDate();
final double initialValue = descriptor.getInitialValue();
final DiscountCurve forwardDiscountCurve = descriptor.getDiscountCurveForForwardRate();
final DiscountCurve discountCurveForDiscountRate = descriptor.getDiscountCurveForDiscountRate();
final double volatility = descriptor.getVolatility();
final double jumpIntensity = descriptor.getJumpIntensity();
final double jumpSizeMean = descriptor.getJumpSizeMean();
final double jumpSizeStdDev = descriptor.getJumpSizeStdDev();

return new MertonModel(referenceDate, initialValue, forwardDiscountCurve, discountCurveForDiscountRate, volatility, jumpIntensity, jumpSizeMean, jumpSizeStdDev);
}


@Override
public double[] getParameterLowerBounds() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.finmath.interpolation;

public class ConstantExtrapolation extends Extrapolation {
@Override
public double getValue(double[] points, double[] values, double x) {
return values[0];
}
}
5 changes: 5 additions & 0 deletions src/main/java/net/finmath/interpolation/Extrapolation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.finmath.interpolation;

public abstract class Extrapolation {
public abstract double getValue(double[] points, double[] values, double x);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package net.finmath.interpolation;

public class LinearExtrapolation extends Extrapolation {
@Override
public double getValue(double[] points, double[] values, double x) {
return values[0] + (values[1] - values[0]) / (points[1] - points[0]) * (x - points[0]);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -181,49 +181,55 @@ public InterpolationMethod getInterpolationMethod() {
* @param x The abscissa at which the interpolation should be performed.
* @return The interpolated value (ordinate).
*/
public double getValue(final double x)
{
public double getValue(final double x) {
synchronized(interpolatingRationalFunctionsLazyInitLock) {
if(interpolatingRationalFunctions == null) {
doCreateRationalFunctions();
}
}

// Get interpolating rational function for the given point x
final int pointIndex = java.util.Arrays.binarySearch(points, x);
if(pointIndex >= 0) {
return values[pointIndex];
}

int intervalIndex = -pointIndex-2;

// Check for extrapolation
Extrapolation extrapolation;
if(intervalIndex < 0) {
// Extrapolation
if(extrapolationMethod == ExtrapolationMethod.CONSTANT) {
return values[0];
} else if(extrapolationMethod == ExtrapolationMethod.LINEAR) {
return values[0]+(values[1]-values[0])/(points[1]-points[0])*(x-points[0]);
} else {
intervalIndex = 0;
}
}
else if(intervalIndex > points.length-2) {
extrapolation = getExtrapolationMethod();
intervalIndex = 0;
} else if(intervalIndex > points.length-2) {
// Extrapolation
if(extrapolationMethod == ExtrapolationMethod.CONSTANT) {
return values[points.length-1];
} else if(extrapolationMethod == ExtrapolationMethod.LINEAR) {
return values[points.length-1]+(values[points.length-2]-values[points.length-1])/(points[points.length-2]-points[points.length-1])*(x-points[points.length-1]);
} else {
intervalIndex = points.length-2;
}
extrapolation = getExtrapolationMethod();
intervalIndex = points.length-2;
} else {
extrapolation = null;
}

// Calculate interpolating value or use extrapolation
if(extrapolation == null) {
final RationalFunction rationalFunction = interpolatingRationalFunctions[intervalIndex];
return rationalFunction.getValue(x-points[intervalIndex]);
} else {
return extrapolation.getValue(points, values, x);
}
}

public Extrapolation getExtrapolationMethod() {
if(extrapolationMethod == ExtrapolationMethod.CONSTANT) {
return new ConstantExtrapolation();
} else if(extrapolationMethod == ExtrapolationMethod.LINEAR) {
return new LinearExtrapolation();
} else {
return null;
}

final RationalFunction rationalFunction = interpolatingRationalFunctions[intervalIndex];

// Calculate interpolating value
return rationalFunction.getValue(x-points[intervalIndex]);
}



private void doCreateRationalFunctions()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -756,13 +756,9 @@ else if(ForwardCurve.class.isInstance(calibrationCurveOld)) {
* @return The discount factor curve associated with the given name.
*/
private DiscountCurve createDiscountCurve(final String discountCurveName) {
DiscountCurve discountCurve = model.getDiscountCurve(discountCurveName);
if(discountCurve == null) {
discountCurve = DiscountCurveInterpolation.createDiscountCurveFromDiscountFactors(discountCurveName, new double[] { 0.0 }, new double[] { 1.0 });
model = model.addCurves(discountCurve);
}
DiscountedAnalyticCurves discountedAnalyticCurves = new DiscountedAnalyticCurves();

return discountCurve;
return discountedAnalyticCurves.createDiscountCurve(discountCurveName, model);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package net.finmath.marketdata.calibration;

import net.finmath.marketdata.model.AnalyticModel;
import net.finmath.marketdata.model.curves.DiscountCurve;
import net.finmath.marketdata.model.curves.DiscountCurveInterpolation;

public class DiscountedAnalyticCurves {
public DiscountCurve createDiscountCurve(final String discountCurveName, AnalyticModel model) {
DiscountCurve discountCurve = model.getDiscountCurve(discountCurveName);
if(discountCurve == null) {
discountCurve = DiscountCurveInterpolation.createDiscountCurveFromDiscountFactors(discountCurveName, new double[] { 0.0 }, new double[] { 1.0 });
model = model.addCurves(discountCurve);
}

return discountCurve;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public double getValue(final double evaluationTime, final AnalyticModel model) {
final DiscountCurve discountCurve = model.getDiscountCurve(discountCurveName);

DiscountCurve discountCurveForForward = null;
if(forwardCurve == null && forwardCurveName != null && forwardCurveName.length() > 0) {
if(checkForwardCurve(forwardCurve, forwardCurveName)) {
// User might like to get forward from discount curve.
discountCurveForForward = model.getDiscountCurve(forwardCurveName);

Expand All @@ -88,4 +88,8 @@ else if(discountCurveForForward != null) {

return payoff * discountFactor / discountCurve.getDiscountFactor(model, evaluationTime);
}

public boolean checkForwardCurve(ForwardCurve forwardCurve, String forwardCurveName){
return (forwardCurve == null && forwardCurveName != null && forwardCurveName.length() > 0);
}
}
6 changes: 3 additions & 3 deletions src/main/java/net/finmath/montecarlo/GammaProcess.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class GammaProcess implements IndependentIncrements, Serializable {

private final RandomVariableFactory randomVariableFactory = new RandomVariableFromArrayFactory();

private transient RandomVariable[][] gammaIncrements;
private transient RandomVariable[][] gammaIncrements;

/**
* Construct a Gamma process with a given shape parameter.
Expand Down Expand Up @@ -122,12 +122,12 @@ public RandomVariable getIncrement(final int timeIndex, final int factor) {
doGenerateGammaIncrements();
}
}

/*
* For performance reasons we return directly the stored data (no defensive copy).
* We return an immutable object to ensure that the receiver does not alter the data.
*/
return gammaIncrements[timeIndex][factor];
RandomVariableLazyEvaluation randomVariableLazyEvaluation = new RandomVariableLazyEvaluation(null);
return randomVariableLazyEvaluation.getIncrement(timeIndex, factor);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public class RandomVariableLazyEvaluation implements RandomVariable {
/**
*
*/


private static final long serialVersionUID = 8413020544732461630L;
private transient RandomVariable[][] gammaIncrements;

private final double time; // Time (filtration)

Expand All @@ -59,6 +62,7 @@ public RandomVariableLazyEvaluation(final RandomVariable value) {
realizations = value.isDeterministic() ? null : value::get;
size = value.size();
valueIfNonStochastic = value.isDeterministic() ? value.get(0) : Double.NaN;
gammaIncrements = null; // Lazy initialization
}

/**
Expand All @@ -68,8 +72,9 @@ public RandomVariableLazyEvaluation(final RandomVariable value) {
*/
public RandomVariableLazyEvaluation(final double value) {
this(0.0, value);
}
gammaIncrements = null; // Lazy initialization

}
/**
* Create a random variable by applying a function to a given other implementation of <code>RandomVariable</code>.
*
Expand All @@ -87,6 +92,8 @@ public double applyAsDouble(final int i) {
};
size = value.size();
valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
gammaIncrements = null; // Lazy initialization

}

/**
Expand All @@ -101,6 +108,17 @@ public RandomVariableLazyEvaluation(final double time, final double value) {
realizations = null;
size = 1;
valueIfNonStochastic = value;
gammaIncrements = null; // Lazy initialization

}

public RandomVariable getIncrement(final int timeIndex, final int factor) {
// Thread safe lazy initialization
/*
* For performance reasons we return directly the stored data (no defensive copy).
* We return an immutable object to ensure that the receiver does not alter the data.
*/
return gammaIncrements[timeIndex][factor];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,35 +73,35 @@ public double getLogLikelihoodForParameters(final double[] parameters)
double logLikelihood = 0.0;

final double volScaling = 1;
double evalPrev = 0.0;
double eval = volScaling * (Math.log((timeSeries.getValue(1))/(timeSeries.getValue(0))));
if(Double.isInfinite(eval) || Double.isNaN(eval)) {
eval = 0;
double evaluationPrev = 0.0;
double evaluation = volScaling * (Math.log((timeSeries.getValue(1))/(timeSeries.getValue(0))));
if(Double.isInfinite(evaluation) || Double.isNaN(evaluation)) {
evaluation = 0;
}
double h = omega / (1.0 - alpha - beta);
double m = 0.0; // xxx how to init?

logLikelihood += - Math.log(h) - 2 * Math.log((Math.abs(timeSeries.getValue(1)))/volScaling) - eval*eval / h;
logLikelihood += - Math.log(h) - 2 * Math.log((Math.abs(timeSeries.getValue(1)))/volScaling) - evaluation*evaluation / h;

final int length = timeSeries.getNumberOfTimePoints();
for (int i = 1; i < length-1; i++) {
m = -mu -theta * m + eval - phi * evalPrev;
m = -mu -theta * m + evaluation - phi * evaluationPrev;
h = (omega + alpha * m * m) + beta * h;

final double value1 = timeSeries.getValue(i);
final double value2 = timeSeries.getValue(i+1);
final double currentValue = timeSeries.getValue(i);
final double nextValue = timeSeries.getValue(i+1);

double evalNext = volScaling * (Math.log((value2)/(value1)));
double evalNext = volScaling * (Math.log((nextValue)/(currentValue)));
if(Double.isInfinite(evalNext) || Double.isNaN(evalNext)) {
evalNext = 0;
}
final double mNext = -mu - theta * m + evalNext - phi * eval;
final double mNext = -mu - theta * m + evalNext - phi * evaluation;

// We need to take abs here, which corresponds to the assumption that -x is lognormal, given that we encounter a negative values.
logLikelihood += - Math.log(h) - 2 * Math.log((Math.abs(value2))/volScaling) - mNext* mNext / h;
logLikelihood += - Math.log(h) - 2 * Math.log((Math.abs(nextValue))/volScaling) - mNext* mNext / h;

evalPrev = eval;
eval = evalNext;
evaluationPrev = evaluation;
evaluation = evalNext;
}
logLikelihood += - Math.log(2 * Math.PI) * (length-1);
logLikelihood *= 0.5;
Expand Down