def test_bdt_bermudan_exercise():
    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    sigma = 0.00001
    model = BDTTree(sigma, num_time_steps)

    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    assert round(valuePay, 4) == 6313.5155

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    assert valueRec == 0.0

    sigma = 0.20
    model = BDTTree(sigma, num_time_steps)

    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    assert round(valuePay, 4) == 19446.0956

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    assert round(valueRec, 4) == 13256.8421
예제 #2
0
def test_BDTExampleOne():
    # HULL BOOK NOTES
    # http://www-2.rotman.utoronto.ca/~hull/technicalnotes/TechnicalNote23.pdf

    valuation_date = Date(1, 1, 2020)
    years = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
    zero_dates = valuation_date.add_years(years)
    zero_rates = [0.00, 0.10, 0.11, 0.12, 0.125, 0.13]

    testCases.header("DATES")
    testCases.print(zero_dates)

    testCases.header("RATES")
    testCases.print(zero_rates)

    curve = DiscountCurveZeros(valuation_date, zero_dates, zero_rates,
                               FrequencyTypes.ANNUAL)

    yieldVol = 0.16

    num_time_steps = 5
    tmat = years[-1]
    dfs = curve.df(zero_dates)

    testCases.print("DFS")
    testCases.print(dfs)

    years = np.array(years)
    dfs = np.array(dfs)

    model = BDTTree(yieldVol, num_time_steps)
    model.build_tree(tmat, years, dfs)
def test_BondOptionAmericanConvergenceONE():

    # Build discount curve
    settlement_date = Date(1, 12, 2019)
    discount_curve = DiscountCurveFlat(settlement_date, 0.05)

    # Bond details
    issue_date = Date(1, 9, 2010)
    maturity_date = Date(1, 9, 2025)
    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)

    # Option Details
    expiry_date = Date(1, 12, 2020)
    strike_price = 100.0
    face = 100.0

    testCases.header("TIME", "N", "PUT_AMER", "PUT_EUR", "CALL_AME",
                     "CALL_EUR")

    timeSteps = range(30, 100, 1)

    for num_time_steps in timeSteps:

        sigma = 0.20

        start = time.time()

        option_type = FinOptionTypes.AMERICAN_PUT
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model = BDTTree(sigma, num_time_steps)
        v1put = bond_option1.value(settlement_date, discount_curve, model)

        option_type = FinOptionTypes.EUROPEAN_PUT
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model = BDTTree(sigma, num_time_steps)
        v2put = bond_option2.value(settlement_date, discount_curve, model)

        option_type = FinOptionTypes.AMERICAN_CALL
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model = BDTTree(sigma, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model)

        option_type = FinOptionTypes.EUROPEAN_CALL
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model = BDTTree(sigma, num_time_steps)
        v2call = bond_option2.value(settlement_date, discount_curve, model)

        end = time.time()

        period = end - start

        testCases.print(period, num_time_steps, v1put, v2put, v1call, v2call)
예제 #4
0
def test_american_put_bdt():
    option_type = OptionTypes.AMERICAN_PUT
    strike_price = 100

    bond_option = BondOption(bond, expiry_date, strike_price, face,
                             option_type)

    sigma = 0.02
    model = BDTTree(sigma, num_time_steps)

    v = bond_option.value(settlement_date, discount_curve, model)

    assert round(v, 4) == 0.6141
예제 #5
0
def test_european_call_bdt():
    option_type = OptionTypes.EUROPEAN_CALL
    strike_price = 100

    bond_option = BondOption(bond, expiry_date, strike_price, face,
                             option_type)

    sigma = 0.20
    model = BDTTree(sigma, num_time_steps)

    v = bond_option.value(settlement_date, discount_curve, model)

    assert round(v, 4) == 2.9156
