def test_FinDateTenors(): start_date = Date(23, 2, 2018) testCases.header("TENOR", "DATE") tenor = "5d" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "7D" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "1W" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "4W" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "1M" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "24M" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "2Y" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "10y" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "0m" testCases.print(tenor, start_date.addTenor(tenor)) tenor = "20Y" testCases.print(tenor, start_date.addTenor(tenor))
def test_DateTenors(): startDate = Date(23, 2, 2018) tenor = "5d" print(tenor, startDate.addTenor(tenor)) tenor = "7D" print(tenor, startDate.addTenor(tenor)) tenor = "1W" print(tenor, startDate.addTenor(tenor)) tenor = "4W" print(tenor, startDate.addTenor(tenor)) tenor = "1M" print(tenor, startDate.addTenor(tenor)) tenor = "24M" print(tenor, startDate.addTenor(tenor)) tenor = "2Y" print(tenor, startDate.addTenor(tenor)) tenor = "10y" print(tenor, startDate.addTenor(tenor)) tenor = "0m" print(tenor, startDate.addTenor(tenor)) tenor = "20Y" print(tenor, startDate.addTenor(tenor))
def test_BondMortgage(): principal = 130000 start_date = Date(23, 2, 2018) end_date = start_date.addTenor("10Y") mortgage = Mortgage(start_date, end_date, principal) rate = 0.035 mortgage.generateFlows(rate, BondMortgageTypes.REPAYMENT) num_flows = len(mortgage._schedule._adjusted_dates) testCases.header("PAYMENT DATE", "INTEREST", "PRINCIPAL", "OUTSTANDING", "TOTAL") for i in range(0, num_flows): testCases.print(mortgage._schedule._adjusted_dates[i], mortgage._interestFlows[i], mortgage._principalFlows[i], mortgage._principalRemaining[i], mortgage._totalFlows[i]) mortgage.generateFlows(rate, BondMortgageTypes.INTEREST_ONLY) testCases.header("PAYMENT DATE", "INTEREST", "PRINCIPAL", "OUTSTANDING", "TOTAL") for i in range(0, num_flows): testCases.print(mortgage._schedule._adjusted_dates[i], mortgage._interestFlows[i], mortgage._principalFlows[i], mortgage._principalRemaining[i], mortgage._totalFlows[i])
def test_FinScheduleAlignmentEff31(): """ EOM schedule so all unadjusted dates fall on month end.""" eomFlag = True valuation_date = Date(29, 7, 2006) effDate = valuation_date.addTenor("2D") freq_type = FrequencyTypes.SEMI_ANNUAL bus_day_adjust_type = BusDayAdjustTypes.MODIFIED_FOLLOWING date_gen_rule_type = DateGenRuleTypes.BACKWARD calendar_type = CalendarTypes.UNITED_STATES adjustTerminationDate = True matDate1 = effDate.addTenor("4Y") matDate2 = effDate.addTenor("50Y") # print(matDate1, matDate2) sched1 = Schedule(effDate, matDate1, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) sched2 = Schedule(effDate, matDate2, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) # print(sched1._adjusted_dates) # print(sched2._adjusted_dates[:len(sched1._adjusted_dates)]) compare = (sched1._adjusted_dates[-1] == sched2._adjusted_dates[ len(sched1._adjusted_dates) - 1]) assert (compare == True)
def test_FinScheduleAlignmentLeapYearEOM(): """ Effective date on leap year.""" valuation_date = Date(26, 2, 2006) effDate = valuation_date.addTenor("2D") freq_type = FrequencyTypes.SEMI_ANNUAL bus_day_adjust_type = BusDayAdjustTypes.MODIFIED_FOLLOWING date_gen_rule_type = DateGenRuleTypes.BACKWARD calendar_type = CalendarTypes.UNITED_STATES adjustTerminationDate = True matDate1 = effDate.addTenor("4Y") matDate2 = effDate.addTenor("50Y") eomFlag = True sched1 = Schedule(effDate, matDate1, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) sched2 = Schedule(effDate, matDate2, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) # print(sched1._adjusted_dates) # print(sched2._adjusted_dates[:len(sched1._adjusted_dates)]) compare = (sched1._adjusted_dates[-1] == sched2._adjusted_dates[ len(sched1._adjusted_dates) - 1]) assert (compare == eomFlag)
def test_FinScheduleAlignment(eomFlag): valuation_date = Date(29, 3, 2005) effDate = valuation_date.addTenor("2d") freq_type = FrequencyTypes.SEMI_ANNUAL bus_day_adjust_type = BusDayAdjustTypes.MODIFIED_FOLLOWING date_gen_rule_type = DateGenRuleTypes.BACKWARD calendar_type = CalendarTypes.UNITED_STATES adjustTerminationDate = False matDate1 = effDate.addTenor("4Y") matDate2 = effDate.addTenor("50Y") # print(matDate1) # print(matDate2) myCal = Calendar(calendar_type) adjustedMatDate1 = myCal.adjust(matDate1, bus_day_adjust_type) adjustedMatDate2 = myCal.adjust(matDate2, bus_day_adjust_type) # print(adjustedMatDate1) # print(adjustedMatDate2) sched1 = Schedule(effDate, adjustedMatDate1, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) # print(sched1) sched2 = Schedule(effDate, adjustedMatDate2, freq_type, calendar_type, bus_day_adjust_type, date_gen_rule_type, adjustTerminationDate, eomFlag) compare = (sched1._adjusted_dates[-1] == sched2._adjusted_dates[ len(sched1._adjusted_dates) - 1]) assert (compare == eomFlag)
def test_BKExampleTwo(): # Valuation of a European option on a coupon bearing bond # This follows example in Fig 28.11 of John Hull's book but does not # have the exact same dt so there are some differences settlement_date = Date(1, 12, 2019) issue_date = Date(1, 12, 2018) expiry_date = settlement_date.addTenor("18m") maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon / bond._frequency num_flows = len(bond._flow_dates) for i in range(1, num_flows): pcd = bond._flow_dates[i - 1] ncd = bond._flow_dates[i] if pcd < settlement_date and ncd > settlement_date: flow_time = (pcd - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) for flowDate in bond._flow_dates: if flowDate > settlement_date: flow_time = (flowDate - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) strikePrice = 105.0 face = 100.0 tmat = (maturity_date - settlement_date) / gDaysInYear texp = (expiry_date - settlement_date) / gDaysInYear times = np.linspace(0, tmat, 11) dates = settlement_date.addYears(times) dfs = np.exp(-0.05 * times) curve = DiscountCurve(settlement_date, dates, dfs) price = bond.clean_price_from_discount_curve(settlement_date, curve) testCases.header("LABEL", "VALUE") testCases.print("Fixed Income Price:", price) sigma = 0.20 a = 0.05 numTimeSteps = 26 model = FinModelRatesBK(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) exerciseType = FinExerciseTypes.AMERICAN v = model.bondOption(texp, strikePrice, face, coupon_times, coupon_flows, exerciseType) # Test convergence num_stepsList = [100, 200, 300, 500, 1000] exerciseType = FinExerciseTypes.AMERICAN testCases.header("TIMESTEPS", "TIME", "VALUE") treeVector = [] for numTimeSteps in num_stepsList: start = time.time() model = FinModelRatesBK(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) v = model.bondOption(texp, strikePrice, face, coupon_times, coupon_flows, exerciseType) end = time.time() period = end - start treeVector.append(v) testCases.print(numTimeSteps, period, v) # plt.plot(num_stepsList, treeVector) # Value in Hill converges to 0.699 with 100 time steps while I get 0.700 if 1 == 0: print("RT") printTree(model._rt, 5) print("Q") printTree(model._Q, 5)
def test_BondOption(): settlement_date = Date(1, 12, 2019) issue_date = Date(1, 12, 2018) maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) times = np.linspace(0, 10.0, 21) dfs = np.exp(-0.05 * times) dates = settlement_date.addYears(times) discount_curve = DiscountCurve(settlement_date, dates, dfs) expiry_date = settlement_date.addTenor("18m") strikePrice = 105.0 face = 100.0 ########################################################################### strikes = [80, 85, 90, 95, 100, 105, 110, 115, 120] optionType = FinOptionTypes.EUROPEAN_CALL testCases.header("LABEL", "VALUE") price = bond.clean_price_from_discount_curve(settlement_date, discount_curve) testCases.print("Fixed Income Price:", price) numTimeSteps = 100 testCases.banner("HW EUROPEAN CALL") testCases.header("STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.01 a = 0.1 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesHW(sigma, a, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print(strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_CALL price = bond.clean_price_from_discount_curve(settlement_date, discount_curve) testCases.header("LABEL", "VALUE") testCases.print("Fixed Income Price:", price) testCases.banner("HW AMERICAN CALL") testCases.header("STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.01 a = 0.1 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesHW(sigma, a) v = bondOption.value(settlement_date, discount_curve, model) testCases.print(strikePrice, v) ########################################################################### optionType = FinOptionTypes.EUROPEAN_PUT testCases.banner("HW EUROPEAN PUT") testCases.header("STRIKE", "VALUE") price = bond.clean_price_from_discount_curve(settlement_date, discount_curve) for strikePrice in strikes: sigma = 0.01 a = 0.1 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesHW(sigma, a) v = bondOption.value(settlement_date, discount_curve, model) testCases.print(strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_PUT testCases.banner("HW AMERICAN PUT") testCases.header("STRIKE", "VALUE") price = bond.clean_price_from_discount_curve(settlement_date, discount_curve) for strikePrice in strikes: sigma = 0.02 a = 0.1 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesHW(sigma, a) v = bondOption.value(settlement_date, discount_curve, model) testCases.print(strikePrice, v)
def test_BondOptionAmericanConvergenceTWO(): # Build discount curve settlement_date = Date(1, 12, 2019) discount_curve = DiscountCurveFlat(settlement_date, 0.05) # Bond details issue_date = Date(1, 12, 2015) maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) expiry_date = settlement_date.addTenor("18m") face = 100.0 spotValue = bond.clean_price_from_discount_curve(settlement_date, discount_curve) testCases.header("LABEL", "VALUE") testCases.print("BOND PRICE", spotValue) testCases.header("TIME", "N", "EUR_CALL", "AMER_CALL", "EUR_PUT", "AMER_PUT") sigma = 0.01 a = 0.1 hwModel = FinModelRatesHW(sigma, a) K = 102.0 vec_ec = [] vec_ac = [] vec_ep = [] vec_ap = [] num_stepsVector = range(100, 500, 100) for num_steps in num_stepsVector: hwModel = FinModelRatesHW(sigma, a, num_steps) start = time.time() europeanCallBondOption = BondOption(bond, expiry_date, K, face, FinOptionTypes.EUROPEAN_CALL) v_ec = europeanCallBondOption.value(settlement_date, discount_curve, hwModel) americanCallBondOption = BondOption(bond, expiry_date, K, face, FinOptionTypes.AMERICAN_CALL) v_ac = americanCallBondOption.value(settlement_date, discount_curve, hwModel) europeanPutBondOption = BondOption(bond, expiry_date, K, face, FinOptionTypes.EUROPEAN_PUT) v_ep = europeanPutBondOption.value(settlement_date, discount_curve, hwModel) americanPutBondOption = BondOption(bond, expiry_date, K, face, FinOptionTypes.AMERICAN_PUT) v_ap = americanPutBondOption.value(settlement_date, discount_curve, hwModel) end = time.time() period = end - start testCases.print(period, num_steps, v_ec, v_ac, v_ep, v_ap) vec_ec.append(v_ec) vec_ac.append(v_ac) vec_ep.append(v_ep) vec_ap.append(v_ap) if plotGraphs: plt.figure() plt.plot(num_stepsVector, vec_ac, label="American Call") plt.legend() plt.figure() plt.plot(num_stepsVector, vec_ap, label="American Put") plt.legend()
def test_HullWhiteExampleTwo(): # HULL BOOK ZERO COUPON BOND EXAMPLE 28.1 SEE TABLE 28.3 # Replication may not be exact as I am using dates rather than times zeroDays = [0, 3, 31, 62, 94, 185, 367, 731, 1096, 1461, 1826, 2194, 2558, 2922, 3287, 3653] zeroRates = [5.0, 5.01772, 4.98282, 4.97234, 4.96157, 4.99058, 5.09389, 5.79733, 6.30595, 6.73464, 6.94816, 7.08807, 7.27527, 7.30852, 7.39790, 7.49015] times = np.array(zeroDays) / 365.0 zeros = np.array(zeroRates) / 100.0 dfs = np.exp(-zeros*times) start_date = Date(1, 12, 2019) sigma = 0.01 a = 0.1 strike = 63.0 face = 100.0 expiry_date = start_date.addTenor("3Y") maturity_date = start_date.addTenor("9Y") texp = (expiry_date - start_date)/gDaysInYear tmat = (maturity_date - start_date)/gDaysInYear numTimeSteps = None model = FinModelRatesHW(sigma, a, numTimeSteps) vAnal = model.optionOnZCB(texp, tmat, strike, face, times, dfs) # Test convergence num_stepsList = range(100, 500, 100) analVector = [] treeVector = [] testCases.banner("Comparing option on zero coupon bond analytical vs Tree") testCases.header("NUMTIMESTEP", "TIME", "VTREE_CALL", "VTREE_PUT", "VANAL CALL", "VANAL_PUT", "CALLDIFF", "PUTDIFF") for numTimeSteps in num_stepsList: start = time.time() model = FinModelRatesHW(sigma, a, numTimeSteps) model.buildTree(texp, times, dfs) vTree1 = model.optionOnZeroCouponBond_Tree(texp, tmat, strike, face) model = FinModelRatesHW(sigma, a, numTimeSteps+1) model.buildTree(texp, times, dfs) vTree2 = model.optionOnZeroCouponBond_Tree(texp, tmat, strike, face) end = time.time() period = end-start treeVector.append(vTree1['put']) analVector.append(vAnal['put']) vTreeCall = (vTree1['call'] + vTree2['call'] ) / 2.0 vTreePut = (vTree1['put'] + vTree2['put'] ) / 2.0 diffC = vTreeCall - vAnal['call'] diffP = vTreePut - vAnal['put'] testCases.print(numTimeSteps, period, vTreeCall, vAnal['call'], vTreePut, vAnal['put'], diffC, diffP)
def test_HullWhiteCallableBond(): # Valuation of a European option on a coupon bearing bond settlement_date = Date(1, 12, 2019) issue_date = Date(1, 12, 2018) maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon/bond._frequency for flowDate in bond._flow_dates[1:]: if flowDate > settlement_date: flow_time = (flowDate - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) ########################################################################### # Set up the call and put times and prices ########################################################################### call_dates = [] call_prices = [] callPx = 120.0 call_dates.append(settlement_date.addTenor("2Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("3Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("4Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("5Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("6Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("7Y")); call_prices.append(callPx) call_dates.append(settlement_date.addTenor("8Y")); call_prices.append(callPx) call_times = [] for dt in call_dates: t = (dt - settlement_date) / gDaysInYear call_times.append(t) put_dates = [] put_prices = [] putPx = 98.0 put_dates.append(settlement_date.addTenor("2Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("3Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("4Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("5Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("6Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("7Y")); put_prices.append(putPx) put_dates.append(settlement_date.addTenor("8Y")); put_prices.append(putPx) put_times = [] for dt in put_dates: t = (dt - settlement_date) / gDaysInYear put_times.append(t) ########################################################################### tmat = (maturity_date - settlement_date) / gDaysInYear curve = DiscountCurveFlat(settlement_date, 0.05, FrequencyTypes.CONTINUOUS) dfs = [] times = [] for dt in bond._flow_dates: if dt > settlement_date: t = (dt - settlement_date) / gDaysInYear df = curve.df(dt) times.append(t) dfs.append(df) dfs = np.array(dfs) times = np.array(times) ########################################################################### v1 = bond.clean_price_from_discount_curve(settlement_date, curve) sigma = 0.02 # basis point volatility a = 0.01 # Test convergence num_stepsList = [100, 200, 500, 1000] tmat = (maturity_date - settlement_date)/gDaysInYear testCases.header("NUMSTEPS", "TIME", "BOND_ONLY", "CALLABLE_BOND") for numTimeSteps in num_stepsList: start = time.time() model = FinModelRatesHW(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) v2 = model.callablePuttableBond_Tree(coupon_times, coupon_flows, call_times, call_prices, put_times, put_prices, 100.0) end = time.time() period = end-start testCases.print(numTimeSteps, period, v1, v2)
def test_HullWhiteBondOption(): # Valuation of a European option on a coupon bearing bond settlement_date = Date(1, 12, 2019) issue_date = Date(1, 12, 2018) expiry_date = settlement_date.addTenor("18m") maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon/bond._frequency num_flows = len(bond._flow_dates) for i in range(1, num_flows): pcd = bond._flow_dates[i-1] ncd = bond._flow_dates[i] if ncd > settlement_date: if len(coupon_times) == 0: flow_time = (pcd - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) flow_time = (ncd - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) strikePrice = 100.0 face = 100.0 y = 0.05 times = np.linspace(0, 10, 21) dfs = np.power(1+y/2, -times*2) sigma = 0.0000001 a = 0.1 model = FinModelRatesHW(sigma, a, None) # Test convergence num_stepsList = range(50, 500, 50) texp = (expiry_date - settlement_date)/gDaysInYear vJam = model.europeanBondOptionJamshidian(texp, strikePrice, face, coupon_times, coupon_flows, times, dfs) testCases.banner("Pricing bond option on tree that goes to bond maturity and one using european bond option tree that goes to expiry.") testCases.header("NUMSTEPS", "TIME", "EXPIRY_ONLY", "EXPIRY_TREE", "JAMSHIDIAN") for numTimeSteps in num_stepsList: start = time.time() model = FinModelRatesHW(sigma, a, numTimeSteps, FinHWEuropeanCalcType.EXPIRY_ONLY) model.buildTree(texp, times, dfs) exerciseType = FinExerciseTypes.EUROPEAN v1 = model.bondOption(texp, strikePrice, face, coupon_times, coupon_flows, exerciseType) model = FinModelRatesHW(sigma, a, numTimeSteps, FinHWEuropeanCalcType.EXPIRY_TREE) model.buildTree(texp, times, dfs) v2 = model.bondOption(texp, strikePrice, face, coupon_times, coupon_flows, exerciseType) end = time.time() period = end-start testCases.print(numTimeSteps, period, v1, v2, vJam) # plt.plot(num_stepsList, treeVector) if 1 == 0: print("RT") printTree(model._rt, 5) print("BOND") printTree(model._bondValues, 5) print("OPTION") printTree(model._optionValues, 5)
def test_BondOptionZEROVOLConvergence(): # Build discount curve settlement_date = Date(1, 12, 2019) # CHANGED rate = 0.05 discount_curve = DiscountCurveFlat(settlement_date, rate, FrequencyTypes.ANNUAL) # Bond details issue_date = Date(1, 9, 2015) maturity_date = Date(1, 9, 2025) coupon = 0.06 freq_type = FrequencyTypes.ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) # Option Details expiry_date = settlement_date.addTenor("18m") # FinDate(1, 12, 2021) # print("EXPIRY:", expiry_date) face = 100.0 dfExpiry = discount_curve.df(expiry_date) spotCleanValue = bond.clean_price_from_discount_curve(settlement_date, discount_curve) fwdCleanValue = bond.clean_price_from_discount_curve(expiry_date, discount_curve) # print("BOND SpotCleanBondPx", spotCleanValue) # print("BOND FwdCleanBondPx", fwdCleanValue) # print("BOND Accrued:", bond._accruedInterest) spotCleanValue = bond.clean_price_from_discount_curve(settlement_date, discount_curve) testCases.header("STRIKE", "STEPS", "CALL_INT", "CALL_INT_PV", "CALL_EUR", "CALL_AMER", "PUT_INT", "PUT_INT_PV", "PUT_EUR", "PUT_AMER") numTimeSteps = range(100, 1000, 200) strikePrices = [90, 100, 110, 120] for strikePrice in strikePrices: callIntrinsic = max(spotCleanValue - strikePrice, 0) putIntrinsic = max(strikePrice - spotCleanValue, 0) callIntrinsicPV = max(fwdCleanValue - strikePrice, 0) * dfExpiry putIntrinsicPV = max(strikePrice - fwdCleanValue, 0) * dfExpiry for num_steps in numTimeSteps: sigma = 0.0000001 model = FinModelRatesBDT(sigma, num_steps) optionType = FinOptionTypes.EUROPEAN_CALL bondOption1 = BondOption(bond, expiry_date, strikePrice, face, optionType) v1 = bondOption1.value(settlement_date, discount_curve, model) optionType = FinOptionTypes.AMERICAN_CALL bondOption2 = BondOption(bond, expiry_date, strikePrice, face, optionType) v2 = bondOption2.value(settlement_date, discount_curve, model) optionType = FinOptionTypes.EUROPEAN_PUT bondOption3 = BondOption(bond, expiry_date, strikePrice, face, optionType) v3 = bondOption3.value(settlement_date, discount_curve, model) optionType = FinOptionTypes.AMERICAN_PUT bondOption4 = BondOption(bond, expiry_date, strikePrice, face, optionType) v4 = bondOption4.value(settlement_date, discount_curve, model) testCases.print(strikePrice, num_steps, callIntrinsic, callIntrinsicPV, v1, v2, putIntrinsic, putIntrinsicPV, v3, v4)
def test_BondOption(): settlement_date = Date(1, 12, 2019) issue_date = Date(1, 12, 2018) maturity_date = settlement_date.addTenor("10Y") coupon = 0.05 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) tmat = (maturity_date - settlement_date) / gDaysInYear times = np.linspace(0, tmat, 20) dates = settlement_date.addYears(times) dfs = np.exp(-0.05*times) discount_curve = DiscountCurve(settlement_date, dates, dfs) expiry_date = settlement_date.addTenor("18m") strikePrice = 105.0 face = 100.0 ########################################################################### strikes = [80, 90, 100, 110, 120] optionType = FinOptionTypes.EUROPEAN_CALL testCases.header("LABEL", "VALUE") price = bond.full_price_from_discount_curve(settlement_date, discount_curve) testCases.print("Fixed Income Price:", price) numTimeSteps = 100 testCases.header("OPTION TYPE AND MODEL", "STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("EUROPEAN CALL - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("EUROPEAN CALL - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_CALL price = bond.full_price_from_discount_curve(settlement_date, discount_curve) testCases.header("LABEL", "VALUE") testCases.print("Fixed Income Price:", price) testCases.header("OPTION TYPE AND MODEL", "STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("AMERICAN CALL - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("AMERICAN CALL - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.EUROPEAN_PUT price = bond.full_price_from_discount_curve(settlement_date, discount_curve) for strikePrice in strikes: sigma = 0.01 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("EUROPEAN PUT - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("EUROPEAN PUT - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_PUT price = bond.full_price_from_discount_curve(settlement_date, discount_curve) for strikePrice in strikes: sigma = 0.02 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("AMERICAN PUT - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 bondOption = BondOption(bond, expiry_date, strikePrice, face, optionType) model = FinModelRatesBDT(sigma, numTimeSteps) v = bondOption.value(settlement_date, discount_curve, model) testCases.print("AMERICAN PUT - BK", strikePrice, v)
def testFinIborCashSettledSwaption(): testCases.header("LABEL", "VALUE") valuation_date = Date(1, 1, 2020) settlement_date = Date(1, 1, 2020) depoDCCType = DayCountTypes.THIRTY_E_360_ISDA depos = [] depo = FinIborDeposit(settlement_date, "1W", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "1M", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "3M", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "6M", 0.0023, depoDCCType) depos.append(depo) # No convexity correction provided so I omit interest rate futures settlement_date = Date(2, 1, 2020) swaps = [] accType = DayCountTypes.ACT_365F fixedFreqType = FrequencyTypes.SEMI_ANNUAL fixed_legType = FinSwapTypes.PAY swap = FinIborSwap(settlement_date, "3Y", fixed_legType, 0.00790, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "4Y", fixed_legType, 0.01200, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "5Y", fixed_legType, 0.01570, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "6Y", fixed_legType, 0.01865, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "7Y", fixed_legType, 0.02160, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "8Y", fixed_legType, 0.02350, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "9Y", fixed_legType, 0.02540, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "10Y", fixed_legType, 0.0273, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "15Y", fixed_legType, 0.0297, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "20Y", fixed_legType, 0.0316, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "25Y", fixed_legType, 0.0335, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "30Y", fixed_legType, 0.0354, fixedFreqType, accType) swaps.append(swap) libor_curve = IborSingleCurve(valuation_date, depos, [], swaps, FinInterpTypes.LINEAR_ZERO_RATES) exerciseDate = settlement_date.addTenor("5Y") swapMaturityDate = exerciseDate.addTenor("5Y") swapFixedCoupon = 0.040852 swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL swapFixedDayCountType = DayCountTypes.THIRTY_E_360_ISDA swapFloatFrequencyType = FrequencyTypes.QUARTERLY swapFloatDayCountType = DayCountTypes.ACT_360 swapNotional = 1000000 fixed_legType = FinSwapTypes.PAY swaption = FinIborSwaption(settlement_date, exerciseDate, swapMaturityDate, fixed_legType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType, swapNotional, swapFloatFrequencyType, swapFloatDayCountType) model = FinModelBlack(0.1533) v = swaption.value(settlement_date, libor_curve, model) testCases.print("Swaption No-Arb Value:", v) fwdSwapRate1 = libor_curve.swap_rate(exerciseDate, swapMaturityDate, swapFixedFrequencyType, swapFixedDayCountType) testCases.print("Curve Fwd Swap Rate:", fwdSwapRate1) fwdSwap = FinIborSwap(exerciseDate, swapMaturityDate, fixed_legType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fwdSwapRate2 = fwdSwap.swap_rate(settlement_date, libor_curve) testCases.print("Fwd Swap Swap Rate:", fwdSwapRate2) model = FinModelBlack(0.1533) v = swaption.cashSettledValue(valuation_date, libor_curve, fwdSwapRate2, model) testCases.print("Swaption Cash Settled Value:", v)
def test_FinIborSwaptionQLExample(): valuation_date = Date(4, 3, 2014) settlement_date = Date(4, 3, 2014) depoDCCType = DayCountTypes.THIRTY_E_360_ISDA depos = [] depo = FinIborDeposit(settlement_date, "1W", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "1M", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "3M", 0.0023, depoDCCType) depos.append(depo) depo = FinIborDeposit(settlement_date, "6M", 0.0023, depoDCCType) depos.append(depo) # No convexity correction provided so I omit interest rate futures swaps = [] accType = DayCountTypes.ACT_365F fixedFreqType = FrequencyTypes.SEMI_ANNUAL fixed_legType = FinSwapTypes.PAY swap = FinIborSwap(settlement_date, "3Y", fixed_legType, 0.00790, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "4Y", fixed_legType, 0.01200, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "5Y", fixed_legType, 0.01570, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "6Y", fixed_legType, 0.01865, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "7Y", fixed_legType, 0.02160, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "8Y", fixed_legType, 0.02350, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "9Y", fixed_legType, 0.02540, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "10Y", fixed_legType, 0.0273, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "15Y", fixed_legType, 0.0297, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "20Y", fixed_legType, 0.0316, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "25Y", fixed_legType, 0.0335, fixedFreqType, accType) swaps.append(swap) swap = FinIborSwap(settlement_date, "30Y", fixed_legType, 0.0354, fixedFreqType, accType) swaps.append(swap) libor_curve = IborSingleCurve(valuation_date, depos, [], swaps, FinInterpTypes.LINEAR_ZERO_RATES) exerciseDate = settlement_date.addTenor("5Y") swapMaturityDate = exerciseDate.addTenor("5Y") swapFixedCoupon = 0.040852 swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL swapFixedDayCountType = DayCountTypes.THIRTY_E_360_ISDA swapFloatFrequencyType = FrequencyTypes.QUARTERLY swapFloatDayCountType = DayCountTypes.ACT_360 swapNotional = 1000000 swaptionType = FinSwapTypes.PAY swaption = FinIborSwaption(settlement_date, exerciseDate, swapMaturityDate, swaptionType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType, swapNotional, swapFloatFrequencyType, swapFloatDayCountType) testCases.header("MODEL", "VALUE") model = FinModelBlack(0.1533) v = swaption.value(settlement_date, libor_curve, model) testCases.print(model.__class__, v) model = FinModelBlackShifted(0.1533, -0.008) v = swaption.value(settlement_date, libor_curve, model) testCases.print(model.__class__, v) model = FinModelSABR(0.132, 0.5, 0.5, 0.5) v = swaption.value(settlement_date, libor_curve, model) testCases.print(model.__class__, v) model = FinModelSABRShifted(0.352, 0.5, 0.15, 0.15, -0.005) v = swaption.value(settlement_date, libor_curve, model) testCases.print(model.__class__, v) model = FinModelRatesHW(0.010000000, 0.00000000001) v = swaption.value(settlement_date, libor_curve, model) testCases.print(model.__class__, v)