# Introduction: Delta Hedging European Call Options

One of the foundational concepts in modern financial theory is the concept of delta hedging. At it’s core, delta hedging is a risk management strategy commonly used by investors and traders to reduce or eliminate the directional risk associated with holding a position in an option or derivative contract. The term "delta" refers to the sensitivity of the option or derivative's price to changes in the price of the underlying asset, thus it is a measure of how much the option's price is expected to change for a given change in the underlying asset's price.

The concept of delta hedging is based on a simple principle; create a position that counteracts the directional risk of the original position—otherwise known as portfolio replication. By doing so, the overall portfolio becomes less sensitive to small price movements in the underlying asset. This can be particularly useful in reducing risk and managing exposure to price fluctuations.

In the Black-Scholes-Merton (BSM) model of European options, one can directly compute delta given the solution to the BSM model. In this post, I want to show how one can implement this quite simply in python using the BSM model. All the code to generate this post can be found on my __ Github__.

- Introduction: Delta Hedging European Call Options
- Delta Hedging Short Calls
- The risk vs reward
- Hedging
- Precise Delta Hedging
- Example: Apple
- Looking at Apple stock
- Getting call options data
- Implementing Delta Hedging
- Profit and Loss
- Monte Carlo
- Summary

# Delta Hedging Short Calls

In this post we will focus on a specific example, namely delta hedging a short call—however, it is straight forward to extend this to long positions and puts. In this case, we are playing the role of a market maker and selling a call to another party at an agreed strike price $K$. We are therefore obligated to sell $100$ shares of the underlying to the buyer at the maturity time $\tau$ if the buyer wishes to exercise their option. Rationally, they will only do so if the price of they underlying asset $S(\tau)>K$. For assuming this this risk, we are going to be paid a premium which is the price of the option $C_{0}$. In reality, we don’t need to hold this contract to maturity and a free to sell it on the open market, but for this example, we are going to hold this contract to maturity.

### The risk vs reward

So what is the risk here? Suppose that at maturity the price of the underlying is $S(\tau)>K$, and we don’t have $100$ shares to meet our obligation. We would therefore need to go out and buy $100$ shares at $S(\tau)$ and then sell it at the strike price $K$, making a loss of $\$100(S(\tau)-K)$ which is not ideal and could be quite substantial!

The payoff curve for a short call looks like graph below.

Our reward for taking this risk is therefore the premium we are paid (the price of the option) for selling the call.

### Hedging

Now, once we have sold the option we don’t need to sit around and wait for the maturity date to purchase the shares to satisfy our obligation. Instead we could look at how the market price is changing and purchase stock along the way to maturity to minimise the loss we would make. The intuition is actually very straightforward; if the underlying price $S(t<\tau)$ is considerably below the strike price $K$, then the likelihood of it exercising in “in the money” is pretty low, so we don’t need to hold $100$ shares of stock. If on the other hand, we see the price drifting upwards to $K$, then we might want to acquire *some *stock to satisfy the position—for example we might purchase $50$ shares at the lower price, and if it keeps drifting closer, then we might acquire another $50$ shares. In this case, we have made two transactions, both of which are lower than the strike price, but preemptively so that such that we have minimised our loss.

### Precise Delta Hedging

If one assumes that the option price is closely modelled by the Black-Scholes-Merton model of European options, then we can, at each time step $dt$, hedge our position exactly so that it remains perfectly hedged (there is a bunch of assumptions underlying this). If our short call is perfectly hedged, then at every time step we will continue to prune and trim our hedge such that it perfectly balances our chances of loss, which conversely also removes any chance of making a profit—in which case our expected profit is zero. However, this is the ideal situation and in reality we cannot perfectly hedge because

- Stock’s don’t perfectly follow Geometric Brownian motion
- Market’s are not efficient, do not act rationally, and may be illiquid
- We cannot hedge continuously, but must do so discretely in time

Despite this, we can use delta hedging to reduce our risk and attempt to concentrate the likelihood of us turning a profit.

# Example: Apple

### Looking at Apple stock

In this example, I will pull down real data from Yahoo finance and use it to implement Delta Hedging. I will also use a bunch of functions that you can find on my __ Github__.

For starters, we will pull down some useful data about the Apple stock price over the last year and calculate the rolling average of realised volatility over one month (21 trading days)

