def test_BDTExampleThree(): # Valuation of a swaption as in Leif Andersen's paper - see Table 1 on # SSRN-id155208.pdf testCases.banner("===================== ANDERSEN PAPER ==============") # This is a sanity check testBlackModelCheck() settlement_date = Date(1, 1, 2020) times = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) dates = settlement_date.add_years(times) rate = 0.06 dfs = 1.0 / (1.0 + rate / 2.0)**(2.0 * times) curve = DiscountCurve(settlement_date, dates, dfs) coupon = 0.06 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA strike_price = 100.0 face = 100.0 # Andersen paper num_time_steps = 200 testCases.header("ExerciseType", "Sigma", "NumSteps", "Texp", "Tmat", "V_Fixed", "V_pay", "V_rec") for exercise_type in [ FinExerciseTypes.EUROPEAN, FinExerciseTypes.BERMUDAN ]: for years_to_maturity in [4.0, 5.0, 10.0, 20.0]: maturity_date = settlement_date.add_years(years_to_maturity) issue_date = Date(maturity_date._d, maturity_date._m, 2000) if years_to_maturity == 4.0 or years_to_maturity == 5.0: sigma = 0.2012 elif years_to_maturity == 10.0: sigma = 0.1522 elif years_to_maturity == 20.0: sigma = 0.1035 for expiryYears in range( int(years_to_maturity / 2) - 1, int(years_to_maturity)): expiry_date = settlement_date.add_years(expiryYears) tmat = (maturity_date - settlement_date) / gDaysInYear texp = (expiry_date - settlement_date) / gDaysInYear bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon / bond._frequency for flow_date in bond._flow_dates: if flow_date > expiry_date: flow_time = (flow_date - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) price = bond.clean_price_from_discount_curve( settlement_date, curve) model = BDTTree(sigma, num_time_steps) model.build_tree(tmat, times, dfs) v = model.bermudan_swaption(texp, tmat, strike_price, face, coupon_times, coupon_flows, exercise_type) testCases.print("%s" % exercise_type, "%9.5f" % sigma, "%9.5f" % num_time_steps, "%9.5f" % expiryYears, "%9.5f" % years_to_maturity, "%9.5f" % price, "%9.2f" % (v['pay'] * 100.0), "%9.2f" % (v['rec'] * 100.0))
def test_BDTExampleThree(): # Valuation of a swaption as in Leif Andersen's paper - see Table 1 on # SSRN-id155208.pdf settlement_date = Date(1, 1, 2020) times = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) dates = settlement_date.add_years(times) rate = 0.06 dfs = 1.0 / (1.0 + rate / 2.0)**(2.0 * times) curve = DiscountCurve(settlement_date, dates, dfs) coupon = 0.06 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA strike_price = 100.0 face = 100.0 # Andersen paper num_time_steps = 200 exercise_type = FinExerciseTypes.EUROPEAN years_to_maturity = 4.0 expiryYears = 2.0 maturity_date = settlement_date.add_years(years_to_maturity) issue_date = Date(maturity_date._d, maturity_date._m, 2000) sigma = 0.2012 expiry_date = settlement_date.add_years(expiryYears) tmat = (maturity_date - settlement_date) / gDaysInYear texp = (expiry_date - settlement_date) / gDaysInYear bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon / bond._frequency for flow_date in bond._coupon_dates: if flow_date > expiry_date: flow_time = (flow_date - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) price = bond.clean_price_from_discount_curve(settlement_date, curve) model = BDTTree(sigma, num_time_steps) model.build_tree(tmat, times, dfs) v = model.bermudan_swaption(texp, tmat, strike_price, face, coupon_times, coupon_flows, exercise_type) assert round(price, 5) == 100.01832 assert round(v['pay'] * 100, 2) == 0.00 assert round(v['rec'] * 100, 2) == 8883.21 exercise_type = FinExerciseTypes.BERMUDAN years_to_maturity = 10.0 expiryYears = 5.0 maturity_date = settlement_date.add_years(years_to_maturity) issue_date = Date(maturity_date._d, maturity_date._m, 2000) sigma = 0.1522 expiry_date = settlement_date.add_years(expiryYears) tmat = (maturity_date - settlement_date) / gDaysInYear texp = (expiry_date - settlement_date) / gDaysInYear bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) coupon_times = [] coupon_flows = [] cpn = bond._coupon / bond._frequency for flow_date in bond._coupon_dates: if flow_date > expiry_date: flow_time = (flow_date - settlement_date) / gDaysInYear coupon_times.append(flow_time) coupon_flows.append(cpn) coupon_times = np.array(coupon_times) coupon_flows = np.array(coupon_flows) price = bond.clean_price_from_discount_curve(settlement_date, curve) model = BDTTree(sigma, num_time_steps) model.build_tree(tmat, times, dfs) v = model.bermudan_swaption(texp, tmat, strike_price, face, coupon_times, coupon_flows, exercise_type) assert round(price, 5) == 100.08625 assert round(v['pay'] * 100, 2) == 263.28 assert round(v['rec'] * 100, 2) == 7437.00