def bond_convexity(price, par, T, coup, freq, dy=0.01): ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) convexity = (price_minus + price_plus - 2 * price) / (price * dy**2) return convexity
def bond_mod_duration(price, par, T, coup, freq, dy=0.01): ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) mduration = (price_minus-price_plus)/(2.*price*dy) return mduration
def bond_mod_duration(price, par, T, coup, freq, dy=0.01): ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) mduration = (price_minus - price_plus) / (2. * price * dy) return mduration
def bond_convexity(price, par, T, coup, freq, dy=0.01): ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) convexity = (price_minus+price_plus-2*price)/(price*dy**2) return convexity
def bond_mod_duration(price, par, T, coup, freq, dy=0.01): ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) # calculate the difference in price when bond moves up and down # for a given change in yield mduration = (price_minus - price_plus) / (2. * price * dy) return mduration
def bond_convexity(price, par, T, coup, freq, dy=0.01): """ Measures the change in duration due to a change in yield a convexity of 300 means a 1% change in yield will lead to a 3% (0.03) change in price resulting from convexity """ ytm = bond_ytm(price, par, T, coup, freq) ytm_minus = ytm - dy price_minus = bond_price(par, T, ytm_minus, coup, freq) ytm_plus = ytm + dy price_plus = bond_price(par, T, ytm_plus, coup, freq) convexity = (price_minus+price_plus-2*price)/(price*dy**2) return convexity
p0 = 100.0 ## the actual principal, the initial investment in dollars invest = 1e2 ## time to maturity of each note/bond you want to calculate t10 = 10 t7 = 7 texp = 10 ## daily rebalance? ## initialize arrays for all desired note/bond prices price10 = np.zeros((len(bond_yield))) price7 = np.zeros((len(bond_yield))) for i in range(len(bond_yield)): price7[i] = bond_price(r=r, y=bond_yield.y7[i] / 100, n=t7, p0=p0) price10[i] = bond_price(r=r, y=bond_yield.y10[i] / 100, n=t10, p0=p0) ## add the price to the dataframe price7_df = pd.DataFrame(price7, index=bond_yield.index) price10_df = pd.DataFrame(price10, index=bond_yield.index) bond_yield.insert(2, "price7", price7_df) bond_yield.insert(3, "price10", price10_df) ## okay, now ready to do backtesting with the following strategy: ## we start rolling from the date: #prev_year='1981' date_array = pd.date_range('1/2/1981', '1/2/2019', freq='BAS-oct') ## divide our initial investment into 3 ten year notes, starting with 1981,
# -*- coding: utf-8 -*- """ Created on Sun Aug 25 22:22:04 2019 yield_plotter.py This script plots bond price as a function of yield @author: jeffreywalker """ import numpy as np from bond_price import bond_price y = np.linspace(-0.1, 0.1, 1e3) p = np.zeros((len(y))) ## rate=0 for zero coupon bonds rate = 0 texp = 30 par = 100 for i in range(0, len(y)): p[i] = bond_price(rate, y[i], texp, par) plt.figure() plt.title('Bond Price as Function of Yield') plt.plot(y, p, '-k', label='Bond Price') plt.legend() plt.xlabel('Yield') plt.ylabel('Bond Price')
## variables r = 0.01625 r = 0.0 ## principal; but actually the par value here. p0 = 100.0 ## the actual principal, the initial investment in dollars invest = 1e2 ## time to maturity of the bond texp = 10 ## daily rebalance? price = np.zeros((len(bond_yield))) for i in range(len(bond_yield)): price[i] = bond_price(r=r, y=bond_yield.y[i] / 100, n=texp, p0=p0) ## add the price to the dataframe price_df = pd.DataFrame(price, index=bond_yield.index) bond_yield.insert(1, "price", price_df) ## use this loop to calculate the return? prev_year = '1981' date_array = pd.date_range('1/2/1981', '1/2/2019', freq='BAS-oct') purchase_date = date_array[0] return_rate = np.zeros((len(date_array))) ## the number of bonds corresponding to the investment. nbonds = np.zeros((len(date_array))) sell_price = np.zeros((len(date_array))) purchase_price = np.zeros((len(date_array))) tot_return = np.zeros((len(date_array)))
## Make an animation? ## use this loop to calculate the return? prev_year = '1981' date_array = pd.date_range('1/2/1981', '1/2/2019', freq='BAS-oct') ## the number of bonds corresponding to the investment. nbonds = np.zeros((len(date_array))) d = {'value': np.zeros((len(date_array)))} portfolio = pd.DataFrame(data=d, index=date_array) purchase_date = date_array[0] return_rate = np.zeros((len(date_array))) ## the number of bonds corresponding to the investment. nbonds = np.zeros((len(date_array))) ## the number of bonds at the begining nbonds[0] = invest / bond_price( r=r, y=bond_yield.y10[date_array[0]] / 100, n=10, p0=p0) nb = nbonds[0] sell_price = np.zeros((len(date_array))) purchase_price = np.zeros((len(date_array))) tot_return = np.zeros((len(date_array))) tot_return[0] = 0 return_factor = np.zeros((len(date_array))) index = 0 for date in date_array[1:]: ## sell the bond from last year p = nb * (bond_price( r=r, y=bond_yield.y9.values[bond_yield.index == date][0] / 100, n=9, p0=p0))
p0=100.0 ## the actual principal, the initial investment in dollars invest=1e2 ## time to maturity of each note/bond you want to calculate t10=10 t7=7 texp=10 ## Can we try a monthly rebalance? ## initialize arrays for all desired note/bond prices price10=np.zeros((len(bond_yield))) price7=np.zeros((len(bond_yield))) for i in range(len(bond_yield)): price7[i]=bond_price(r=r,y=bond_yield['7'][i]/100,n=t7,p0=p0) price10[i]=bond_price(r=r,y=bond_yield['10'][i]/100,n=t10,p0=p0) ## add the price to the dataframe price7_df=pd.DataFrame(price7,index=bond_yield.index) price10_df=pd.DataFrame(price10,index=bond_yield.index) bond_yield.insert(2, "price7", price7_df) bond_yield.insert(3, "price10", price10_df) ## okay, now ready to do backtesting with the following strategy: ## we start rolling from the date: date_array=pd.date_range('1/2/1981','1/2/2020',freq='BAS-oct') ## divide our initial investment into 3 ten year notes, starting with 1981, ## then 1982, then 1983.