* $f_t = R_t S_t$ where $R_t = \exp(\int_t^T r_s dt)$. The dynamics of spot are $\frac{dS_t}{S_t} = r_t dt + \sigma_{\beta} (R_t S_t)^{\beta-1} dW$.
* This means we can treat the local volatility as $\sigma(t,S_t) = \sigma_{\beta} (R_t S_t)^{\beta-1}$
*/
@Test
public void cevTest() {
final CEVPriceFunction cev = new CEVPriceFunction();
final double k = 14.0;
final boolean isCall = true;
final int tNodes = 100;
int nu = 80;
int xNodes = nu * tNodes;
final double df = DIS_CURVE.getDiscountFactor(T);
final double fwd = FWD_CURVE.getForward(T);
final double sigma = 1.0;
final double beta = 0.5;
final Function<Double, Double> vol = new Function2D<Double, Double>() {
@Override
public Double evaluate(final Double t, final Double s) {
final double tau = T - t;
final double rt = Math.exp(tau * R);
return sigma * Math.pow(rt * s, beta - 1.0);
}
};
final LocalVolatilitySurfaceStrike volSurf = new LocalVolatilitySurfaceStrike(FunctionalDoublesSurface.from(vol));
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, T, isCall);
final CEVFunctionData data = new CEVFunctionData(fwd, df, sigma, beta);
final Function1D<CEVFunctionData, Double> priceFunc = cev.getPriceFunction(option);
final double cevPrice = priceFunc.evaluate(data);
double pdePrice = PRICER.price(FWD_CURVE, RISK_FREE_CURVE, option, volSurf, isCall, xNodes, tNodes);
// double relErr = Math.abs((pdePrice - cevPrice) / cevPrice);