Skip to content

Commit

Permalink
Minor pep8changes
Browse files Browse the repository at this point in the history
  • Loading branch information
domokane committed Mar 9, 2024
1 parent 7344c27 commit d65c57e
Show file tree
Hide file tree
Showing 22 changed files with 305 additions and 317 deletions.
22 changes: 11 additions & 11 deletions financepy/market/curves/discount_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class DiscountCurve:

def __init__(self,
value_dt: Date,
df_dts: list,
df_dates: list,
df_values: np.ndarray,
interp_type: InterpTypes = InterpTypes.FLAT_FWD_RATES):
""" Create the discount curve from a vector of times and discount
Expand All @@ -43,26 +43,26 @@ def __init__(self,
check_argument_types(self.__init__, locals())

# Validate curve
if len(df_dts) < 1:
if len(df_dates) < 1:
raise FinError("Times has zero length")

if len(df_dts) != len(df_values):
if len(df_dates) != len(df_values):
raise FinError("Times and Values are not the same")

self._times = [0.0]
self._dfs = [1.0]
self._df_dts = df_dts
self._df_dates = df_dates

num_points = len(df_dts)
num_points = len(df_dates)

start_index = 0
if num_points > 0:
if df_dts[0] == value_dt:
if df_dates[0] == value_dt:
self._dfs[0] = df_values[0]
start_index = 1

for i in range(start_index, num_points):
t = (df_dts[i] - value_dt) / gDaysInYear
t = (df_dates[i] - value_dt) / gDaysInYear
self._times.append(t)
self._dfs.append(df_values[i])

Expand Down Expand Up @@ -298,8 +298,8 @@ def df(self,

if isinstance(dfs, float):
return dfs
else:
return np.array(dfs)

return np.array(dfs)

###########################################################################

Expand Down Expand Up @@ -452,10 +452,10 @@ def fwd_rate(self,
def __repr__(self):

s = label_to_string("OBJECT TYPE", type(self).__name__)
num_points = len(self._df_dts)
num_points = len(self._df_dates)
s += label_to_string("DATES", "DISCOUNT FACTORS")
for i in range(0, num_points):
s += label_to_string("%12s" % self._df_dts[i],
s += label_to_string("%12s" % self._df_dates[i],
"%12.8f" % self._dfs[i])

return s
Expand Down
62 changes: 31 additions & 31 deletions financepy/market/volatility/fx_vol_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@


@njit(fastmath=True, cache=True)
def g(K, *args):
def g(k, *args):
""" This is the objective function used in the determination of the FX
option implied strike which is computed in the class below. """

Expand All @@ -56,7 +56,7 @@ def g(K, *args):
option_type_value = args[6]
delta_target = args[7]

delta_out = fast_delta(s, t, K, r_d, r_f,
delta_out = fast_delta(s, t, k, r_d, r_f,
volatility,
delta_method_value,
option_type_value)
Expand All @@ -78,7 +78,7 @@ def obj_fast(params, *args):
t = args[1]
r_d = args[2]
r_f = args[3]
K_ATM = args[4]
k_atm = args[4]
atm_vol = args[5]
k_25d_c_ms = args[6]
k_25d_p_ms = args[7]
Expand All @@ -92,7 +92,7 @@ def obj_fast(params, *args):
# new volatility curve

# Match the at-the-money option volatility
atm_curve_vol = vol_function(vol_type_value, params, f, K_ATM, t)
atm_curve_vol = vol_function(vol_type_value, params, f, k_atm, t)
term1 = (atm_vol - atm_curve_vol)**2

###########################################################################
Expand Down Expand Up @@ -147,7 +147,7 @@ def obj_fast(params, *args):

def solve_to_horizon_fast(s, t,
rd, rf,
K_ATM, atm_vol,
k_atm, atm_vol,
ms_25d_vol, rr_25d_vol,
delta_method_value, vol_type_value,
xopt):
Expand Down Expand Up @@ -185,7 +185,7 @@ def solve_to_horizon_fast(s, t,
tol = 1e-8

fargs = (s, t, rd, rf,
K_ATM, atm_vol,
k_atm, atm_vol,
k_25d_c_ms, k_25d_p_ms,
v_25d_ms,
delta_method_value, rr_25d_vol, vol_type_value)
Expand Down Expand Up @@ -565,7 +565,7 @@ def build_vol_surface(self):
self._F0T = np.zeros(num_vol_curves)
self._rd = np.zeros(num_vol_curves)
self._rf = np.zeros(num_vol_curves)
self._K_ATM = np.zeros(num_vol_curves)
self._k_atm = np.zeros(num_vol_curves)
self._deltaATM = np.zeros(num_vol_curves)

self._k_25d_c = np.zeros(num_vol_curves)
Expand Down Expand Up @@ -598,13 +598,13 @@ def build_vol_surface(self):

# This follows exposition in Clarke Page 52
if self._atm_method == FinFXATMMethod.SPOT:
self._K_ATM[i] = s
self._k_atm[i] = s
elif self._atm_method == FinFXATMMethod.FWD:
self._K_ATM[i] = f
self._k_atm[i] = f
elif self._atm_method == FinFXATMMethod.FWD_DELTA_NEUTRAL:
self._K_ATM[i] = f * np.exp(atm_vol*atm_vol*t_exp/2.0)
self._k_atm[i] = f * np.exp(atm_vol*atm_vol*t_exp/2.0)
elif self._atm_method == FinFXATMMethod.FWD_DELTA_NEUTRAL_PREM_ADJ:
self._K_ATM[i] = f * np.exp(-atm_vol*atm_vol*t_exp/2.0)
self._k_atm[i] = f * np.exp(-atm_vol*atm_vol*t_exp/2.0)
else:
raise FinError("Unknown Delta Type")

Expand Down Expand Up @@ -684,14 +684,14 @@ def build_vol_surface(self):
t = self._t_exp[i]
r_d = self._rd[i]
r_f = self._rf[i]
K_ATM = self._K_ATM[i]
k_atm = self._k_atm[i]
atm_vol = self._atm_vols[i]
ms_25d_vol = self._ms25DeltaVols[i]
rr_25d_vol = self._rr25DeltaVols[i]

# print(t, rd, rf, K_ATM, atm_vol, ms_25d_vol, rr_25d_vol)
# print(t, rd, rf, k_atm, atm_vol, ms_25d_vol, rr_25d_vol)

res = solve_to_horizon_fast(s, t, r_d, r_f, K_ATM,
res = solve_to_horizon_fast(s, t, r_d, r_f, k_atm,
atm_vol, ms_25d_vol, rr_25d_vol,
delta_method_value, vol_type_value,
x_inits[i])
Expand Down Expand Up @@ -784,32 +784,32 @@ def check_calibration(self, verbose: bool, tol: float = 1e-6):
print("CNT_CPD_RF:%9.6f %%" % (self._rf[i]*100))
print("FWD_RATE: %9.6f" % (self._F0T[i]))

sigma_ATM_out = vol_function(self._vol_func_type.value,
sigma_atm_out = vol_function(self._vol_func_type.value,
self._parameters[i],
self._F0T[i],
self._K_ATM[i],
self._k_atm[i],
self._t_exp[i])

if verbose:
print("======================================================")
print("VOL FUNCTION", self._vol_func_type)
print("VOL_PARAMETERS:", self._parameters[i])
print("======================================================")
print("OUT_K_ATM: %9.6f" % (self._K_ATM[i]))
print("OUT_K_ATM: %9.6f" % (self._k_atm[i]))
print("OUT_ATM_VOL: %9.6f %%"
% (100.0*sigma_ATM_out))
% (100.0*sigma_atm_out))

diff = sigma_ATM_out - self._atm_vols[i]
diff = sigma_atm_out - self._atm_vols[i]

if np.abs(diff) > tol:
print("FAILED FIT TO ATM VOL IN: %9.6f OUT: %9.6f DIFF: %9.6f" %
(self._atm_vols[i]*100.0, sigma_ATM_out*100.0,
(self._atm_vols[i]*100.0, sigma_atm_out*100.0,
diff * 100.0))

call._strike_fx_rate = self._K_ATM[i]
put._strike_fx_rate = self._K_ATM[i]
call._strike_fx_rate = self._k_atm[i]
put._strike_fx_rate = self._k_atm[i]

model = BlackScholes(sigma_ATM_out)
model = BlackScholes(sigma_atm_out)

delta_call = call.delta(self._value_dt,
self._spot_fx_rate,
Expand Down Expand Up @@ -1072,8 +1072,8 @@ def plot_vol_curves(self):
strikes = []
vols = []
num_intervals = 30
K = low_k
dK = (high_k - low_k)/num_intervals
k = low_k
dk = (high_k - low_k)/num_intervals
params = self._parameters[tenor_index]
t = self._t_exp[tenor_index]
f = self._F0T[tenor_index]
Expand All @@ -1082,7 +1082,7 @@ def plot_vol_curves(self):
sigma = vol_function(vol_type_val, params, f, K, t) * 100.0
strikes.append(K)
vols.append(sigma)
K = K + dK
k = k + dk

label_str = self._tenors[tenor_index]
label_str += " ATM: " + str(atm_vol)[0:6]
Expand All @@ -1097,7 +1097,7 @@ def plot_vol_curves(self):
" " + str(self._vol_func_type)

key_strikes = []
key_strikes.append(self._K_ATM[tenor_index])
key_strikes.append(self._k_atm[tenor_index])

key_vols = []
for K in key_strikes:
Expand All @@ -1114,8 +1114,8 @@ def plot_vol_curves(self):

key_vols = []

for K in key_strikes:
sigma = vol_function(vol_type_val, params, f, K, t) * 100.0
for k in key_strikes:
sigma = vol_function(vol_type_val, params, f, k, t) * 100.0
key_vols.append(sigma)

plt.plot(key_strikes, key_vols, 'bo', markersize=4)
Expand Down Expand Up @@ -1149,10 +1149,10 @@ def __repr__(self):
s += label_to_string("MS VOLS", self._ms25DeltaVols[i]*100.0)
s += label_to_string("RR VOLS", self._rr25DeltaVols[i]*100.0)

s += label_to_string("ATM Strike", self._K_ATM[i])
s += label_to_string("ATM Strike", self._k_atm[i])
s += label_to_string("ATM Delta", self._deltaATM[i])

s += label_to_string("K_ATM", self._K_ATM[i])
s += label_to_string("k_atm", self._k_atm[i])
s += label_to_string("MS 25D Call Strike", self._k_25d_c_ms[i])
s += label_to_string("MS 25D Put Strike", self._k_25d_p_ms[i])
s += label_to_string("SKEW 25D CALL STRIKE", self._k_25d_c[i])
Expand Down
24 changes: 12 additions & 12 deletions financepy/market/volatility/swaption_vol_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ def _solve_to_horizon(t, f,
opt = minimize(_obj, x_inits, args, method="CG", tol=tol)
xopt = opt.x

print("t: %9.5f alpha:%9.5f beta: %9.5f rho: %9.5f nu: %9.5f" %
(t, xopt[0], 0.5, xopt[1], xopt[2]))
# print("t: %9.5f alpha:%9.5f beta: %9.5f rho: %9.5f nu: %9.5f" %
# (t, xopt[0], 0.5, xopt[1], xopt[2]))

params = np.array(xopt)
return params
Expand Down Expand Up @@ -414,13 +414,13 @@ def __init__(self,

self._build_vol_surface(fin_solver_type=fin_solver_type)

self._F0T = []
self._stock_price = None
self._atm_method = None
self._atm_vols = []
self._delta_method = None
self._strikes = []
self._vol_grid = []
# self._F0T = []
# self._stock_price = None
# self._atm_method = None
# self._atm_vols = []
# self._delta_method = None
# self._strikes = []
# self._vol_grid = []

###############################################################################

Expand Down Expand Up @@ -796,6 +796,9 @@ def check_calibration(self, verbose: bool, tol: float = 1e-6):
which sets out the quality of fit to the ATM and 10 and 25 delta market
strangles and risk reversals. """

