0% found this document useful (0 votes)
48 views

Finance Functions Python

The document contains Python functions for calculating various finance metrics related to bonds and options, including duration, yield spreads, tax implications, and option valuations. The functions take bond prices, yields, tax rates, and other financial values as inputs and return calculated values such as duration, yield spreads, taxable equivalent yields, and option moneyness. Examples are provided for each function.

Uploaded by

Ahmet Arslanoglu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views

Finance Functions Python

The document contains Python functions for calculating various finance metrics related to bonds and options, including duration, yield spreads, tax implications, and option valuations. The functions take bond prices, yields, tax rates, and other financial values as inputs and return calculated values such as duration, yield spreads, taxable equivalent yields, and option moneyness. Examples are provided for each function.

Uploaded by

Ahmet Arslanoglu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Finance Functions Bonds & Options

July 7, 2019

[1]: def duration(per_chg_price, chg_yld):


'''
Summary: Calculate the duration of a bond.

PARA per_chg_price: The percentage change in bond price.


PARA type: float

PARA chg_yld: The yield change in percent.


PARA type: float

'''

return -(per_chg_price / chg_yld)

#EXAMPLE
price_change = -.05
yield_change = .01
duration(price_change, yield_change)
[1]: 5.0
[2]: def absolute_yield_spread(yield_higher, yield_lower):
'''
Summary: Calculate the absolute yield spread given two bonds.

PARA yield_higher: The yield on the higher-yield bond.


PARA type: float

PARA yield_lower: The yield on the lower-yield bond.


PARA type: float

'''

return (yield_higher - yield_lower)

#EXAMPLE
y_h = .0675

1
y_l = .0650
absolute_yield_spread(y_h, y_l)
[2]: 0.0025000000000000022
[3]: def relative_yield_spread(absolute_yield, yield_benchmark):
'''
Summary: Calculate the relative yield spread of a given bond.

PARA absolute_yield: The the absolute yield spread for two given bonds.
PARA type: float

PARA yield_benchmark: The yield of the bond that we are defining as the␣
,→ benchmark, the one we want to compare.
PARA type: float

'''

return absolute_yield / yield_benchmark

#EXAMPLE
y_h = .0675
y_l = .0650
y_a = absolute_yield_spread(y_h, y_l)
relative_yield_spread(y_a, y_l)
[3]: 0.03846153846153849
[4]: def yield_ratio(subject_yield, benchmark_yield):
'''
Summary: Calculate the yield ratio, given two bonds.

PARA subject_yield: The yield of the subject bond.


PARA type: float

PARA benchmark_yield: The yield of the bond that we are defining as the␣
,→ benchmark, the one we want to compare.
PARA type: float

'''

return subject_yield / benchmark_yield

#EXAMPLE
y_h = .0675
y_l = .0650
yield_ratio(y_h, y_l)
[4]: 1.0384615384615385

2
[5]: def after_tax_yield(taxable_yield, marginal_tax_rate):
'''
Summary: Calculate the after-tax yield on a taxable security.

PARA taxable_yield: The taxable yield of a bond.


PARA type: float

PARA marginal_tax_rate: The investor's marginal tax rate.


PARA type: float

'''

return taxable_yield * (1 - marginal_tax_rate)

#EXAMPLE
yld_tax = .10
mrg_tax = .40
after_tax_yield(yld_tax, mrg_tax)
[5]: 0.06
[7]: def taxable_equivalent_yield(tax_free_yield, marginal_tax_rate):
'''
Summary: Calculate the taxable-equivalent yield for a given bond.

PARA tax_free_yield: The tax-free yield of a bond.


PARA type: float

PARA marginal_tax_rate: The investor's marginal tax rate.


PARA type: float

'''

return tax_free_yield / (1 - marginal_tax_rate)

#EXAMPLE
yld_tax = .045
mrg_tax = .350
taxable_equivalent_yield(yld_tax, mrg_tax)
[7]: 0.06923076923076922
[8]: def effective_duration(bond_dec, bond_inc, bond_int, yld_delta):
'''
Summary: Calculate the effective duration of a bond, given a change in␣
,→yield.

PARA bond_dec: The value of a bond is the yield decreases by the␣


,→ yield_delta.

3
PARA type: float

PARA bond_inc: The value of a bond is the yield increases by the␣


,→yield_delta.

PARA type: float

PARA bond_int: The inital bond price.


PARA type: float

PARA yld_delta: The change in yield to get bond_dec & bond_inc


PARA type: float

'''

return (bond_inc - bond_dec) / (2 * bond_int * yld_delta)

#EXAMPLE
bond_inc = 952.30
bond_dec = 866.80
bond_int = 908.00
delt_yld = .005
effective_duration(bond_dec, bond_inc, bond_int, delt_yld)
[8]: 9.416299559471366
[9]: def pct_change_bond(effective_duration, yld_chg):
'''
Summary: Calculate the percentage change in bond price.

PARA effective_duration: The effective duration of the bond.


PARA type: float

PARA yld_chg: The percentage change in yield.


PARA type: float

'''

