def call_on_zero_coupon_bond(today=None, strike_date=None, maturity=None, strike_price=None, zeros=None, dcf_method=None, **params): S = dcf(today, strike_date, method=dcf_method) T = dcf(today, maturity, method=dcf_method) bond_S = zeros[strike_date] bond_T = zeros[maturity] a, b = params['k'] sigma, nu = params['nu'] rho = params['rho'][0][1] sigma_term = np.sqrt(mini_sigma(a, b, sigma, nu, rho, 0, S, T)) factor = np.log(bond_T / (bond_S * strike_price)) / sigma_term return bond_T * norm.cdf(factor + sigma_term / 2) - bond_S * strike_price * norm.cdf( factor - sigma_term / 2)
def floorlet_black(bond, forward, S, T, K, sigma, method='Act360'): dcf_factor = dcf(S, T, method=method) vol = sigma * np.sqrt(S) return bond * dcf_factor * blacklet(K, S, forward, vol, omega=-1)
def bond_func(maturity, **params): maturity_in_yrs = dcf(today, maturity, method=bond_dcf) # Here shift is purposely different than delta, which should be zero, as we prefer to do shift by # using the extension with his shift parameter. return BondPriceFunction(0, maturity_in_yrs, **params) * np.exp( -params['shift'] * maturity_in_yrs)
def ZBC_func(strike_date, bond_maturity, K, **params): market_to_strike = bond_func(strike_date, **params) market_to_bond_maturity = bond_func(bond_maturity, **params) S_bond = dcf(today, strike_date, method=bond_dcf) T_bond = dcf(today, bond_maturity, method=bond_dcf) S_opt = dcf(today, strike_date, method=ZBC_dcf) T_opt = dcf(today, bond_maturity, method=ZBC_dcf) ref_model_strike = BondPriceFunction(0, S_bond, **params) ref_model_bond_maturity = BondPriceFunction(0, T_bond, **params) modifier = market_to_bond_maturity / ref_model_bond_maturity modified_strike = K * (market_to_strike / ref_model_strike) / modifier return ZBCPricerFunction(0, S_opt, T_opt, modified_strike, ** params) * modifier
def in_default_func(maturity, **params): maturity_in_yrs = dcf(today, maturity, method=bond_dcf) # Here we do not use shift method but we use the intrisitic bond value function. return InDefaultFunction(0, maturity_in_yrs, **params)
def test_dcf_2_x_3(): df = dcf.dcf(8.08, growth_rates=[-0.01, -0.02], discount_rates=[0.00, 0.01, 0.02]) expected = np.array([[799.9, 395.9], [398.0, 263.1], [263.1, 196.0]]) assert np.allclose(df.values, expected, atol=0.1)
discount_rates = [ 0.00, 0.01, 0.02, 0.03, 0.04, 0.05 ] # I honestly have no idea how to think about discount rates years = [2018, 2019, 2020] key_df = pd.DataFrame.from_records( [ [7.5239, 7.8880, 8.0800], # billion USD [1.333, 2.117, 4.945], # billion USD [25.746, 28.042, 29.471], # billion USD ], columns=[str(x) for x in years], index=["adj_earnings", "cash", "debt"]) wt_avg_fixed_cpn = 0.0413 # see DDIS; wt_avg_yrs = 11.78 share_price = 41.06 # USD shares = 1.86 # billion if __name__ == '__main__': # print(key_df) pd.set_option('display.float_format', '{:.1f}'.format) df = dcf.dcf( np.mean(key_df.loc["adj_earnings"]), growth_rates, discount_rates, debt=np.mean(key_df.loc["debt"]), cash=np.mean(key_df.loc["cash"]), debt_rate=wt_avg_fixed_cpn, ) print( f"Adj EPS PV: base=2018-2020, debt=naive, shares=constant, terminal-value=0\n{df / shares}" )