/**
* 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.surface;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.Validate;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve;
import com.opengamma.analytics.financial.model.volatility.BlackFormulaRepository;
import com.opengamma.analytics.math.surface.Surface;
import com.opengamma.analytics.math.surface.SurfaceShiftFunctionFactory;
/**
* A surface that contains the Black (implied) volatility as a function of time to maturity and (call) delta. Delta is in the range [0,1], where 0.5 is
* the ATM (DNS), Delta > 0.5 is ITM calls and Delta < 0.5 is OTM calls. Since prices are normally quoted for OTM options, Delta > 0.5 will actually be populated
* by OTM puts (Delta_put > -0.5, since Delta_call - Delta_put = 1 always holds).
*/
public class BlackVolatilitySurfaceDelta extends BlackVolatilitySurface<Delta> {
private final ForwardCurve _fc;
/**
*
* @param surface A implied volatility surface parameterised by time and (call) delta
* @param forwardCurve the forward curve
*/
public BlackVolatilitySurfaceDelta(final Surface<Double, Double, Double> surface, final ForwardCurve forwardCurve) {
super(surface);
Validate.notNull(forwardCurve, "null forward curve");
_fc = forwardCurve;
}
/**
* Return a volatility for the expiry, strike pair provided.
* Interpolation/extrapolation behaviour depends on underlying surface, which is parameterised by time and (call) delta
* @param t time to maturity
* @param k strike
* @return The Black (implied) volatility
*/
@Override
public double getVolatility(final double t, final double k) {
final double delta = BlackVolatilitySurfaceConverter.deltaForStrike(k, this, t);
return getVolatilityForDelta(t, delta);
}
/**
* Return a volatility for the expiry, (call) delta pair provided.
* Interpolation/extrapolation behaviour depends on underlying surface
* @param t time to maturity
* @param delta the call delta
* @return The Black (implied) volatility
*/
public double getVolatilityForDelta(final double t, final double delta) {
return getVolatility(t, new Delta(delta));
}
public ForwardCurve getForwardCurve() {
return _fc;
}
@Override
public double getAbsoluteStrike(final double t, final Delta s) {
final double vol = getVolatility(t, s);
final double fwd = _fc.getForward(t);
return BlackFormulaRepository.impliedStrike(s.value(), true, fwd, t, vol);
}
@Override
public BlackVolatilitySurface<Delta> withShift(final double shift, final boolean useAdditive) {
return new BlackVolatilitySurfaceDelta(SurfaceShiftFunctionFactory.getShiftedSurface(getSurface(), shift, useAdditive), _fc);
}
@Override
public BlackVolatilitySurface<Delta> withSurface(final Surface<Double, Double, Double> surface) {
return new BlackVolatilitySurfaceDelta(surface, _fc);
}
@Override
public <S, U> U accept(final BlackVolatilitySurfaceVisitor<S, U> visitor, final S data) {
return visitor.visitDelta(this, data);
}
@Override
public <U> U accept(final BlackVolatilitySurfaceVisitor<?, U> visitor) {
return visitor.visitDelta(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + _fc.hashCode();
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof BlackVolatilitySurfaceDelta)) {
return false;
}
final BlackVolatilitySurfaceDelta other = (BlackVolatilitySurfaceDelta) obj;
if (!ObjectUtils.equals(_fc, other._fc)) {
return false;
}
return true;
}
}