/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation;
import com.opengamma.util.ArgumentChecker;
/**
* A function to allow a smooth weighing between two functions. If two functions f(x) and g(x) fit the data set (x_i,y_i) at the points x_a and x_b
* (i.e. f(x_a) = g(x_a) = y_a and f(x_b) = g(x_b) = y_b), then a weighted function h(x) = w(x)f(x) + (1-w(x))*g(x) with 0 <= w(x) <= 1 will also
* fit the points a and b
* TODO this belongs with interpolator
*/
public abstract class WeightingFunction {
/**
* Get the function weight for point x
* @param xs All the independent data points
* @param x An arbitrary point
* @return The weight
*/
public double getWeight(final double[] xs, final double x) {
ArgumentChecker.notNull(xs, "strikes");
final int index = SurfaceArrayUtils.getLowerBoundIndex(xs, x);
final double y = getY(xs, index, x);
return getWeight(y);
}
/**
* Get the function weight for point x - use this if index in known
* @param xs All the independent data points
* @param index The index of the data point below x
* @param x An arbitrary point
* @return The weight
*/
public double getWeight(final double[] xs, final int index, final double x) {
ArgumentChecker.notNull(xs, "strikes");
final double y = getY(xs, index, x);
return getWeight(y);
}
/**
* For an arbitrary point x, let the two data points immediately below and above x be, x_a and x_b, then define y = (x_b - x)/(x_b - x_a).
* @param xs All the independent data points
* @param lowerBoundIndex The index of x_a
* @param x An arbitrary point
* @return y
*/
private double getY(double[] xs, int lowerBoundIndex, double x) {
ArgumentChecker.notNull(xs, "strikes");
ArgumentChecker.notNegative(lowerBoundIndex, "index");
ArgumentChecker.isTrue(lowerBoundIndex <= xs.length - 2, "index cannot be larger than {}, have {}", xs.length - 2, lowerBoundIndex);
return (xs[lowerBoundIndex + 1] - x) / (xs[lowerBoundIndex + 1] - xs[lowerBoundIndex]);
}
/**
* The condition that must be satisfied by all weight functions is that w(1) = 1, w(0) = 0 and dw(y)/dy <= 0 - i.e. w(y) is monotonically decreasing
* @param y a value between 0 and 1
* @return The weight
*/
public abstract double getWeight(double y);
}