I want to use the fsolve
one by one for each iteration. Supposed I have DataFrame
look like below:
PD Downturn | PD TTC |
---|---|
0.12 | 0.008 |
0.15 | 0.016 |
0.24 | 0.056 |
0.56 | 0.160 |
1.00 | 1.000 |
Here is the code I try:
result = []
for i in range(len(df) - 1):
def R(x):
ZDownturn = norm.ppf(df['PD Downturn'])[i] #Exclude 'Default' class
ZShift = np.sqrt(
x / (1 - x)
) * norm.ppf(0.999)
ZPortion = np.sqrt(
1 / (1 - x)
) * norm.ppf(df['PD TTC'])[i] #Exclude 'Default' class
target = ZShift + ZPortion
error = np.abs(ZDownturn - target)
return error
# Initial guess
x0 = [0.01]
# Solver
Rho = fsolve(R, x0)
result.append(Rho[0])
I want to find x
variable based on some calculation logic but I need to do it one-by-one. So, I create the new function in every iteration. The results are below:
[0.19153452995548875,
0.15906256238706026,
0.08759684851688349,
0.1348702069117432]
It's work but I am looking for another way maybe more pythonic way to write the code.
Thank you.
You're probably looking for a vectorized version of your objective function. That's exactly where numpy shines:
import numpy as np
from scipy.optimize import fsolve
from scipy.stats import norm
pd_downturn = np.array([0.12, 0.15, 0.24, 0.56])
pd_ttc = np.array([0.008, 0.016, 0.056, 0.160])
#pd_downturn = df['PD Downturn'].values[:-1]
#pd_ttc = df['PD TTC'].values[:-1]
def R(x):
ZDownturn = norm.ppf(pd_downturn)
ZShift = np.sqrt(x / (1 - x)) * norm.ppf(0.999)
ZPortion = np.sqrt(1 / (1 - x)) * norm.ppf(pd_ttc)
target = ZShift + ZPortion
error = (ZDownturn - target)**2
return error
# Initial guess
x0 = 0.01*np.ones(pd_downturn.size)
# Solver
result = fsolve(R, x0)
Note note you should try to avoid np.abs
for root-finding or optimization problems whenever possible, just square the difference instead. The absolute value function is not differentiable at the point where its argument is zero and thus you'd be violating the mathematical assumptions of most algorithms under the hood of fsolve
.