I am trying to show the monte carlo barrier prices for different number of simultations in the x axis. This is what i tried so far but i'm getting the error -> ValueError: x and y must have same first dimension, but have shapes (10,) and (5,).
I am new to python and as hard as i try i cannot find the error
import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt
def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):
# Constants
dt = T / N # change in time
nudt = (r - 0.5 * vol ** 2) * dt # deterministic component
volsdt = vol * np.sqrt(dt) # diffusion coefficient
erdt = np.exp(r * dt) # discount factor
# Standard Error Placeholders
sum_CT = 0
sum_CT2 = 0
# Monte Carlo Method
for i in range(M):
# Barrier Crossed Flag
BARRIER = False
St = S0
for j in range(N):
epsilon = np.random.normal()
Stn = St * np.exp(nudt + volsdt * epsilon)
St = Stn
Ptn = np.exp(-2. * (H - St) * (H - Stn) / (St ** 2. * volsdt ** 2.))
Pt = Ptn
if Pt >= npr.uniform():
BARRIER = True
if np.amin(St) > H and BARRIER == False:
CT = np.maximum(St - K, 0)
else:
CT = 0.
sum_CT = sum_CT + CT
sum_CT2 = sum_CT2 + CT * CT
C0_MC = np.exp(-r * T) * sum_CT / M
return C0_MC
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
assert (method in ['MC', 'AV', 'CV'])
mean_payoffs = np.zeros(int(np.ceil(max_sample / 10)))
if method == 'MC':
for n_sample in range(10, max_sample + 1, 10):
payoffs = mc_single_barrier_do(n_sample, S0, K, T, H, r, vol, N)
mean_payoffs[int(n_sample / 10 - 1)] = np.mean(payoffs)
return mean_payoffs
r = 0.1
vol = 0.2
T = 2
N = 20
dt = T / N
S0 = 50
K = 50
H = 45
max_sample = 100
MC_price_estimates = sim_iterator(S0, T, r, vol, K, H, max_sample, N, method='MC')
x_axis1 = range(10, max_sample + 1, 10)
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("No. of Simulations")
plt.ylabel("Estimated option price")
plt.title("Ordinary Monte Carlo Method")
plt.legend()
plt.show()
in your function definition you used:
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
while when using the function you used:
MC_price_estimates = sim_iterator(S0, T, r, vol, K, H, max_sample, N, method='MC')
python has positional arguments, which means the arguments are mapped according to their position, not their name, so in the first position is mapped to the first argument, which means S0 in the second line was mapped to max_sample in the first line, just fix the arguments arrangement, or use keyword arguments S0=S0.
MC_price_estimates = sim_iterator(S0=S0, T=T, r=r, vol=vol, K=K, H=H, max_sample=max_sample, N=N, method='MC')
this is what your code will look like when you fix all arguments to be keyword arguments.
def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):
# Constants
dt = T / N # change in time
nudt = (r - 0.5 * vol ** 2) * dt # deterministic component
volsdt = vol * np.sqrt(dt) # diffusion coefficient
erdt = np.exp(r * dt) # discount factor
# Standard Error Placeholders
sum_CT = 0
sum_CT2 = 0
# Monte Carlo Method
for i in range(M):
# Barrier Crossed Flag
BARRIER = False
St = S0
for j in range(N):
epsilon = np.random.normal()
Stn = St * np.exp(nudt + volsdt * epsilon)
St = Stn
Ptn = np.exp(-2. * (H - St) * (H - Stn) / (St ** 2. * volsdt ** 2.))
Pt = Ptn
if Pt >= npr.uniform():
BARRIER = True
if np.amin(St) > H and BARRIER == False:
CT = np.maximum(St - K, 0)
else:
CT = 0.
sum_CT = sum_CT + CT
sum_CT2 = sum_CT2 + CT * CT
C0_MC = np.exp(-r * T) * sum_CT / M
return C0_MC
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
assert (method in ['MC', 'AV', 'CV'])
mean_payoffs = np.zeros(int(np.ceil(max_sample / 10)))
if method == 'MC':
for n_sample in range(10, max_sample + 1, 10):
payoffs = mc_single_barrier_do(M=n_sample,S0= S0, K=K, T=T, H=H, r=r, vol=vol, N=N)
mean_payoffs[int(n_sample / 10 - 1)] = np.mean(payoffs)
return mean_payoffs
r = 0.1
vol = 0.2
T = 2
N = 20
dt = T / N
S0 = 50
K = 50
H = 45
max_sample = 100
MC_price_estimates = sim_iterator(S0=S0, T=T, r=r, vol=vol, K=K, H=H, max_sample=max_sample, N=N, method='MC')
x_axis1 = range(10, max_sample + 1, 10)
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("No. of Simulations")
plt.ylabel("Estimated option price")
plt.title("Ordinary Monte Carlo Method")
plt.legend()
plt.show()
I have a given power spectral density function of a wind excitation. In order to find my covariance function, I am using the irfft function in python. However, the covariance function is weirdly mirrored at about x = 5.
Here is my code.
def to_time_domain(x, y):
N = 2*len(x)-1 # Number of samples in the time domain
T = (len(x)-1) / (x[-1]) # observation length in time
sample_rate = N/T
ys =irfft(y*sample_rate/2, N-1)
return ys
# power spectral density of wind
def Gust_induced_vibration( vm, vm_10 ,z ,f, k, alpha, roh = 1.25): #
I_z_quad = 6 * k * (z/10)**(-2* alpha)
v_z = vm_10 * (z/10)**alpha
zeta = 1200 * f/ vm_10
S = (roh * 2 * vm)**2 * I_z_quad * v_z**2 * 2/3 * zeta**2 / ((1 + zeta** 2)**(4/3))
return S
sample_rate = 250 #data point per second --> max. freq: sample_rate/2
T = 10 # observation length
N = sample_rate * T # number of samples
dt = 1/sample_rate #time step
f = rfftfreq(N, 1/sample_rate)
#environmental conditions that influence the excitation
k = 0.02 #city
z = 10 # m
v = 22 # m/s
alpha = 1/np.log(10/0.5) #depends on surface roughness
power_spec = Gust_induced_vibration( v, v, z ,f, k, alpha)
#covariance
cov = to_time_domain(f,power_spec)
t = np.linspace(0, T-dt, sample_rate * T)
plt.plot(t, cov)
plt.show()
The plot of the covariance function looks as following.
Plot of covariance
I am grateful for every tip!
I'm trying to approximate the European call option price of the Black-Scholes model (PDE) by the explicit finite difference method in python. For reference, the exact solution using the Black-Scholes formula is 10.247013813310648
Here is a link about the PDE Black-Scholes Equation and the discretized version of the equation can be found here Explicit finite difference method for Black-Scholes model
Can anyone point out why I'm not getting an approximation?
import numpy as np
# Terminal time
T = 0.25
# Strike price
K = 10
# risk free rate
r = 0.1
# volatility (systemic/market risk)
sigma = 0.4
# initial asset value
S0 = 20
# Assume an upper limit for the underlying stock that is 3 - 4 times the exercise price
S_max = 3 * K
# Number of space intervals
M = 200
# space mesh and space step
space_mesh, space_step = np.linspace(0, S_max, M, retstep=True)
# Stability condition
stability_cond = 1 / ( sigma**2 * (M-1) + 0.5* r )
# Find the number of time intervals and time steps that satisfy the stability condition
for percentage in np.arange(.99, .0001, -.0001):
time_step = np.round(percentage * stability_cond, 6)
N = T / time_step
if N.is_integer():
print("Number of time intervals = ", N," ", "time step = ", time_step)
# Choose number of time intervals
N = 2000
# time mesh
time_mesh, time_step = np.linspace(0, T, N, retstep= True)
# time step
time_step = np.round(time_step, 6)
# unknown u at new time level
u = np.zeros(M)
# u at the previous time level
u_prev = np.zeros(M)
# initial condition
for m in range(0, M):
u_prev[m] = np.maximum(space_mesh[m] - K, 0)
# Explicit finite difference scheme
for n in range(0, N):
for m in range(1,M-1):
a = 0.5 * time_step * ( sigma**2 *m**2 - r * m )
b = 1 - time_step * ( sigma**2 * m**2 + r )
c = 0.5 * time_step * ( sigma**2 * m**2 + r * m)
# The discretized version of the Black-Scoles PDE
u[m] = a * u_prev[m-1] + b* u_prev[m] + c * u_prev[m+1]
# insert boundry conditions
u[0] = 0
u[M-1] = S_max
# update u_prev before next iteration
u_prev[:] = u
I'm new to python so the code may not be the best. I'm trying to find the minimum Total Cost (TotalC) and the corresponding m,k and xM values that go with this minimum cost. I'm not sure how to do this. I have tried using min(TotalC) however this gives an error within the loop or outside the loop only returns the value of TotalC and not the corresponding m, k, and xM values. Any help would be appreciated. This section is at the end of the code, I have included my entire code.
import numpy as np
import matplotlib.pyplot as plt
def Load(x):
Fpeak = (1000 + (9*(x**2) - (183*x))) *1000 #Fpeak in N
td = (20 - ((0.12)*(x**2)) + (4.2*(x))) / 1000 #td in s
return Fpeak, td
#####################################################################################################
####################### Part 2 ########################
def displacement(m,k,x,dt): #Displacement function
Fpeak, td = Load(x) #Load Function from step 1
w = np.sqrt(k/m) # Natural circular frequency
T = 2 * np.pi /w #Natural period of blast (s)
time = np.arange(0,2*T,0.001) #Time array with range (0 - 2*T) with steps of 2*T/100
zt = [] #Create a lsit to store displacement values
for t in time:
if (t <= td):
zt.append((Fpeak/k) * (1 - np.cos(w*t)) + (Fpeak/(k*td)) * ((np.sin(w*t)/w) - t))
else:
zt.append((Fpeak/(k*w*td)) * (np.sin(w*t) - np.sin(w*(t-td))) - ((Fpeak/k) * np.cos(w*t)))
zmax=max(zt) #Find the max displacement from the list of zt values
return zmax #Return max displacement
k = 1E6
m = 200
dt = 0.0001
x = 0
z = displacement(m,k,x,dt)
###################################################################################
############### Part 3 #######################
# k = 1E6 , m = 200kg , Deflection = 0.1m
k_values = np.arange(1E6, 7E6, ((7E6-1E6)/10)) #List of k values between min and max (1E6 and 7E6).
m_values = np.arange(200,1200,((1200-200)/10)) #List of m values between min and max 200kg and 1200kg
xM = []
for k in k_values: # values of k
for m in m_values: # values of m within k for loop
def bisector(m,k,dpoint,dt): #dpoint = decimal point accuracy
xL = 0
xR = 10
xM = (xL + xR)/2
zmax = 99
while round(zmax, dpoint) !=0.1:
zmax = displacement(m,k,xM,dt)
if zmax > 0.1:
xL = xM
xM = (xL + xR)/2
else:
xR = xM
xM = (xL + xR)/2
return xM
xM = bisector(m, k, 4, 0.001)
print('xM value =',xM)
####################################################################################
def cost (m,k,xM):
Ck = np.array(900 + 825*((k/1E6)**2) - (1725*(k/1E6)))
Cm = np.array(10*m - 2000)
Cx = np.array(2400*((xM**2)/4))
TotalC = Ck + Cm + Cx
print(TotalC)
print(min(TotalC))
return TotalC
TotalC = cost(m, k, xM)
print([xM, m, k, TotalC])
You want this:
minIndex = TotalC.argmin()
Now you use that numeric index into all your arrays TotalC, Ck, Cm and Cx.
find the index of the min value in total and the index should be same for corresponding arrays.
I've created a fatorial function that would help me calculate the taylor expansion of sine. There are no evident mistakes in my code, but the returned value is wrong. That's my code:
PI = 3.14159265358979323846
def fatorial(n):
fatorial = 1
for i in range(1,n+1,1):
fatorial = fatorial * i
return fatorial
def seno(theta):
n = 1
k = 3
eps = 10**-10
theta = (theta*PI)/180
x = ((-1)**n)*((theta)**k)
y = fatorial(k)
while x/y > eps or x/y < -eps:
theta = theta + (x/y)
n = n + 1
k = k + 2
x = ((-1)**n) * ((theta)**k)
y = fatorial(k)
return theta
You are summing theta in the while-loop and therefore using an adjusted angle for the next elements of the Taylor series. Just add a thetas (for the sum) like so (I have taken the liberty to add some performance improvements, no need to recalculate the full factorial, also calculated first elements explicitly and changed the limit check to avoid recalculations of x/y):
import math
PI = 3.14159265358979323846
def fatorial(n):
fatorial = 1
for i in range(1,n+1,1):
fatorial = fatorial * i
return fatorial
def seno(theta):
n = 1
k = 3
#eps = 10**-10
theta = (theta*PI)/180
thetas = theta # <- added this
x = -theta*theta*theta
y = 6
#while x/y > eps or x/y < -eps:
while k < 14:
thetas = thetas + (x/y) # sum thetas
n = n + 1
k = k + 2
#x = ((-1)**n) * ((theta)**k)
x = ((-1)**(n%2)) * ((theta)**k) # but use the original value for the series
#y = fatorial(k)
y *= k * (k-1)
return thetas # return the sum
if __name__ == '__main__':
print(seno(80), math.sin(8*PI/18))
this results in
0.984807753125684 0.984807753012208