# Is this the right way to accelerate my Monte-Carlo Simulation

I am trying to develop a pricer for Call VS Call and I'm using MonteCarlo method to do so because my stocks are correlated between each others.

Basically my inputs are stockswhich is a dataframe whose columns are stock name, volatility, weight for the basket, strike, spot and dividendes, datawhich is a dictionary with the risk free rate, the number of simulations to do and the time to maturity and finally correlationwhich is going to be the implied correlation between stocks (I chose to take it as a float instead of correlation matrix because there is usually only two stocks).

I do Monte-Carlo because there is correlation between my stocks but my option is not path dependent, so I thought I could skip generating X steps for each simulation and directly generate the move over the life of the option. Then I could generate an random array of length (number of stocks, number of simulation) and thus get rid of the usual double loop which is slowing the simulation. When I do like this, I'm able to generate about a million simulation in around 1 second.

However, I struggle to really understand if my way of doing it is good and if this approach is theoretically valid.

Here is my code so each of you can see how I do it :

import random
import matplotlib as plt
import numpy as np
from math import *
import pandas as pd

class CallVsCallCalculation() :
def __init__(self,stocks,data,correlation):
self.stocks = stocks
self.data = data
self.correlation = correlation

no_obs = int(self.data["correlation"])
r = self.data["rate"]
T= self.data["time_to_maturity"]
self.weight = np.array(self.stocks["Weight"]).reshape(len(self.stocks["Weight"]),1)
self.strike= np.array(self.stocks["Strike"])
self.spot =np.array(self.stocks["Spot"])
self.dividend =np.array(self.stocks["Dividendes"])
means= [0]*len(self.stocks["Variance"])
no_cols=len(self.stocks["Asset_name"])
self.vol=list(self.stocks["Variance"])
sd = np.diag(self.vol)

observations=np.random.normal(0, 1,(no_cols, no_obs))

cor_matrix = np.zeros(shape=(no_cols,no_cols))
for i in range (no_cols):
for j in range (no_cols):
if i==j :
cor_matrix[i][j]=11
else :
cor_matrix[i][j])=self.correlation

cov_matrix = np.dot(sd,np.dot(cor_matrix, sd))
Chol = np.linalg.cholesky(cov_matrix)
self.chol = np.linalg.cholesky(cov_matrix)
sam_eq_mean = chol.dot(observations)
s = sam_eq_mean.transpose() + means
samples = s.transpose()

std = np.array(self.vol)
std **=2
std = -std/2
std += r
std -= self.dividend
std*=(T)

eps_array = samples*np.sqrt(T)
eps_array = eps_array*np.array(self.vol).reshape((2,1))
expi = std.reshape(len(self.stocks["Variance"]),1) + eps_array
#Computing the last last price, or the price at expiration
self.last_price =  self.spot.reshape(len(self.stocks["Variance"]),1)*np.exp(expi)
#Dividing each price by the initial price
self.last_price_perc = self.last_price/self.spot.reshape(len(self.stocks["Variance"]),1)
#Getting each price regarding its weights
self.last_price_weighted = self.weight.T @self.last_price_perc
#Calculating the strike
#Getting the payoff for the basket

#Getting the strike in term of percentage
self.strike_stock - self.strike/self.spot
#weighing the last price by the initial price
self.last_price_on_spot = self.last_price/self.spot.reshape(len(self.stocks["Variance"]),1)
#Discounting the strike
self.last_price_minus_strike = self.last_price_on_spot-self.strike_stock.reshape(len(self.stocks["Variance"]),1)
#Getting the payoff
self.payoff_long = np.maximum(self.last_price_minus_strike,0)
#Taking the mean of each stocks
self.payoff_long_mean = self.payoff_long.mean(axis=1)
#Getting also the weight
self.long_payoff = self.weight.T@self.payoff_long_mean

#Getting the call price
self.call_price = (self.long_payoff-self.short_payoff)[0]*np.exp(-r*T)


I also get used of that topic to ask a smaller question about the stock price formula :

I struggle to understand what is the real origin of W in this formula when you consider correlated basket. Is it only the random samples and is it random samples that were multiplied by the lower matrix of the Cholesky decomposition of the covariance matrix ?

Thanks everyone for your help on both question, I hope I was clear enough !

• Hi, could you add the definition of the call-vs-call option, please? Thanks a lot Apr 5 at 19:59
• A call VS call option is a option when you are long a call on every underlying of a basket with their weight and short a call on a basket composed of those underlying with their weight, it gives you exposure to the correlation between the underlyings Apr 5 at 21:55
• Thanks! So the payoff is $\sum w_i (S_i-X_i)^+ - (\sum w_iS_i-X)^+$ ? Apr 6 at 4:25
• Yes exactly, but for my question you can also consider that I'm getting the payoff only for the basket of stocks, as it juste a different computation ones you did simulates the prices Apr 6 at 8:38