I have a function of 5 variables. I would like to visualize how the function behaves by plotting a surface where I span the range of 2 variables and hold the remaining 3 constant.
In my case, the function is Black Scholes and it is a function of S,T,K,r,s: BS(S,T,K,r,s)
And I would like to plot the result of BS(S,T,Kvec,r,svec) Where K and s are replaced with vector inputs. Or BS(Svec,Tvec,K,r,s) Where S and T are replaced with vector inputs. Or BS(S,Tvec,K,r,svec) Where T and K are replaced with vector inputs.
In summary, I would like to have the user pass in 2 vectors and 3 constants and then have the function adapt.
How can I do this elegantly without coding up all 5 Choose 2 cases?
I have tried turning all the inputs into Numpy arrays and then iterating but numpy arrays with a single value are not iterable.
def BS_Call_HyperCube(Svec,Kvec,Tvec,rvec,svec):
Svec = np.asarray(Svec)
Kvec = np.asarray(Kvec)
Tvec = np.asarray(Tvec)
rvec = np.asarray(rvec)
svec = np.asarray(svec)
for S in Svec:
for K in Kvec:
for T in Tvec:
print(S,K,T)
I also tried this:
def BS_Call_HyperCube(Svec,Kvec,Tvec,rvec,vvec):
nS = 1 if isinstance(Svec,(int,float)) else len(Svec)
nK = 1 if isinstance(Kvec,(int,float)) else len(Kvec)
nT = 1 if isinstance(Tvec,(int,float)) else len(Tvec)
nr = 1 if isinstance(rvec,(int,float)) else len(rvec)
nv = 1 if isinstance(svec,(int,float)) else len(vvec)
cube = np.ndarray((nS,nK,nT,nr,ns))
for iS in range(nS):
S = Svec[iS]
for iK in range(nK):
K = Svec[iK]
for iT in range(nT):
T = Svec[iT]
for ir in range(nr):
r = Svec[ir]
for iv in range(nv):
v = Svec[iv]
cube[iS,iK,iT,ir,iv] = BS_Call(S,K,T,r,v)
Is there no way in python to have a degenerate loop that is looping over just a constant?
Apparently to loop over a constant in python simply requires putting that constant in a list to make it iterable. Thank you all for that answer. Regarding the next step of making the constants iterable ... Checking the data type using isinstance seems more elegant than try catch. Please let me know if that is incorrect. Here is my solution below. Thank you all again.
S = 100; K = 100; T = 1; r = .05; s = .32
K = np.linspace(20,70,11)
T = np.linspace(.10,.60,11)
if isinstance(S,(int,float)):
nS = 1
Svec = [S]
else:
nS = len(S)
Svec = S
if isinstance(T,(int,float)):
nT = 1
Tvec = [T]
else:
nT = len(T)
Tvec = T
if isinstance(K,(int,float)):
nK = 1
Kvec = [K]
else:
nK = len(K)
Kvec = K
if isinstance(r,(int,float)):
nr = 1
rvec = [r]
else:
nr = len(r)
rvec = r
if isinstance(s,(int,float)):
ns = 1
svec = [s]
else:
ns = len(s)
svec = s
cube = np.ndarray((nS,nK,nT,nr,ns))
for iS in range(nS):
xS = Svec[iS]
for iK in range(nK):
xK = Kvec[iK]
for iT in range(nT):
xT = Tvec[iT]
for ir in range(nr):
xr = rvec[ir]
for iv in range(ns):
xs = svec[iv]
cube[iS,iK,iT,ir,iv] = BS_Call(xS,xK,xT,xr,xs)
square = np.squeeze(cube)
square.shape