return -effective_duration * yld_chg

#EXAMPLE
bond_inc = 952.30
bond_dec = 866.80
bond_int = 908.00
delt_yld = .005
ed = effective_duration(bond_dec, bond_inc, bond_int, delt_yld)

pct_yld = .003
pct_change_bond(ed, pct_yld)

4
[9]: -0.028248898678414097
[12]: import numpy as np

def portfolio_duration(bonds, durations):


'''
Summary: Calculate the duration of a portfolio given a list of bond prices,␣
,→and a list of durations for each bonds.

PARA bonds: A list of bonds at their market value prices


PARA type: float

PARA durations: A list of durations for each bond in the bonds list
PARA type: float

'''

# calculate the weights


np_bonds = np.array(bonds)
np_weights = np_bonds / np_bonds.sum()

np_durations = np.array(durations)

return np.dot(np_weights, np_durations)

#EXAMPLE
bond = [6000, 4000]
dura = [8.5, 4.0]
portfolio_duration(bond, dura)
[12]: 6.699999999999999
[15]: def return_impact(mod_duration, spread, spread_type, convexity):
'''
Summary: Calculate the return impact for a bond, using either a large or␣
,→small spread.

PARA mod_duration: The modified duration of the bond.


PARA type: float

PARA spread: The change in spread


PARA type: float

PARA spread_type: Defines the spread as either a small spread change or␣
,→large spread change. Options are 'large' or 'small'

PARA type: string

PARA convexity: The spread convexity

5
PARA type: float

'''

if spread_type == 'small':

return -mod_duration * spread

else:

return (-mod_duration * spread) + (.5 * convexity * (spread ** 2))

#EXAMPLE
duration = 6.4
convexity = 50
spread = -.0075

# small example
spread_type = 'small'
display(return_impact(duration, spread, spread_type, convexity))

# large example
spread_type = 'large'
display(return_impact(duration, spread, spread_type, convexity))

0.048

0.04940625

[20]: def option_moneyness(option_type, strike_price, selling_price):


'''
Summary: Returns whether a put option or call option is in the money, at␣
,→the money, or out the money.

PARA option_type: Defines whether the option is a 'call' or 'put' option.


PARA type: string

PARA strike_price: The strike price of the option.


PARA type: float

PARA selling_price: The current selling price of the option


PARA type: float

'''

6
# describe the conditions for a call option
if option_type == 'call':

if (selling_price - strike_price) > 0:


return ('in-the-money', selling_price - strike_price)

elif (selling_price - strike_price) < 0:


return ('out-of-the-money', selling_price - strike_price)

elif(selling_price == strike_price):
return ('at-the-money', 0)

# describe the condtions for a put option


else:

if (strike_price - selling_price) > 0:


return ('in-the-money', strike_price - selling_price)

elif (strike_price - selling_price) < 0:


return ('out-of-the-money', strike_price - selling_price)

elif(selling_price == strike_price):
return ('at-the-money', 0)

# EXAMPLE
selling_price = 37.00
strike_price = 40.00

# call example
opt_type = 'call'
display(option_moneyness(opt_type, strike_price, selling_price))

# put example
opt_type = 'put'
display(option_moneyness(opt_type, strike_price, selling_price))

('out-of-the-money', -3.0)

('in-the-money', 3.0)

[21]: def exp_date_payoff(exercise_price, index_price, contracts):


'''
Summary: Returns the expiration date payoff for a option.

PARA exercise_price: The exercise price of the option.


PARA type: float

7
PARA index_price: The index price at expiration.
PARA type: float

PARA contracts: The contract multiplier


PARA type: int

'''

return (index_price - exercise_price) * contracts

# EXAMPLE
i_price = 962.00
e_price = 950.00
cont = 250
exp_date_payoff(e_price, i_price, cont)
[21]: 3000.0
[22]: def option_intrinsic_value(option_type, strike_price, selling_price):
'''
Summary: Returns the intrinsic value of either a put or call option.

PARA option_type: Defines whether the option is a 'call' or 'put' option.


PARA type: string

PARA strike_price: The strike price of the option.


PARA type: float

PARA selling_price: The current selling price of the option


PARA type: float

'''

# calculate the intrinsic value of a call option


if option_type == 'call':

return max([0, (selling_price - strike_price)])

# calculate the intrinsic value of a put option


else:

return max([0, (strike_price - selling_price)])

# EXAMPLE
selling_price = 55.00
strike_price = 50.00

8
# call example
opt_type = 'call'
display(option_intrinsic_value(opt_type, strike_price, selling_price))

# put example
opt_type = 'put'
display(option_intrinsic_value(opt_type, strike_price, selling_price))

5.0

[29]: def min_max_option(option_type, option_style, risk_free_rate, strike_price,␣


,→selling_price, time_frame):