예제 #6
0
def testIborSwaptionMatlabExamples():

    # We value a European swaption using Black's model and try to replicate a
    # ML example at https://fr.mathworks.com/help/fininst/swaptionbyblk.html

    testCases.header("=======================================")
    testCases.header("MATLAB EXAMPLE WITH FLAT TERM STRUCTURE")
    testCases.header("=======================================")

    valuation_date = Date(1, 1, 2010)
    libor_curve = DiscountCurveFlat(valuation_date, 0.06,
                                    FrequencyTypes.CONTINUOUS,
                                    DayCountTypes.THIRTY_E_360)

    settlement_date = Date(1, 1, 2011)
    exercise_date = Date(1, 1, 2016)
    maturity_date = Date(1, 1, 2019)

    fixed_coupon = 0.062
    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    # Pricing a PAY
    swaptionType = SwapTypes.PAY
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    model = Black(0.20)
    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 2.071

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    ###############################################################################

    testCases.header("===================================")
    testCases.header("MATLAB EXAMPLE WITH TERM STRUCTURE")
    testCases.header("===================================")

    valuation_date = Date(1, 1, 2010)

    dates = [
        Date(1, 1, 2011),
        Date(1, 1, 2012),
        Date(1, 1, 2013),
        Date(1, 1, 2014),
        Date(1, 1, 2015)
    ]

    zero_rates = [0.03, 0.034, 0.037, 0.039, 0.040]

    contFreq = FrequencyTypes.CONTINUOUS
    interp_type = InterpTypes.LINEAR_ZERO_RATES
    day_count_type = DayCountTypes.THIRTY_E_360

    libor_curve = DiscountCurveZeros(valuation_date, dates, zero_rates,
                                     contFreq, day_count_type, interp_type)

    settlement_date = Date(1, 1, 2011)
    exercise_date = Date(1, 1, 2012)
    maturity_date = Date(1, 1, 2017)
    fixed_coupon = 0.03

    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360
    float_frequency_type = FrequencyTypes.SEMI_ANNUAL
    float_day_count_type = DayCountTypes.THIRTY_E_360
    notional = 1000.0

    # Pricing a put
    swaptionType = SwapTypes.RECEIVE
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional,
                            float_frequency_type, float_day_count_type)

    model = Black(0.21)
    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 0.5771

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    ###############################################################################

    testCases.header("===================================")
    testCases.header("MATLAB EXAMPLE WITH SHIFTED BLACK")
    testCases.header("===================================")

    valuation_date = Date(1, 1, 2016)

    dates = [
        Date(1, 1, 2017),
        Date(1, 1, 2018),
        Date(1, 1, 2019),
        Date(1, 1, 2020),
        Date(1, 1, 2021)
    ]

    zero_rates = np.array([-0.02, 0.024, 0.047, 0.090, 0.12]) / 100.0

    contFreq = FrequencyTypes.ANNUAL
    interp_type = InterpTypes.LINEAR_ZERO_RATES
    day_count_type = DayCountTypes.THIRTY_E_360

    libor_curve = DiscountCurveZeros(valuation_date, dates, zero_rates,
                                     contFreq, day_count_type, interp_type)

    settlement_date = Date(1, 1, 2016)
    exercise_date = Date(1, 1, 2017)
    maturity_date = Date(1, 1, 2020)
    fixed_coupon = -0.003

    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    float_frequency_type = FrequencyTypes.SEMI_ANNUAL
    float_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 1000.0

    # Pricing a PAY
    swaptionType = SwapTypes.PAY
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional,
                            float_frequency_type, float_day_count_type)

    model = BlackShifted(0.31, 0.008)
    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 12.8301

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    ###############################################################################

    testCases.header("===================================")
    testCases.header("MATLAB EXAMPLE WITH HULL WHITE")
    testCases.header("===================================")

    # https://fr.mathworks.com/help/fininst/swaptionbyhw.html

    valuation_date = Date(1, 1, 2007)

    dates = [
        Date(1, 1, 2007),
        Date(1, 7, 2007),
        Date(1, 1, 2008),
        Date(1, 7, 2008),
        Date(1, 1, 2009),
        Date(1, 7, 2009),
        Date(1, 1, 2010),
        Date(1, 7, 2010),
        Date(1, 1, 2011),
        Date(1, 7, 2011),
        Date(1, 1, 2012)
    ]

    zero_rates = np.array([0.075] * 11)
    interp_type = InterpTypes.FLAT_FWD_RATES
    day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    contFreq = FrequencyTypes.SEMI_ANNUAL

    libor_curve = DiscountCurveZeros(valuation_date, dates, zero_rates,
                                     contFreq, day_count_type, interp_type)

    settlement_date = valuation_date
    exercise_date = Date(1, 1, 2010)
    maturity_date = Date(1, 1, 2012)
    fixed_coupon = 0.04

    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    swaptionType = SwapTypes.RECEIVE
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    model = HWTree(0.05, 0.01)
    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 2.9201

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    ###############################################################################

    testCases.header("====================================")
    testCases.header("MATLAB EXAMPLE WITH BLACK KARASINSKI")
    testCases.header("====================================")

    # https://fr.mathworks.com/help/fininst/swaptionbybk.html
    valuation_date = Date(1, 1, 2007)

    dates = [
        Date(1, 1, 2007),
        Date(1, 7, 2007),
        Date(1, 1, 2008),
        Date(1, 7, 2008),
        Date(1, 1, 2009),
        Date(1, 7, 2009),
        Date(1, 1, 2010),
        Date(1, 7, 2010),
        Date(1, 1, 2011),
        Date(1, 7, 2011),
        Date(1, 1, 2012)
    ]

    zero_rates = np.array([0.07] * 11)

    interp_type = InterpTypes.FLAT_FWD_RATES
    day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    contFreq = FrequencyTypes.SEMI_ANNUAL

    libor_curve = DiscountCurveZeros(valuation_date, dates, zero_rates,
                                     contFreq, day_count_type, interp_type)

    settlement_date = valuation_date
    exercise_date = Date(1, 1, 2011)
    maturity_date = Date(1, 1, 2012)

    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    model = BKTree(0.1, 0.05, 200)

    fixed_coupon = 0.07
    swaptionType = SwapTypes.PAY
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 0.3634

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    fixed_coupon = 0.0725
    swaptionType = SwapTypes.RECEIVE
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 0.4798

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)

    ###############################################################################

    testCases.header("====================================")
    testCases.header("MATLAB EXAMPLE WITH BLACK-DERMAN-TOY")
    testCases.header("====================================")

    # https://fr.mathworks.com/help/fininst/swaptionbybdt.html

    valuation_date = Date(1, 1, 2007)

    dates = [
        Date(1, 1, 2007),
        Date(1, 7, 2007),
        Date(1, 1, 2008),
        Date(1, 7, 2008),
        Date(1, 1, 2009),
        Date(1, 7, 2009),
        Date(1, 1, 2010),
        Date(1, 7, 2010),
        Date(1, 1, 2011),
        Date(1, 7, 2011),
        Date(1, 1, 2012)
    ]

    zero_rates = np.array([0.06] * 11)

    interp_type = InterpTypes.FLAT_FWD_RATES
    day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    contFreq = FrequencyTypes.ANNUAL

    libor_curve = DiscountCurveZeros(valuation_date, dates, zero_rates,
                                     contFreq, day_count_type, interp_type)

    settlement_date = valuation_date
    exercise_date = Date(1, 1, 2012)
    maturity_date = Date(1, 1, 2015)

    fixed_frequency_type = FrequencyTypes.ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    fixed_coupon = 0.062
    swaptionType = SwapTypes.PAY
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    model = BDTTree(0.20, 200)
    v_finpy = swaption.value(valuation_date, libor_curve, model)
    v_matlab = 2.0592

    testCases.header("LABEL", "VALUE")
    testCases.print("FP Price:", v_finpy)
    testCases.print("MATLAB Prix:", v_matlab)
    testCases.print("DIFF:", v_finpy - v_matlab)
