# Barrier option pricing with Monte Carlo

In this short article, I will apply Monte Carlo to barrier option pricing. Here are the points I am going to tackle:

• Quicker barrier options reminder
• Pros and cons of Monte Carlo for pricing
• Steps for Monte Carlo Pricing
• Up-and-Out Call pricing example
• Conclusion and ideas for better performance

### Barrier options

Before entering in pricing I will make a quick reminder about these exotic options (even though they are not considered exotic anymore…). Barrier options are part of the path-dependent option family. The final payoff of a barrier option depends on what happened during the option’s life.

Barrier option includes the effect of the barrier (knock-in or knock-out) and the way (up or down). A Down-and-Out call becomes worthless if the underlying drops under the barrier level.

Example: Up-and-In Call with strike $K = 50$ and barrier $B = 57$.

Final payoff is : $P_T = (S_T - K)^{+}*1_{M \geq B}$ with $M = max(S_t ; 0 \leq t \leq T)$

Simulation of 3 assets

An Up-and-In Call is activated if and only if the underlying goes above the barrier before the option’s maturity. If we had barrier options on each one of the simulated assets above, only one has a positive final payoff:

• Asset 1 (BLUE): This asset never exceeds the barrier level (57) during the considered period, the barrier option expires worthless.
• Asset 2 (ORANGE): This asset exceeds the barrier at the beginning, it activates the option. But at maturity, the payoff is 0 since the asset price is below 50.
• Asset 3 (GREEN): This asset exceeds the barrier at the end of the period, it activates the option. At maturity, the asset price is close to 58, the final payoff is around 8.

### Steps for Monte Carlo Pricing

1. Simulate the risk-neutral random walk for the entire period.
2. Compute the final payoff
3. Perform N times the two first steps
4. Take the average of all your payoffs
5. The option value is the discounted value of this average.

The goal is to estimate:

$P = e^{-rT}*E[h(S_T)]$

where $h(x)$ is the payoff function.

### Pros and cons of Monte Carlo

Pros:

• Really easy to code.
• Doesn’t imply hard mathematics.

Cons:

• Time-consuming (this argument disappears as computers are more and more efficient).
• Harder to get greeks.

### Up-and-Out Call Monte Carlo Pricing example

Tqdm package is useful when you want to see the advancement of loops:

The code gives the final price and the statistical 95% confidence interval :

import numpy as np
import math
from tqdm import tqdm

def compute_barrier_call_payoff(asset_path,strike,barrier):
if max(asset_path)&gt;=barrier:
return 0
if asset_path[-1] - strike &gt; 0:
return asset_path[-1] - strike
return 0

def simulate_price(S,R,Vol,dt,X):
return S*math.exp((R-(Vol**2)/2)*dt + Vol*math.sqrt(dt)*X)

def price_up_and_out_call(volatility,interest_rate,strike,barrier,S0,maturity,dt,nb_time,nb_simulations):
#1 column matrix that contains all the final computed payoffs:
all_final_payoffs = np.zeros((nb_simulations, 1), dtype=float)

for i in tqdm(range(nb_simulations)):
path_generated_asset = np.zeros((1, nb_time), dtype=float)  # 1 row matrix that contains the random walk
path_generated_asset[0, 0] = S0  # Initial value of the asset is S0:
for j in range(1, nb_time):
X = np.random.randn(1)
path_generated_asset[0, j] = simulate_price(path_generated_asset[0, j - 1], interest_rate, volatility, dt, X)

#Compute the payoff for the generated random walk and store the value in all_final_payoffs:
all_final_payoffs[i, 0] = compute_barrier_call_payoff(path_generated_asset[0, :], strike, barrier)

option_price = np.mean(all_final_payoffs) * math.exp(-interest_rate * maturity)
variance_payoff = np.std(all_final_payoffs)
upper_bound_95 = option_price + 1.96 * variance_payoff / math.sqrt(nb_simulations)
lower_bound_95 = option_price - 1.96 * variance_payoff / math.sqrt(nb_simulations)
print("Option price : {}".format(option_price))
print("{} barrier {} strike up and out 95% confident call price interval : [{} ; {}]".format(barrier, strike,
lower_bound_99,
upper_bound_99))

#Options parameters :
volatility = 0.3
interest_rate = 0.01
strike = 50
barrier = 65
S0 = 50
maturity = 1 #1year
dt = 1/1000
nb_time = 1000
nb_simulations = 10000

price_up_and_out_call(volatility,interest_rate,strike,barrier,S0,maturity,dt,nb_time,nb_simulations)


With $S_0 = 50$, $\sigma = 0.3$, $R = 0.01$, $K = 50$, $B = 65$, $T=1$, $dt = \frac{1}{1000}$ and 10 000 simulations I get 0.795 and it takes 1 minute for my computer to complete the process. The real price is roughly 0.73 for this barrier option.

Decreasing time discretization to $dt = \frac{1}{2000}$ and increasing the number of simulations to 20 000 leads me to 0.755\$ in 3 mins 50 secs and a smaller 95% confidence interval (still pretty large).

Note that for path-dependent option pricing, a sufficient number a time-steps is really important since it better models the underlying’s price movement. Taking thinner time-steps when it gets closer could be relevant here!

### Conclusion

Monte Carlo is a numerical method widely used in finance to price derivatives. Its precision slowly increases by $\frac{1}{\sqrt{N}}$ with N the number of simulations. Powerful Variance Reduction methods exist to reduce the variance of the generated payoffs and get a more accurate price while not changing the number of simulations, we will see them in a next article!

For improvement of the execution time (very very poor here), one can use Cython (generate your Python code in C and allows typing your variables) or implement the pricer in C++ or C#. For the same set of parameters it takes for me:

• Cythonize only: 2mins 50secs
• Cython + typed variables: 1min
• C# : 7secs

### Reference

Paul Wilmott – Introduces Quantitative Finance, Chapter 13.