```
# tickers for the Apple
ticker = "AAPL"
interval = "1d"
end_date = dt.datetime(2023, 7, 20)
start_date = end_date - dt.timedelta(days = 365)
# Get yesterdays price data for the S&P 500
data = get_stock_data(ticker, start_date, end_date, interval)
data.index = data.index.date
# We first want to estimate the realized volatility of the stock
data['log_return'] = np.log(data['Close']) - np.log(data['Close'].shift(1))
data['volatility'] = data['log_return'].rolling(21).std() * np.sqrt(252)
# get at the money price
S0 = data['Close'].values[-1]
# we will assume the volatility is the same as the last realised volatility
vol = data['volatility'].values[-1]/(100/tau**0.5)
```

If we now plot price vs time and the volatility as a function of time we can clearly see that Apple stock is experiencing a nice bull run after all the market turbulence with inflation peaking in 2022. Now with inflation coming down and the good earnings of tech stocks over 2023, we can see this reflected as steady growth with lower realised volatility

So, I’m not providing any forecasting analysis here, but let’s say that right now wanted to sell some call options on apple for whatever reason (I realise that doing this during a period of higher volatility would be much more lucrative—at the end of 2022—but for the purpose of this example, we won’t worry so much).

### Getting call options data

Now we want to check that the BSM model will be suitable for our purposes. We can pull down the options data from Yahoo finance when the market is open using the get_options_data function I have written, but for this model, I simply saved this data locally. We can then read it in and compute some useful quantities. Also, we can pull down the repo-rate and use as our risk free rate (pulled from https://fred.stlouisfed.org/series/DFF). Here we will be interested in selling a call option due to expire in 92 days (13 weeks) from our purchase date of 20/07/2023.

```
# get expirey date within tau days of yesterday
trading_days = 252
tau = 92
# Number of trading days
tau_trading = 66
dtau = 5
# interest rate per day (repo rate)
r = get_repo_rate(end_date-dt.timedelta(days=7), end_date).values[0,0]/(100)
# daily interest rate change
r_t = r/365
# load in the options data
options = pd.read_csv('./data/options.csv', index_col=0)
```

Now, let’s see if the BSM model will provide an appropriate fit to the options data we have pulled down from the market

```
# We will now compare the BSM to the actual options price
K_vals = np.linspace(50, 350, 100)
# Get the call price for different K values
call_price = OptionsPriceBSM(S0, K_vals, tau_trading, vol, r_t, option_type='call')
```

If we now plot these two against the data that we pulled down we can clearly see we get pretty good agreement between the BSM model and the actual options prices. Recall that call options are “in the money” when the strike $K$ is less than the underlying stock price $S(t)$, thus options that with strikes that are in the money (t

Given that we have pretty good agreement, we will assume that the BSM model is providing an accurate measure of Apple stocks behaviour and the pricing of their options. In reality, this is all very crude and we need to be far more careful as Delta hedging is very sensitive to realised volatility, as we will discuss below!

### Implementing Delta Hedging

In Delta hedging, we compute $\Delta(t)$ quite straightforwardly as

$\Delta(t) = \frac{\partial C(t)}{\partial S(t)}\,,$that is, it is the partial derivative of the option price with respect to the stock price. This captures the essence of delta hedging, namely that if there is a change in the underlying value of stock, this necessarily generates a change in the value of our option. Given that we know the solution to the BSM model for Euro options yields the value of a call option at time $t$ as

$C(t) = S_{0}N(d_{+}(t)) - Ke^{- r t}N(d_{-}(t))$where $S_{0}$ is the initial value of the stock price, $r$ is the risk free interest rate, and $N(x)$ is the cumulative distribution function (CDF) of a normal distribution, and the quantities

$d_{+}(t) = \frac{\log \left(\frac{S_{0}}{K}\right) +(r +\frac{1}{2}{}\sigma^{2})t}{\sigma\sqrt{t}}$and

$d_{-}(t) = d_{+}(t) - \sigma \sqrt{t}$Given this solution, one can easily calculate $\Delta(t)$ providing us with the delta hedging equation

$\Delta(t) = N(d_{+}(t))\,.$This is very straight forward then to implement numerically. Now, it is worth noting that $\Delta(t)$ is continuous in time, but in reality, we have to tend to our hedges periodically in time. In our simulation above, we are going to balance our position weekly, that is every week we will look at the value of Apple stock and compute how many stocks of Apple we need to buy/sell to hedge our position.

In our simulation, we are going to assume that we have sold an “at the money” call, that is given $S_{0} = 195.1$, we will set the strike at $K=195$ (they usually come in 5 dollar increments).

**We can now implement this quite easily in code assuming the stock price will evolve according to Geometric Brownian motion for a single trajectory over the next 13 weeks, given the current realised volatility**

**$\sigma_{\rm real}$**

**. Most importantly, in our simulation we will assume that the drift in stock is zero (despite the strong upward trend in apple stock; in reality this would need to be carefully analysed as we will discuss at the end).**

```
# Assuming geometric brownian motion, we can simulate the stock price
t = np.arange(10e-4, tau_trading+dtau, dtau)
# Compute stock price evolution
St = stockprice_evolution(S0, t, dtau, 0, vol, 1)
# Compute the options price evolution and the change in delta
Ct = OptionsPriceBSM(St, K, t[::-1], vol, r_t, option_type='call')
deltat = OptionDeltaBSM(St, K, t[::-1], vol, r_t, option_type='call')
deltat = np.round(100*deltat, 0).astype(int)
# compute delta adjustments
d_delta = np.diff(deltat, axis=1)
```

For this single trajectory, we can go into the cashflow and look at how our position has changed over time

```
# create a dataframe to store the data with index name as week
df = pd.DataFrame(index=np.arange(len(t)), columns=['Stock Price', 'Delta'])
df.index.name = 'Week'
df['Stock Price'] = St[0]
df['Delta'] = - deltat[0]
df['Delta Adjustments'] = df['Delta'].diff()
df['Total Delta Adjustment'] = df.loc[0, 'Delta'] - df['Delta']
df['Adjustment Cashflow'] = df['Delta Adjustments']*df['Stock Price']
```

As you can we initially start out by first purchasing $56$ shares of Apple stock (the negative sign here indicates that we have borrowed from the money market to finance this). After the first week, the stock price went down, thus moving away from the strike and decreasing the likelihood of us having to payout, therefore we unload $7$ shares of Apple stock. As you can see over the course of the 14 weeks, the stock begins to rise again and we therefore begin to repurchase Apple stock to hedge against the likelihood of paying out. However, in the end, the stock finishes “out of the money” and we do not need to payout, so we begin to unload our hedge before maturity. Over the course of this evolution we are constantly buying and selling stock to hedge against payout.

### Profit and Loss

Now we want to calculate whether or not we have turned a profit or a loss during this whole process! Let’s go through all the costs.

**Option Premium: **We first received our premium here for selling the call option which commanded 100 shares, thus we have $100 C_{0}$.

**Initial purchase of stock: **To open our hedge, we needed to buy $56$ shares of Apple stock.

So our initial position is

$X_{0} = 100C_{0} - \Delta_{0}S_{0}$**Cashflow: **Over the course of the 13 weeks we bought and sold Apple stock to maintain the hedge, thus we need to some all this payments $V$.

**Exercise at Maturity: **Finally at the end we needed to payout out the strike price $K$; however in this case we didn’t have to since the call expired out of the money so our final payment was $\Delta_{\tau}K$.

We also need to be mindful of keeping track of the interest payments to: **Interest on Option Premium invested in the money Market and the interest on our loan from the money market to facilitate the purchasing of stock. **

We now sum all these guys up to obtain

```
# Compute P&L on option
option_premium = 100*Ct[:, 0]
option_interest = 100*Ct[:, 0] * r_t* t[-1]
# Compute cashflow adjustments for delta hedging
d_cashflow = -d_delta*St[:, 1:]
# compute cashfolow adjustments for delta hedging
cashflow = (-d_delta*St[:, 1:]).sum(axis=1)
# Compute profit and loss on stocks hedge
stock_PandL = deltat[:, -1] * K - deltat[:, 0] * St[:, 0]
# Compute interest on net stock position as borrowed from the money market
stock_interest = (-deltat[0]*St[:, 0] * r_t * dtau).sum()
# Sum all P&L
total_cashflow = option_premium + cashflow + stock_PandL
total_interest = option_interest + stock_interest
# Return total P&L
total = total_cashflow + total_interest
# Print results
print(f'Opiton Premum: {option_premium[0]:.2f}')
print(f'Stock P&L: {stock_PandL[0]:.2f}')
print(f'Adjustment P&L: {cashflow[0]:.2f}')
print(f'Interest on Original P&L: {option_interest[0]:.2f}')
print(f'Interest on Stock P&L: {stock_interest:.2f}')
print(f'Total P&L: {total[0]:.2f}')
--------------------------------------
Opiton Premum: 854.91
Stock P&L: -10925.60
Adjustment P&L: 10403.77
Interest on Original P&L: 7.73
Interest on Stock P&L: -62.86
Total P&L: 277.95
```

We therefore made a net profit of $277.95 in this example! Basically the loan we had to take out to purchase the initial hedge is the mostly cancelled out by the cash flow from closing out the hedge. Likewise, if we ended such that the option was in the money and we had to sell the stock at the strike price, then the money we would make on this should largely cancel out a debt, but most likely not all due to the lower strike, thus resulting in a loss.

### Monte Carlo

We can now rerun this experiment but 10000 times to see what happens! Here we will just define a simple function to do this:

```
def MonteCarloPandL(N, S0, K, t, dtau, r, mu, vol_implied, vol_realised, option_type='call'):
'''
Compute the P&L of a delta hedged portfolio using Monte Carlo simulation
----------
Parameters
----------
N: int
Number of simulations
S0: float
Initial stock price
K: float
Strike price
t: array_like
Time to maturity
dtau: float
Time step
r: float
Interest rate (per trading day)
mu: float
Drift of stock price
vol: float
Stock measured Volatility
option_type: str
Type of option ('call' or 'put')
-------
Returns
-------
PnL: array_like
Profit and loss of the portfolio
'''
# Compute stock price evolution
St = stockprice_evolution(S0, t, dtau, mu, vol_realised, N)
# define a function that returns greeks using black scholes
Ct = OptionsPriceBSM(St, K, t[::-1], vol_implied, r, option_type)
deltat = OptionDeltaBSM(St, K, t[::-1], vol_implied, r, option_type)
deltat = np.round(100*deltat, 0).astype(int)
# compute delta adjustments
d_delta = np.diff(deltat, axis=1)
# Compute P&L on option
option_premium = 100*(Ct[:, 0])
# Compute interest on option that we say is invested in the money market
option_interest = 100*Ct[:, 0] *(1- np.exp(-r*t[-1]))
# compute cashfolow adjustments for delta hedging
cashflow = (-d_delta*St[:, 1:]).sum(axis=1)
# Compute profit and loss on stocks hedge
stock_PandL = K * deltat[:, -1] - deltat[:, 0] * St[:, 0]
stock_interest = (-deltat[:]*St * r * dtau).sum(axis=1)
# Sum all P&L
total_cashflow = option_premium + cashflow + stock_PandL
total_interest = option_interest + stock_interest
# Return total P&L
return total_cashflow + total_interest, St
PanL, St = MonteCarloPandL(100000, S0, S0, t, dtau, r_t, -0.00, vol, vol, option_type='call')
```

The results of this experiment are plotted here. Clearly we can see that on average we are make zero profit or loss and the returns are normally distributed around this result. This reflects the concept of the **law of one price** where the average payout of the option is a Martingale and should be equal to the initial “fair price” of the option.

You will notice though that in this simulation, we have assumed that the implied volatility $\sigma_{\rm imp}$— the volatility as back calculated from the actual market prices of the option— was equal to the realised volatility $\sigma_{\rm real}$ in our simulation. It is because these two are equal that the Law of one price holds.

**for prices such that the implied volatility $\sigma_{\rm imp} > \sigma_{\rm real}$ thus commanding a higher price. Buyer’s on the other hand will**

**ask****for prices such that $\sigma_{\rm imp}<\sigma_{\rm real}$ thus commanding a lower price.**

**bid**We can understand this concept quite easily from the concept of the seller of the option. In the case on the right (left), the implied volatility is lower (greater) than realised volatility and thus leading to an average loss (profit) for the seller of the call option. This highlights how important it is for market participants to accurately estimate the true volatility of a stock so that they can price their options as effectively as possible!

# Summary

So we can finish this post up here. Basically, we have gone through in detail how one can implement delta hedging of a European call option using Apple stock as an example. The take home message is the following: if you want to use delta hedging, then you want to accurately estimate the true volatility of the underlying. This will ensure that you can obtain the best possible price for selling a call option where you’re hedge will likely payout with an above average expectation! If you want the code to this, you can easily download it from my __ Github__.