예제 #7
0
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))
예제 #8
0
def test_BDTExampleTwo():
    # Valuation of a European option on a coupon bearing bond
    # This follows example in Fig 28.11 of John Hull's book (6th Edition)
    # but does not have the exact same dt so there are some differences

    testCases.banner("===================== FIG 28.11 HULL BOOK =============")

    settlement_date = Date(1, 12, 2019)
    issue_date = Date(1, 12, 2015)
    expiry_date = settlement_date.add_tenor("18m")
    maturity_date = settlement_date.add_tenor("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 flow_date in bond._flow_dates:
        if flow_date > settlement_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)

    strike_price = 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.add_years(times)
    dfs = np.exp(-0.05 * times)

    testCases.header("LABEL", "VALUES")
    testCases.print("TIMES:", times)

    curve = DiscountCurve(settlement_date, dates, dfs)

    price = bond.clean_price_from_discount_curve(settlement_date, curve)
    testCases.print("Fixed Income Price:", price)

    sigma = 0.20

    # Test convergence
    num_steps_list = [5]  # [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
    exercise_type = FinExerciseTypes.AMERICAN

    testCases.header("Values")
    treeVector = []
    for num_time_steps in num_steps_list:
        model = BDTTree(sigma, num_time_steps)
        model.build_tree(tmat, times, dfs)
        v = model.bond_option(texp, strike_price, face, coupon_times,
                              coupon_flows, exercise_type)

        testCases.print(v)
        treeVector.append(v['call'])

    if PLOT_GRAPHS:
        plt.plot(num_steps_list, treeVector)

    # The value in Hull converges to 0.699 with 100 time steps while I get 0.70

    if 1 == 0:
        print("RT")
        print_tree(model._rt, 5)
        print("Q")
        print_tree(model._Q, 5)
