BlackScholesHedgedPortfolio.java
/*
* (c) Copyright Christian P. Fries, Germany. Contact: email@christian-fries.de.
*
* Created on 10.06.2004
*/
package net.finmath.montecarlo.assetderivativevaluation.products;
import net.finmath.exception.CalculationException;
import net.finmath.functions.AnalyticFormulas;
import net.finmath.montecarlo.assetderivativevaluation.AssetModelMonteCarloSimulationModel;
import net.finmath.stochastic.RandomVariable;
import net.finmath.stochastic.Scalar;
/**
* This class implements a delta and delta-gamma hedged portfolio of an European option (a hedge simulator).
*
* The hedge is done under the assumption of a Black Scholes Model (even if the pricing model is a different one).
*
* In case of the gamma hedge and the vega hedge, note that we make the assumption that the
* market trades these option according to Black-Scholes parameters assumed in hedging.
* While this is a simple model, it is to some extend reasonable, when we assume that the
* hedge is done by calculating delta from a calibrated model (where the risk free rate and
* the volatility are "market implied").
*
* That said, this class evaluates the hedge portfolio given that the market implies a given
* risk free rate and volatility, while the underlying follows a given (possibly different) stochastic
* process.
*
* The <code>getValue</code>-method returns the random variable \( \Pi(t) \) representing the value
* of the replication portfolio \( \Pi(t) = \phi_0(t) N(t) + \phi_1(t) S(t) + \psi_0(t) C(t) \).
*
* @author Christian Fries
* @version 1.4
*/
public class BlackScholesHedgedPortfolio extends AbstractAssetMonteCarloProduct {
public enum HedgeStrategy {
deltaHedge,
deltaGammaHedge,
deltaVegaHedge
}
// Properties of the European option we wish to replicate
private final double maturity;
private final double strike;
// Model assumptions for the hedge
private final double riskFreeRate; // Actually the same as the drift (which is not stochastic)
private final double volatility;
// Properties for the hedge option if we do a gamma hedge
private final double hedgeOptionMaturity;
private final double hedgeOptionStrike;
private final HedgeStrategy hedgeStrategy;
/**
* Construction of a delta-gamma hedge portfolio assuming a Black-Scholes model.
*
* @param maturity Maturity of the option we wish to replicate.
* @param strike Strike of the option we wish to replicate.
* @param riskFreeRate Model riskFreeRate assumption for our delta hedge.
* @param volatility Model volatility assumption for our delta hedge.
* @param hedgeOptionMaturity Maturity of the option used in the hedge portfolio (to hedge gamma).
* @param hedgeOptionStrike Strike of the option used in the hedge portfolio (to hedge gamma).
* @param hedgeStrategy Specification of the hedge strategy to be used (delta, delta-gamma, etc.).
*/
public BlackScholesHedgedPortfolio(final double maturity, final double strike, final double riskFreeRate, final double volatility,
final double hedgeOptionMaturity, final double hedgeOptionStrike, final HedgeStrategy hedgeStrategy) {
super();
this.maturity = maturity;
this.strike = strike;
this.riskFreeRate = riskFreeRate;
this.volatility = volatility;
this.hedgeOptionMaturity = hedgeOptionMaturity;
this.hedgeOptionStrike = hedgeOptionStrike;
this.hedgeStrategy = hedgeStrategy;
}
/**
* Construction of a hedge portfolio assuming a Black-Scholes model for the hedge ratios.
*
* @param maturity Maturity of the option we wish to replicate.
* @param strike Strike of the option we wish to replicate.
* @param riskFreeRate Model riskFreeRate assumption for our delta hedge.
* @param volatility Model volatility assumption for our delta hedge.
*/
public BlackScholesHedgedPortfolio(final double maturity, final double strike, final double riskFreeRate, final double volatility) {
this(maturity, strike, riskFreeRate, volatility, 0.0 /* hedgeOptionMaturity */, 0.0 /* hedgeOptionStrike */, HedgeStrategy.deltaHedge /* hedgeStrategy */);
}
@Override
public RandomVariable getValue(final double evaluationTime, final AssetModelMonteCarloSimulationModel model) throws CalculationException {
/*
* Going forward in time we monitor the hedge portfolio on each path.
*/
// Initialize the portfolio to zero stocks and as much cash as the Black-Scholes Model predicts we need.
final RandomVariable underlyingToday = model.getAssetValue(0.0,0);
final RandomVariable numeraireToday = model.getNumeraire(0.0);
final RandomVariable valueOfOptionAccordingBlackScholes = AnalyticFormulas.blackScholesOptionValue(
underlyingToday,
riskFreeRate,
volatility,
maturity - 0.0,
strike);
// We store the composition of the hedge portfolio (depending on the path)
RandomVariable amountOfNumeraireAsset = valueOfOptionAccordingBlackScholes.div(numeraireToday);
RandomVariable amountOfUnderlyingAsset = model.getRandomVariableForConstant(0.0);
// In case of a gamma hedge, the hedge portfolio consist of additional options
RandomVariable amountOfHedgeOptions = model.getRandomVariableForConstant(0.0);
// Ask the model for its discretization
final int timeIndexEvaluationTime = model.getTimeIndex(evaluationTime);
for(int timeIndex = 0; timeIndex<timeIndexEvaluationTime; timeIndex++) {
// Get value of underlying and numeraire assets
final RandomVariable underlyingAtTimeIndex = model.getAssetValue(timeIndex,0);
final RandomVariable numeraireAtTimeIndex = model.getNumeraire(timeIndex);
// Delta of option to replicate
RandomVariable delta = AnalyticFormulas.blackScholesOptionDelta(
underlyingAtTimeIndex,
riskFreeRate,
volatility,
maturity-model.getTime(timeIndex), // remaining time
strike);
// If we do not perform a gamma hedge, set gamma to zero here, otherwise set it to the gamma of option to replicate.
RandomVariable gamma = model.getRandomVariableForConstant(0.0);
if(hedgeOptionStrike != 0) {
gamma = AnalyticFormulas.blackScholesOptionGamma(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
maturity-model.getTime(timeIndex), // remaining time
strike);
}
// If we do not perform a vega hedge, set vega to zero here, otherwise set it to the vega of option to replicate.
RandomVariable vega = model.getRandomVariableForConstant(0.0);
if(hedgeOptionStrike != 0) {
vega = AnalyticFormulas.blackScholesOptionVega(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
maturity-model.getTime(timeIndex), // remaining time
strike);
}
/*
* If our hedge portfolio consist of a second option (gamma hedge), calculate its price, delta and gamma
*/
// Price of option used in hedge
final RandomVariable priceOfHedgeOption = AnalyticFormulas.blackScholesOptionValue(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
hedgeOptionMaturity-model.getTime(timeIndex), // remaining time
hedgeOptionStrike);
// Delta of option used in hedge
final RandomVariable deltaOfHedgeOption = AnalyticFormulas.blackScholesOptionDelta(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
hedgeOptionMaturity-model.getTime(timeIndex), // remaining time
hedgeOptionStrike);
// Gamma of option used in hedge
final RandomVariable gammaOfHedgeOption = AnalyticFormulas.blackScholesOptionGamma(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
hedgeOptionMaturity-model.getTime(timeIndex), // remaining time
hedgeOptionStrike);
// Vega of option used in hedge
final RandomVariable vegaOfHedgeOption = AnalyticFormulas.blackScholesOptionVega(
underlyingAtTimeIndex, // current underlying value
riskFreeRate,
volatility,
hedgeOptionMaturity-model.getTime(timeIndex), // remaining time
hedgeOptionStrike);
/*
* Change the portfolio according to the trading strategy
*/
// Determine the amount of hedge options to buy
RandomVariable newNumberOfHedgeOptions;
switch(hedgeStrategy) {
case deltaGammaHedge:
newNumberOfHedgeOptions = gamma.div(gammaOfHedgeOption);
break;
case deltaVegaHedge:
newNumberOfHedgeOptions = vega.div(vegaOfHedgeOption);
break;
case deltaHedge:
default:
newNumberOfHedgeOptions = new Scalar(0.0);
break;
}
final RandomVariable hedgeOptionsToBuy = newNumberOfHedgeOptions.sub(amountOfHedgeOptions);
// Adjust delta: remainingDelta = delta - newNumberOfHedgeOptions * deltaOfHedgeOption
delta = delta.sub(newNumberOfHedgeOptions.mult(deltaOfHedgeOption));
// Determine the delta hedge
final RandomVariable newNumberOfStocks = delta;
final RandomVariable stocksToBuy = newNumberOfStocks.sub(amountOfUnderlyingAsset);
// Ensure self financing
final RandomVariable numeraireAssetsToSell = stocksToBuy.mult(underlyingAtTimeIndex).add(hedgeOptionsToBuy.mult(priceOfHedgeOption)).div(numeraireAtTimeIndex);
final RandomVariable newNumberOfNumeraireAsset = amountOfNumeraireAsset.sub(numeraireAssetsToSell);
// Update portfolio
amountOfNumeraireAsset = newNumberOfNumeraireAsset;
amountOfUnderlyingAsset = newNumberOfStocks;
amountOfHedgeOptions = newNumberOfHedgeOptions;
}
/*
* At evaluationTime, calculate the value of the replication portfolio
*/
// Get value of underlying and numeraire assets
final RandomVariable underlyingAtEvaluationTime = model.getAssetValue(evaluationTime,0);
final RandomVariable numeraireAtEvaluationTime = model.getNumeraire(evaluationTime);
final RandomVariable priceOfHedgeOption;
if(hedgeStrategy.equals(HedgeStrategy.deltaHedge)) {
priceOfHedgeOption = new Scalar(0.0);
}
else {
priceOfHedgeOption = AnalyticFormulas.blackScholesOptionValue(
underlyingAtEvaluationTime, // current underlying value
model.getRandomVariableForConstant(riskFreeRate),
model.getRandomVariableForConstant(volatility),
hedgeOptionMaturity-model.getTime(timeIndexEvaluationTime), // remaining time
hedgeOptionStrike);
}
final RandomVariable portfolioValue = amountOfNumeraireAsset.mult(numeraireAtEvaluationTime)
.add(amountOfUnderlyingAsset.mult(underlyingAtEvaluationTime))
.add(amountOfHedgeOptions.mult(priceOfHedgeOption));
return portfolioValue;
}
}