/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.greeks; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.ObjectUtils; import com.opengamma.analytics.financial.pnl.UnderlyingType; /** * Definition of commonly-used greeks. */ public abstract class Greek implements Comparable<Greek> { /** * First-order sensitivity with respect to cost of carry */ public static final Greek CARRY_RHO = new Greek(new NthOrderUnderlying(1, UnderlyingType.COST_OF_CARRY), "CarryRho") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitCarryRho(); } }; /** * First-order sensitivity with respect to spot */ public static final Greek DELTA = new Greek(new NthOrderUnderlying(1, UnderlyingType.SPOT_PRICE), "Delta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitDelta(); } }; /** * Second-order sensitivity with respect to spot and time */ public static final Greek DELTA_BLEED = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.SPOT_PRICE), new NthOrderUnderlying(1, UnderlyingType.TIME))), "DeltaBleed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitDeltaBleed(); } }; /** * */ public static final Greek DRIFTLESS_THETA = new Greek(null, "DriftlessTheta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitDriftlessTheta(); } }; /** * Third-order sensitivity; first with respect to implied volatility, second with respect to spot */ public static final Greek DVANNA_DVOL = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VOLATILITY), new NthOrderUnderlying(2, UnderlyingType.SPOT_PRICE))), "DVannaDVol") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitDVannaDVol(); } }; /** * */ public static final Greek DZETA_DVOL = new Greek(null, "DZetaDVol") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitDZetaDVol(); } }; /** * */ public static final Greek ELASTICITY = new Greek(null, "Elasticity") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitElasticity(); } }; /** * Fair price */ public static final Greek FAIR_PRICE = new Greek(new NthOrderUnderlying(0, null), "FairPrice") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitPrice(); } }; /** * Second-order sensitivity with respect to spot */ public static final Greek GAMMA = new Greek(new NthOrderUnderlying(2, UnderlyingType.SPOT_PRICE), "Gamma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitGamma(); } }; /** * Third-order sensitivity; first with respect to time, second with respect to spot */ public static final Greek GAMMA_BLEED = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.TIME), new NthOrderUnderlying(2, UnderlyingType.SPOT_PRICE))), "GammaBleed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitGammaBleed(); } }; /** * */ public static final Greek GAMMA_P = new Greek(null, "GammaP") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitGammaP(); } }; /** * */ public static final Greek GAMMA_P_BLEED = new Greek(null, "GammaPBleed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitGammaPBleed(); } }; /** * First-order sensitivity with respect to yield */ public static final Greek PHI = new Greek(new NthOrderUnderlying(1, UnderlyingType.YIELD), "Phi") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitPhi(); } }; /** * First-order sensitivity with respect to interest rate */ public static final Greek RHO = new Greek(new NthOrderUnderlying(1, UnderlyingType.INTEREST_RATE), "Rho") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitRho(); } }; /** * Third-order sensitivity with respect to spot */ public static final Greek SPEED = new Greek(new NthOrderUnderlying(3, UnderlyingType.SPOT_PRICE), "Speed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitSpeed(); } }; /** * */ public static final Greek SPEED_P = new Greek(null, "SpeedP") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitSpeedP(); } }; /** * First-order sensitivity with respect to strike */ public static final Greek STRIKE_DELTA = new Greek(new NthOrderUnderlying(1, UnderlyingType.STRIKE), "StrikeDelta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitStrikeDelta(); } }; /** * First-order sensitivity with respect to strike */ public static final Greek DUAL_DELTA = new Greek(new NthOrderUnderlying(1, UnderlyingType.STRIKE), "DualDelta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitStrikeDelta(); } }; /** * Second-order sensitivity with respect to strike */ public static final Greek STRIKE_GAMMA = new Greek(new NthOrderUnderlying(2, UnderlyingType.STRIKE), "StrikeGamma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitStrikeGamma(); } }; /** * Second-order sensitivity with respect to strike */ public static final Greek DUAL_GAMMA = new Greek(new NthOrderUnderlying(2, UnderlyingType.STRIKE), "DualGamma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitStrikeGamma(); } }; /** * First-order sensitivity with respect to time */ public static final Greek THETA = new Greek(new NthOrderUnderlying(1, UnderlyingType.TIME), "Theta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitTheta(); } }; /** * Third-order sensitivity with respect to implied volatility */ public static final Greek ULTIMA = new Greek(new NthOrderUnderlying(3, UnderlyingType.IMPLIED_VOLATILITY), "Ultima") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitUltima(); } }; /** * Second-order sensitivity with respect to spot and implied volatility */ public static final Greek VANNA = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.SPOT_PRICE), new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VOLATILITY))), "Vanna") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVanna(); } }; /** * Third-order sensitivity with respect to implied variance */ public static final Greek VARIANCE_ULTIMA = new Greek(new NthOrderUnderlying(3, UnderlyingType.IMPLIED_VARIANCE), "VarianceUltima") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVarianceUltima(); } }; /** * Second-order sensitivity with respect to spot and implied variance */ public static final Greek VARIANCE_VANNA = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.SPOT_PRICE), new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VARIANCE))), "VarianceVanna") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVarianceVanna(); } }; /** * First-order sensitivity with respect to implied variance */ public static final Greek VARIANCE_VEGA = new Greek(new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VARIANCE), "VarianceVega") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVarianceVega(); } }; /** * Second-order sensitivity with respect to implied variance */ public static final Greek VARIANCE_VOMMA = new Greek(new NthOrderUnderlying(2, UnderlyingType.IMPLIED_VARIANCE), "VarianceVomma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVarianceVomma(); } }; /** * First-order sensitivity with respect to implied volatility */ public static final Greek VEGA = new Greek(new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VOLATILITY), "Vega") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVega(); } }; /** * Second-order sensitivity with respect to implied volatility and time */ public static final Greek VEGA_BLEED = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.IMPLIED_VOLATILITY), new NthOrderUnderlying(1, UnderlyingType.TIME))), "VegaBleed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVegaBleed(); } }; /** * First-order sensitivity with respect to percentage volatility */ public static final Greek VEGA_P = new Greek(null, "VegaP") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVegaP(); } }; /** * Second-order sensitivity with respect to implied volatility */ public static final Greek VOMMA = new Greek(new NthOrderUnderlying(2, UnderlyingType.IMPLIED_VOLATILITY), "Vomma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVomma(); } }; /** * */ public static final Greek VOMMA_P = new Greek(null, "VommaP") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitVommaP(); } }; /** * */ public static final Greek ZETA = new Greek(null, "Zeta") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitZeta(); } }; /** * */ public static final Greek ZETA_BLEED = new Greek(null, "ZetaBleed") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitZetaBleed(); } }; /** * Third-order sensitivity; first with respect to time, second with respect to spot */ public static final Greek ZOMMA = new Greek(new MixedOrderUnderlying(Arrays.asList(new NthOrderUnderlying(1, UnderlyingType.TIME), new NthOrderUnderlying(2, UnderlyingType.SPOT_PRICE))), "Zomma") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitZomma(); } }; /** * */ public static final Greek ZOMMA_P = new Greek(null, "ZommaP") { @Override public <T> T accept(final GreekVisitor<T> visitor) { return visitor.visitZommaP(); } }; /** A set containing all greeks that can be calculated */ private static final Set<Greek> ALL_GREEKS; //REVIEW elaine 9-7-2010 This is not ideal, because adding a new greek definition means remembering to put it in here static { ALL_GREEKS = new HashSet<>(); ALL_GREEKS.add(CARRY_RHO); ALL_GREEKS.add(DELTA); ALL_GREEKS.add(DELTA_BLEED); ALL_GREEKS.add(DRIFTLESS_THETA); ALL_GREEKS.add(DUAL_DELTA); ALL_GREEKS.add(DUAL_GAMMA); ALL_GREEKS.add(DVANNA_DVOL); ALL_GREEKS.add(DZETA_DVOL); ALL_GREEKS.add(ELASTICITY); ALL_GREEKS.add(FAIR_PRICE); ALL_GREEKS.add(GAMMA); ALL_GREEKS.add(GAMMA_BLEED); ALL_GREEKS.add(GAMMA_P); ALL_GREEKS.add(GAMMA_P_BLEED); ALL_GREEKS.add(PHI); ALL_GREEKS.add(RHO); ALL_GREEKS.add(SPEED); ALL_GREEKS.add(SPEED_P); ALL_GREEKS.add(STRIKE_DELTA); ALL_GREEKS.add(STRIKE_GAMMA); ALL_GREEKS.add(THETA); ALL_GREEKS.add(ULTIMA); ALL_GREEKS.add(VANNA); ALL_GREEKS.add(VARIANCE_ULTIMA); ALL_GREEKS.add(VARIANCE_VEGA); ALL_GREEKS.add(VARIANCE_VOMMA); ALL_GREEKS.add(VEGA); ALL_GREEKS.add(VEGA_BLEED); ALL_GREEKS.add(VEGA_P); ALL_GREEKS.add(VOMMA); ALL_GREEKS.add(VOMMA_P); ALL_GREEKS.add(ZETA); ALL_GREEKS.add(ZETA_BLEED); ALL_GREEKS.add(ZOMMA); ALL_GREEKS.add(ZOMMA_P); } /** * @return A set containing all greeks */ public static final Set<Greek> getAllGreeks() { return ALL_GREEKS; } /** The underlying of the greek */ private final Underlying _underlying; /** The name of the greek */ private final String _name; /** * @param underlying The underlying * @param name The name */ public Greek(final Underlying underlying, final String name) { _underlying = underlying; _name = name; } /** * accept() method for the visitor pattern * @param visitor A visitor * @param <T> The type of the result * @return The result returned by the visitor */ public abstract <T> T accept(GreekVisitor<T> visitor); /** * @return The underlying */ public Underlying getUnderlying() { return _underlying; } @Override public String toString() { return _name; } @Override public int compareTo(final Greek other) { return _name.compareTo(other._name); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((_name == null) ? 0 : _name.hashCode()); result = prime * result + ((_underlying == null) ? 0 : _underlying.hashCode()); return result; } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (getClass() != obj.getClass()) { return false; } final Greek other = (Greek) obj; return ObjectUtils.equals(_name, other._name) && ObjectUtils.equals(_underlying, other._underlying); } }