def elementarySecurity(srl, qu=0.5): ''' build elementary security lattice :param srl: short rate lattice :returns: state price lattice ''' n = srl.n bt = BT.BinomialTree(n) qd = 1 - qu bt.setNode(0, 0, 1) for i in range(1, n): # j=0 case bt.setNode(i, 0, bt.getNode(i - 1, 0) / 2. / (1 + srl.getNode(i - 1, 0))) for j in range(1, i): bt.setNode( i, j, 0.5 * (bt.getNode(i - 1, j - 1) / (1 + srl.getNode(i - 1, j - 1)) + bt.getNode(i - 1, j) / (1 + srl.getNode(i - 1, j)))) # j=i case bt.setNode( i, i, 0.5 * (bt.getNode(i - 1, i - 1) / (1 + srl.getNode(i - 1, i - 1)))) return bt
def futureBond(bond, expire, srl, qu=0.5, c=0.): ''' calculate the price of forward on Bond :param bond: underline bond :param expire: forward mature time :param srl: short rate lattice :param qu: up move probability :param c: coupon rate ''' n = expire + 1 if n > srl.n or n > bond.n: print "! wrong expiration time n!" exit() coupon = bond.getNode(bond.n - 1, 1) / (1 + c) * c # calculate the coupon qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(expire, i, bond.getNode(expire, i) - coupon) # remove the coupon at expiration date for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j))) return bt.getNode(0, 0)
def swaption(swap, srl, strike, expire, qu=0.5): ''' calculate the price of Swaption :param swap: underline swap :param srl: short rate lattice :param strike: strike rate :param expire: expire time :param qu: up move probability :returns: swapion price at time 0 ''' n = expire + 1 if n > swap.n or n > srl.n: print "! wrong expiration time n!" exit() qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(n - 1, i, max(swap.getNode(n - 1, i) - strike, 0)) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j))) return bt.getNode(0, 0)
def bondlet(expire, srl, strike, qu=0.5, type='cap'): ''' calculate the price of caplet/floorlet :param expire: expire time (arrear settle) :param srl: short rate lattice :param strike: strike rate :param qu: up move probability :param type: cap/floor :returns: caplet price ''' if type == 'cap': coef = 1 else: # 'floor' coef = -1 if expire > srl.n: print "! wrong expiration time n!" exit() n = expire qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode( n - 1, i, max(coef * (srl.getNode(n - 1, i) - strike), 0) / (1 + srl.getNode(n - 1, i))) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j))) return bt.getNode(0, 0)
def setCouponBond(srl, p=100, c=0.1, qu=0.5, n=-1): ''' calculate the price structure of Coupon-Bearing Bond :param srl: short rate lattice :param p: strike price :param c: coupon rate :param qu: up move probability :param n: expiration time :returns: the coupon-bearing bond lattice ''' if n == -1: n = srl.n elif n > srl.n: print "! wrong expiration time n!" exit() else: n = n + 1 qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(n - 1, i, p + p * c) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j)) + p * c) bt.setNode(0, 0, bt.getNode(0, 0) - p * c) # correct last step - no coupon at time 0 return bt
def callBond(strike, expire, bond, srl, qu=0.5, outputfile=''): ''' calculate the Call option on the Binomial Bond :param strike: strike price :param expire: time for expiration :param zcb: underline zero coupon bond :param srl: underline short rate lattice ''' n = expire + 1 if n > srl.n or n > bond.n: print "! wrong expiration time n!" exit() qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(expire, i, max(0, bond.getNode(expire, i) - strike)) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j))) if outputfile: with open(outputfile, 'w') as f: bt.showData(f, form='{0:.2f}') return bt.getNode(0, 0)
def setZCB(srl, p=100, qu=0.5, n=-1): ''' calculate the price structure of Zero-Coupon-Bond :param srl: short rate lattice :param p: strike price :param qu: up move probability :param n: expiration time :returns: the zero coupon bond lattice ''' if n == -1: n = srl.n elif n >= srl.n: print "! wrong expiration time n!" exit() else: n = n + 1 qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(n - 1, i, p) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j))) return bt
def setShortRateLattice(r0, u, d, n): ''' set short rate lattice :param r0: interest rate at time 0 :param u: up move of interest rate :param d: down move of interest rate :param n: total period n ''' bt = BT.BinomialTree(n + 1) for i in range(n + 1): for j in range(i + 1): bt.setNode(i, j, r0 * u**(i - j) * d**j) return bt
def swap(expire, srl, fr, qu=0.5, pay='fix', start=0): ''' calculate the price of Swaps :param expire: expire time (arrear settle) :param srl: short rate lattice :param fr: fix rate :param qu: up move probability :returns: swaps lattice ''' if expire >= srl.n: print "! wrong expiration time n!" exit() if pay == 'fix': coef = 1 else: coef = -1 # pay float receive fix n = expire + 1 qd = 1 - qu bt = BT.BinomialTree(n) # set initial payment for i in range(n): bt.setNode(n - 1, i, (coef * (srl.getNode(n - 1, i) - fr) / (1 + srl.getNode(n - 1, i)))) # construct backwards for i in range(n - 2, start - 1, -1): for j in range(i + 1): bt.setNode( i, j, ((coef * (srl.getNode(i, j) - fr) + qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j)))) for i in range(start - 1, -1, -1): for j in range(i + 1): bt.setNode( i, j, ((qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j)))) return bt
def calcR(srl, n, qu=0.5): ''' calculate the cash account price for 1 dollar at time n :param srl: short rate lattice :param n: time n :returns: E[1/Bn] ''' n = n + 1 if n > srl.n: print "! wrong expiration time n!" exit() qd = 1 - qu bt = BT.BinomialTree(n) # last time step for i in range(n): bt.setNode(n - 1, i, 1.) for i in range(n - 2, -1, -1): for j in range(i + 1): bt.setNode( i, j, (qu * bt.getNode(i + 1, j + 1) + qd * bt.getNode(i + 1, j)) / (1 + srl.getNode(i, j))) return bt.getNode(0, 0)
u = 1.1 d = 0.9 r0 = 0.05 a = 0.01 b = 1.01 rec = 0.2 F = 100 qu = 0.5 qd = 1-0.5 # set up short rate lattice rlat = bino.setShortRateLattice(0.05,1.1,0.9,n) # set up default probability hlat = BT.BinomialTree(n+1) for i in range(n+1): for j in range(i+1): hlat.setNode(i,j,a*b**(j-i/2.)) # set up price z = BT.BinomialTree(n+1) i = n for j in range(i+1): z.setNode(i,j,F) for i in range(n-1,-1,-1): for j in range(i+1): nondef = (1-hlat.getNode(i,j))*(qu*z.getNode(i+1,j+1)+qd*z.getNode(i+1,j)) defau = hlat.getNode(i,j)*F*rec
price = 0 for i in range(2, 12): s = [(srl.getNode(i - 1, j) - 0.045) / (1 + srl.getNode(i - 1, j)) * d.getNode(i - 1, j) for j in range(i)] price += sum(s) print price * 1000000 # question 6 e = bi.swap(10, srl, fr=0.045, start=1) print bi.swaption(e, srl, 0, 5) * 1000000 # another way import bfc.BinomialTree as BT n = srl.n expire = 5 bt = BT.BinomialTree(n) qu = 0.5 qd = 1 - qu fr = 0.045 bt.setNode(0, 0, 1) for i in range(1, n): # j=0 case bt.setNode(i, 0, bt.getNode(i - 1, 0) / 2. / (1 + srl.getNode(i - 1, 0))) for j in range(1, i): bt.setNode( i, j, 0.5 * (bt.getNode(i - 1, j - 1) / (1 + srl.getNode(i - 1, j - 1)) + bt.getNode(i - 1, j) / (1 + srl.getNode(i - 1, j)))) # j=i case