예제 #9
0
def test_IborBermudanSwaptionBKModel():
    """ Replicate examples in paper by Leif Andersen which can be found at
    file:///C:/Users/Dominic/Downloads/SSRN-id155208.pdf """

    valuation_date = Date(1, 1, 2011)
    settlement_date = valuation_date
    exercise_date = settlement_date.add_years(1)
    swapMaturityDate = settlement_date.add_years(4)

    swapFixedCoupon = 0.060
    swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = DayCountTypes.ACT_365F

    libor_curve = DiscountCurveFlat(valuation_date, 0.0625,
                                    FrequencyTypes.SEMI_ANNUAL,
                                    DayCountTypes.ACT_365F)

    fwdPAYSwap = IborSwap(exercise_date, swapMaturityDate, SwapTypes.PAY,
                          swapFixedCoupon, swapFixedFrequencyType,
                          swapFixedDayCountType)

    fwdSwapValue = fwdPAYSwap.value(settlement_date, libor_curve, libor_curve)

    testCases.header("LABEL", "VALUE")
    testCases.print("FWD SWAP VALUE", fwdSwapValue)

    # fwdPAYSwap.print_fixed_leg_pv()

    # Now we create the European swaptions
    fixed_leg_type = SwapTypes.PAY
    europeanSwaptionPay = IborSwaption(settlement_date, exercise_date,
                                       swapMaturityDate, fixed_leg_type,
                                       swapFixedCoupon, swapFixedFrequencyType,
                                       swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    europeanSwaptionRec = IborSwaption(settlement_date, exercise_date,
                                       swapMaturityDate, fixed_leg_type,
                                       swapFixedCoupon, swapFixedFrequencyType,
                                       swapFixedDayCountType)

    ###########################################################################
    ###########################################################################
    ###########################################################################
    # BLACK'S MODEL
    ###########################################################################
    ###########################################################################
    ###########################################################################

    testCases.banner("======= ZERO VOLATILITY ========")
    model = Black(0.0000001)
    testCases.print("Black Model", model._volatility)

    valuePay = europeanSwaptionPay.value(settlement_date, libor_curve, model)
    testCases.print("EUROPEAN BLACK PAY VALUE ZERO VOL:", valuePay)

    valueRec = europeanSwaptionRec.value(settlement_date, libor_curve, model)
    testCases.print("EUROPEAN BLACK REC VALUE ZERO VOL:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner("======= 20%% BLACK VOLATILITY ========")

    model = Black(0.20)
    testCases.print("Black Model", model._volatility)

    valuePay = europeanSwaptionPay.value(settlement_date, libor_curve, model)
    testCases.print("EUROPEAN BLACK PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(settlement_date, libor_curve, model)
    testCases.print("EUROPEAN BLACK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    ###########################################################################
    ###########################################################################
    # BK MODEL
    ###########################################################################
    ###########################################################################
    ###########################################################################

    testCases.banner("=======================================================")
    testCases.banner("=======================================================")
    testCases.banner("==================== BK MODEL =========================")
    testCases.banner("=======================================================")
    testCases.banner("=======================================================")

    testCases.banner("======= 0% VOLATILITY EUROPEAN SWAPTION BK MODEL ======")

    # Used BK with constant short-rate volatility
    sigma = 0.000000001
    a = 0.01
    num_time_steps = 100
    model = BKTree(sigma, a, num_time_steps)

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BK PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 20% VOLATILITY EUROPEAN SWAPTION BK MODEL ========")

    # Used BK with constant short-rate volatility
    sigma = 0.20
    a = 0.01
    model = BKTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL SWAPTION CLASS EUROPEAN EXERCISE")

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BK PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################

    # Now we create the Bermudan swaptions but only allow European exercise
    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.EUROPEAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    exercise_type = FinExerciseTypes.EUROPEAN

    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BK MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.000001
    a = 0.01
    model = BKTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 20% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BK MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.2
    a = 0.01
    model = BKTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    # Now we create the Bermudan swaptions but allow Bermudan exercise
    ###########################################################################

    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BK MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.000001
    a = 0.01
    model = BKTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 20% VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BK MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.20
    a = 0.01
    model = BKTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BK REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    ###########################################################################
    ###########################################################################
    # BDT MODEL
    ###########################################################################
    ###########################################################################
    ###########################################################################

    testCases.banner("=======================================================")
    testCases.banner("=======================================================")
    testCases.banner("======================= BDT MODEL =====================")
    testCases.banner("=======================================================")
    testCases.banner("=======================================================")

    testCases.banner("====== 0% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======")

    # Used BK with constant short-rate volatility
    sigma = 0.00001
    num_time_steps = 200
    model = BDTTree(sigma, num_time_steps)

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BDT PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner("===== 20% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======")

    # Used BK with constant short-rate volatility
    sigma = 0.20
    a = 0.01
    model = BDTTree(sigma, num_time_steps)

    testCases.banner("BDT MODEL SWAPTION CLASS EUROPEAN EXERCISE")

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BDT PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################

    # Now we create the Bermudan swaptions but only allow European exercise
    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.EUROPEAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BDT MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.000001
    model = BDTTree(sigma, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 20% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BDT MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.2
    model = BDTTree(sigma, num_time_steps)

    testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    # Now we create the Bermudan swaptions but allow Bermudan exercise
    ###########################################################################

    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BDT MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.000001
    a = 0.01
    model = BDTTree(sigma, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 20% VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BDT MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.20
    a = 0.01
    model = BDTTree(sigma, num_time_steps)

    #    print("BDT MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    ###########################################################################
    ###########################################################################
    # BDT MODEL
    ###########################################################################
    ###########################################################################
    ###########################################################################

    testCases.banner("=======================================================")
    testCases.banner("=======================================================")
    testCases.banner("======================= HW MODEL ======================")
    testCases.banner("=======================================================")
    testCases.banner("=======================================================")

    testCases.banner("====== 0% VOLATILITY EUROPEAN SWAPTION HW MODEL ======")

    sigma = 0.0000001
    a = 0.1
    num_time_steps = 200
    model = HWTree(sigma, a, num_time_steps)

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN HW PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN HW REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner("===== 20% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======")

    # Used BK with constant short-rate volatility
    sigma = 0.01
    a = 0.01
    model = HWTree(sigma, a, num_time_steps)

    testCases.banner("HW MODEL SWAPTION CLASS EUROPEAN EXERCISE")

    valuePay = europeanSwaptionPay.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN HW PAY VALUE:", valuePay)

    valueRec = europeanSwaptionRec.value(valuation_date, libor_curve, model)
    testCases.print("EUROPEAN HW REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################

    # Now we create the Bermudan swaptions but only allow European exercise
    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.EUROPEAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE HW MODEL ========"
    )

    sigma = 0.000001
    model = HWTree(sigma, a, num_time_steps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 100bp VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE HW MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.01
    model = HWTree(sigma, a, num_time_steps)

    testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN BDT REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    ###########################################################################
    # Now we create the Bermudan swaptions but allow Bermudan exercise
    ###########################################################################

    fixed_leg_type = SwapTypes.PAY
    exercise_type = FinExerciseTypes.BERMUDAN

    bermudan_swaption_pay = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    fixed_leg_type = SwapTypes.RECEIVE
    bermudan_swaption_rec = IborBermudanSwaption(
        settlement_date, exercise_date, swapMaturityDate, fixed_leg_type,
        exercise_type, swapFixedCoupon, swapFixedFrequencyType,
        swapFixedDayCountType)

    testCases.banner(
        "======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE HW MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.000001
    a = 0.01
    model = HWTree(sigma, a, num_time_steps)

    testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN HW PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN HW REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)

    testCases.banner(
        "======= 100bps VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE HW MODEL ========"
    )

    # Used BK with constant short-rate volatility
    sigma = 0.01
    a = 0.01
    model = HWTree(sigma, a, num_time_steps)

    testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudan_swaption_pay.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN HW PAY VALUE:", valuePay)

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    testCases.print("BERMUDAN HW REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)
예제 #10
0
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.add_tenor("18m")  # Date(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._accrued_interest)

    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")

    num_time_steps = range(100, 1000, 200)
    strike_prices = [90, 100, 110, 120]

    for strike_price in strike_prices:

        callIntrinsic = max(spotCleanValue - strike_price, 0)
        putIntrinsic = max(strike_price - spotCleanValue, 0)
        callIntrinsicPV = max(fwdCleanValue - strike_price, 0) * dfExpiry
        putIntrinsicPV = max(strike_price - fwdCleanValue, 0) * dfExpiry

        for num_steps in num_time_steps:

            sigma = 0.0000001
            model = BDTTree(sigma, num_steps)

            option_type = FinOptionTypes.EUROPEAN_CALL
            bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v1 = bond_option1.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.AMERICAN_CALL
            bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v2 = bond_option2.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.EUROPEAN_PUT
            bond_option3 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v3 = bond_option3.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.AMERICAN_PUT
            bond_option4 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v4 = bond_option4.value(settlement_date, discount_curve, model)

            testCases.print(strike_price, num_steps, callIntrinsic,
                            callIntrinsicPV, v1, v2, putIntrinsic,
                            putIntrinsicPV, v3, v4)
예제 #11
0
def test_BondOption():

    settlement_date = Date(1, 12, 2019)
    issue_date = Date(1, 12, 2018)
    maturity_date = settlement_date.add_tenor("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.add_years(times)
    dfs = np.exp(-0.05 * times)
    discount_curve = DiscountCurve(settlement_date, dates, dfs)

    expiry_date = settlement_date.add_tenor("18m")
    strike_price = 105.0
    face = 100.0

    ###########################################################################

    strikes = [80, 90, 100, 110, 120]

    option_type = FinOptionTypes.EUROPEAN_CALL

    testCases.header("LABEL", "VALUE")

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)
    testCases.print("Fixed Income Price:", price)

    num_time_steps = 100

    testCases.header("OPTION TYPE AND MODEL", "STRIKE", "VALUE")

    for strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN CALL - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN CALL - BK", strike_price, v)

    ###########################################################################

    option_type = 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 strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN CALL - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN CALL - BK", strike_price, v)

    ###########################################################################

    option_type = FinOptionTypes.EUROPEAN_PUT

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)

    for strike_price in strikes:

        sigma = 0.01

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN PUT - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN PUT - BK", strike_price, v)

    ###########################################################################

    option_type = FinOptionTypes.AMERICAN_PUT

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)

    for strike_price in strikes:

        sigma = 0.02

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN PUT - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BDTTree(sigma, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN PUT - BK", strike_price, v)
예제 #12
0
def test_BondOptionAmericanConvergenceTWO():

    # Build discount curve
    settlement_date = Date(1, 12, 2019)
    discount_curve = DiscountCurveFlat(settlement_date, 0.05,
                                       FrequencyTypes.CONTINUOUS)

    # Bond details
    issue_date = Date(1, 9, 2014)
    maturity_date = Date(1, 9, 2025)
    coupon = 0.05
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)
    expiry_date = settlement_date.add_tenor("18m")
    face = 100.0

    spotValue = bond.full_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.2
    model = BDTTree(sigma)
    K = 101.0

    vec_ec = []
    vec_ac = []
    vec_ep = []
    vec_ap = []

    if 1 == 1:
        K = 100.0
        bkModel = BDTTree(sigma, 100)
        europeanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.EUROPEAN_CALL)

        v_ec = europeanCallBondOption.value(settlement_date, discount_curve,
                                            model)
        testCases.header("LABEL", "VALUE")
        testCases.print("OPTION", v_ec)

    num_stepsVector = range(100, 100, 1)  # should be 100-400

    for num_steps in num_stepsVector:

        bkModel = BDTTree(sigma, num_steps)

        start = time.time()

        europeanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.EUROPEAN_CALL)
        v_ec = europeanCallBondOption.value(settlement_date, discount_curve,
                                            bkModel)

        americanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.AMERICAN_CALL)
        v_ac = americanCallBondOption.value(settlement_date, discount_curve,
                                            bkModel)

        europeanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           FinOptionTypes.EUROPEAN_PUT)
        v_ep = europeanPutBondOption.value(settlement_date, discount_curve,
                                           bkModel)

        americanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           FinOptionTypes.AMERICAN_PUT)
        v_ap = americanPutBondOption.value(settlement_date, discount_curve,
                                           bkModel)

        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_ec, label="European Call")
        plt.legend()

        plt.figure()
        plt.plot(num_stepsVector, vec_ac, label="American Call")
        plt.legend()

        plt.figure()
        plt.plot(num_stepsVector, vec_ep, label="European Put")
        plt.legend()

        plt.figure()
        plt.plot(num_stepsVector, vec_ap, label="American Put")
        plt.legend()