'''
Summary: Returns the maximum and minimum value for a european or american␣
,→call/put.

PARA option_type: Defines whether the option is a 'call' or 'put' option.


PARA type: string

PARA option_style: Defines whether the option is an 'american' or␣


,→'european' option.

PARA type: string

PARA risk_free_rate: The current risk-free rate.


PARA type: float

PARA selling_price: The current selling price of the option.


PARA type: float

PARA strike_price: The strike price of the option.


PARA type: float

PARA time_frame: The time frame of the option, for example a 4 month option␣
,→ would be 4.
PARA type: float

'''

if option_type == 'call':

if option_style == 'american' or option_style == 'european':

max_opt_1 = 0

9
max_opt_2 = (selling_price - strike_price / (1 + risk_free_rate)␣
,→ **(time_frame / 12))

minimum_value = max([max_opt_1, max_opt_2])


maximum_value = selling_price

return (minimum_value, maximum_value)

else:

if option_style == 'american':
max_opt_1 = 0
max_opt_2 = strike_price - selling_price

minimum_value = max([max_opt_1, max_opt_2])


maximum_value = strike_price

return (minimum_value, maximum_value)

else:
max_opt_1 = 0
max_opt_2 = (strike_price / (1 + risk_free_rate) **(time_frame /␣
,→12)) - selling_price

minimum_value = max([max_opt_1, max_opt_2])


maximum_value = (strike_price / (1 + risk_free_rate) **(time_frame /
,→ 12))

return (minimum_value, maximum_value)

# EXAMPLE - PUTS
selling_price = 63.00
strike_price = 65.00
time_frame = 4
rfr = .05

# put example
opt_type = 'put'
opt_styl = 'american'
display(min_max_option(opt_type, opt_styl, rfr, strike_price, selling_price,␣
,→time_frame))

# put example
opt_type = 'put'
opt_styl = 'european'

10
display(min_max_option(opt_type, opt_styl, rfr, strike_price, selling_price,␣
,→time_frame))

# EXAMPLE - CALLS
selling_price = 68.00
strike_price = 65.00
time_frame = 3
rfr = .05

# call example
opt_type = 'call'
opt_styl = 'american'
display(min_max_option(opt_type, opt_styl, rfr, strike_price, selling_price,␣
,→time_frame))

# call example
opt_type = 'call'
opt_styl = 'european'
display(min_max_option(opt_type, opt_styl, rfr, strike_price, selling_price,␣
,→time_frame))

(2.0, 65.0)

(0.9514295424027992, 63.9514295424028)

(3.788024417500182, 68.0)

(3.788024417500182, 68.0)

[36]: def put_call_parity(calc = 'none', put = 0, call = 0, strike_price = 0,␣


,→stock_price = 0, risk_free_rate = 0, time_frame = 0):

'''
Summary: Define the put-call parity formula, which returns the price of a␣
,→call given a put and vice verse.

PARA calc: Calculate either the value of a 'call' given a put or calculate␣
,→a 'put' given a call.

PARA type: string

PARA put: The price of the put.


PARA type: float

PARA call: The price of the call


PARA type: float

11
PARA exercise_price: The current selling price of the option.
PARA type: float

PARA stock_price: The current price of the stock


PARA type: float

PARA risk_free_rate: The current risk-free rate.


PARA type: float

PARA time_frame: The time frame of the option, for example a 4 month option␣
,→would be 4.

PARA type: int


'''

if calc == 'put':

put = call - stock_price + (strike_price / ((1 + risk_free_rate) **␣


,→(time_frame / 12)))

return put

else:

call = stock_price + put - (strike_price / ((1 + risk_free_rate) **␣


,→ (time_frame / 12)))
return call

#EXAMPLE
stock = 52.00
rfr = .05
time = 3
exercise = 50.00
put = 1.50
calc_type = 'call'
put_call_parity(calc = calc_type,
put = put,
strike_price = exercise,
stock_price = stock,
risk_free_rate = rfr,
time_frame =time)
[36]: 4.106172628846302
[37]: def fixed_rate_pay(swap_fixed_rate, libor, principal, num_days):
'''
Summary: Define the put-call parity formula, which returns the price of a␣
,→call given a put and vice verse.

12
PARA calc: Calculate either the value of a 'call' given a put or calculate␣
,→ a 'put' given a call.
PARA type: string

PARA swap_fixed_rate: The swap's fixed rate.


PARA type: float

PARA libor: The libor rate


PARA type: float

PARA principal: The principal of the swap


PARA type: float

PARA num_days: The number of days until payment


PARA type: int
'''

return (swap_fixed_rate - libor) * (num_days / 360) * (principal)

#EXAMPLE
swap = .06
libor = .04
principal = 1000000
days = 90
fixed_rate_pay(swap, libor, principal, days)
[37]: 4999.999999999999

13

You might also like