if self._vol_grid == []:
raise FinError("Error: Vol Grid is empty")

if verbose:

print("==========================================================")
Expand All @@ -811,11 +814,8 @@ def check_calibration(self, verbose: bool, tol: float = 1e-6):
for j in range(0, self._num_strikes):

strike = self._strike_grid[j][i]

fitted_vol = self.vol_from_strike_dt(strike, expiry_dt)

mkt_vol = self._vol_grid[j][i]

diff = fitted_vol - mkt_vol

print("%s %12.3f %7.4f %7.4f %7.5f" %
Expand Down
14 changes: 6 additions & 8 deletions financepy/models/black_scholes_analytic.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ def bs_delta(s, t, k, r, q, v, option_type_value):
elif option_type_value == OptionTypes.EUROPEAN_PUT.value:
phi = -1.0
else:
raise FinError("Unknown option type value")
return 0.0
raise FinError("Error: Unknown option type value")

k = np.maximum(k, g_small)
t = np.maximum(t, g_small)
Expand Down Expand Up @@ -247,17 +246,17 @@ def bs_implied_volatility(s, t, k, r, q, price, option_type_value):
else:
intrinsic_value = np.exp(-r*t) * max(k - fwd, 0.0)

divAdjStockPrice = s * np.exp(-q * t)
div_adj_stock_price = s * np.exp(-q * t)
df = np.exp(-r * t)

# Flip ITM call option to be OTM put and vice-versa using put call parity
if intrinsic_value > 0.0:

if option_type_value == OptionTypes.EUROPEAN_CALL.value:
price = price - (divAdjStockPrice - k * df)
price = price - (div_adj_stock_price - k * df)
option_type_value = OptionTypes.EUROPEAN_PUT.value
else:
price = price + (divAdjStockPrice - k * df)
price = price + (div_adj_stock_price - k * df)
option_type_value = OptionTypes.EUROPEAN_CALL.value

# Update intrinsic based on new option type
Expand All @@ -280,7 +279,7 @@ def bs_implied_volatility(s, t, k, r, q, price, option_type_value):
if option_type_value == OptionTypes.EUROPEAN_CALL.value:
call = price
else:
call = price + (divAdjStockPrice - k * df)
call = price + (div_adj_stock_price - k * df)

# Notation in SSRN-id567721.pdf
X = k * np.exp(-r*t)
Expand Down Expand Up @@ -315,10 +314,9 @@ def bs_implied_volatility(s, t, k, r, q, price, option_type_value):
hsigma = 0.0
gamma = 2.0
arg = (2*call+X-S)**2 - gamma * (S+X)*(S-X)*(S-X) / pi / S

arg = max(arg, 0.0)

hsigma = (2 * call + X - S + np.sqrt(arg))
hsigma = 2.0 * call + X - S + np.sqrt(arg)
hsigma = hsigma * np.sqrt(2.0*pi) / 2.0 / (S+X)
hsigma = hsigma / np.sqrt(t)

Expand Down
Loading

0 comments on commit d65c57e

Please sign in to comment.