예제 #13
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
예제 #14
0
def test_BDTExampleTwo():
    # Valuation of a European option on a coupon bearing bond
    # This follows example in Fig 28.11 of John Hull's book (6th Edition)
    # but does not have the exact same dt so there are some differences

    settlement_date = Date(1, 12, 2019)
    issue_date = Date(1, 12, 2015)
    expiry_date = settlement_date.add_tenor("18m")
    maturity_date = settlement_date.add_tenor("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._coupon_dates)

    for i in range(1, num_flows):
        pcd = bond._coupon_dates[i - 1]
        ncd = bond._coupon_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 flow_date in bond._coupon_dates:
        if flow_date > settlement_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)

    strike_price = 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.add_years(times)
    dfs = np.exp(-0.05 * times)

    curve = DiscountCurve(settlement_date, dates, dfs)

    price = bond.clean_price_from_discount_curve(settlement_date, curve)
    assert round(price, 4) == 99.5420

    sigma = 0.20

    # Test convergence
    num_time_steps = 5
    exercise_type = FinExerciseTypes.AMERICAN

    model = BDTTree(sigma, num_time_steps)
    model.build_tree(tmat, times, dfs)
    v = model.bond_option(texp, strike_price, face, coupon_times, coupon_flows,
                          exercise_type)

    assert round(v['call'], 4) == 0.5043
    assert round(v['put'], 4) == 8.2242