def testIborSwaptionModels():

    ##########################################################################
    # COMPARISON OF MODELS
    ##########################################################################

    valuation_date = Date(1, 1, 2011)
    libor_curve = test_ibor_depositsAndSwaps(valuation_date)

    exercise_date = Date(1, 1, 2012)
    swapMaturityDate = Date(1, 1, 2017)

    swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = DayCountTypes.ACT_365F

    strikes = np.linspace(0.02, 0.08, 5)

    testCases.header("LAB", "STRIKE", "BLK", "BLK_SHFT", "SABR", "SABR_SHFT",
                     "HW", "BK")

    model1 = Black(0.00001)
    model2 = BlackShifted(0.00001, 0.0)
    model3 = SABR(0.013, 0.5, 0.5, 0.5)
    model4 = SABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
    model5 = HWTree(0.00001, 0.00001)
    model6 = BKTree(0.01, 0.01)

    settlement_date = valuation_date.add_weekdays(2)

    for k in strikes:
        swaptionType = SwapTypes.PAY
        swaption = IborSwaption(settlement_date, exercise_date,
                                swapMaturityDate, swaptionType, k,
                                swapFixedFrequencyType, swapFixedDayCountType)

        swap1 = swaption.value(valuation_date, libor_curve, model1)
        swap2 = swaption.value(valuation_date, libor_curve, model2)
        swap3 = swaption.value(valuation_date, libor_curve, model3)
        swap4 = swaption.value(valuation_date, libor_curve, model4)
        swap5 = swaption.value(valuation_date, libor_curve, model5)
        swap6 = swaption.value(valuation_date, libor_curve, model6)
        testCases.print("PAY", k, swap1, swap2, swap3, swap4, swap5, swap6)

    testCases.header("LABEL", "STRIKE", "BLK", "BLK_SHFTD", "SABR",
                     "SABR_SHFTD", "HW", "BK")

    for k in strikes:
        swaptionType = SwapTypes.RECEIVE
        swaption = IborSwaption(settlement_date, exercise_date,
                                swapMaturityDate, swaptionType, k,
                                swapFixedFrequencyType, swapFixedDayCountType)

        swap1 = swaption.value(valuation_date, libor_curve, model1)
        swap2 = swaption.value(valuation_date, libor_curve, model2)
        swap3 = swaption.value(valuation_date, libor_curve, model3)
        swap4 = swaption.value(valuation_date, libor_curve, model4)
        swap5 = swaption.value(valuation_date, libor_curve, model5)
        swap6 = swaption.value(valuation_date, libor_curve, model6)
        testCases.print("REC", k, swap1, swap2, swap3, swap4, swap5, swap6)
Beispiel #2
0
def test_HullWhiteExampleOne():
    # HULL BOOK INITIAL EXAMPLE SECTION 28.7 HW EDITION 6

    times = [0.0, 0.5000, 1.00000, 1.50000, 2.00000, 2.500000, 3.00000]
    zeros = [0.03, 0.0343, 0.03824, 0.04183, 0.04512, 0.048512, 0.05086]
    times = np.array(times)
    zeros = np.array(zeros)
    dfs = np.exp(-zeros * times)

    start_date = Date(1, 12, 2019)
    end_date = Date(1, 12, 2022)
    sigma = 0.01
    a = 0.1
    num_time_steps = 3
    model = HWTree(sigma, a, num_time_steps)
    treeMat = (end_date - start_date) / gDaysInYear
    model.build_tree(treeMat, times, dfs)
Beispiel #3
0
def test_matlab_hw():
    sigma = 0.01  # basis point volatility
    a = 0.1

    model = HWTree(sigma, a, num_time_steps)

    v = puttableBond_matlab.value(settlement_date_matlab,
                                  discount_curve_matlab, model)

    assert round(v['bondwithoption'], 4) == 102.8733
    assert round(v['bondpure'], 4) == 102.0603
Beispiel #4
0
def test_quantlib_hw():
    # the value used in blog of 12% bp vol is unrealistic
    sigma = 0.12  # basis point volatility
    a = 0.03
    model = HWTree(sigma, a, num_time_steps)

    v = puttableBond_quantlib.value(settlement_date_quantlib,
                                    discount_curve_quantlib, model)

    assert round(v['bondwithoption'], 4) == 68.8665
    assert round(v['bondpure'], 4) == 95.0619
Beispiel #5
0
def test_american_put_hw():
    option_type = OptionTypes.AMERICAN_PUT
    strike_price = 100

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

    sigma = 0.02
    a = 0.1
    model = HWTree(sigma, a)

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

    assert round(v, 4) == 4.7948
Beispiel #6
0
def test_european_put_hw():
    option_type = OptionTypes.EUROPEAN_PUT
    strike_price = 100

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

    sigma = 0.01
    a = 0.1
    model = HWTree(sigma, a)

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

    assert round(v, 4) == 2.2767
def test_hw_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.000001
    a = 0.01
    model = HWTree(sigma, a, num_time_steps)

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

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

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

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

    valueRec = bermudan_swaption_rec.value(valuation_date, libor_curve, model)
    assert round(valueRec, 4) == 10406.4558
Beispiel #8
0
def test_european_call_hw():
    option_type = OptionTypes.EUROPEAN_CALL
    strike_price = 100
    num_time_steps = 100

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

    sigma = 0.01
    a = 0.1
    model = HWTree(sigma, a, num_time_steps)

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

    assert round(v, 4) == 1.8809
Beispiel #9
0
def test_FinIborCapFloor():

    todayDate = Date(20, 6, 2019)
    valuation_date = todayDate
    start_date = todayDate.add_weekdays(2)
    maturity_date = start_date.add_tenor("1Y")
    libor_curve = test_ibor_depositsAndSwaps(todayDate)

    # The capfloor has begun
    # lastFixing = 0.028

    ##########################################################################
    # COMPARISON OF MODELS
    ##########################################################################

    strikes = np.linspace(0.02, 0.08, 5)

    testCases.header("LABEL", "STRIKE", "BLK", "BLK_SHFTD", "SABR",
                     "SABR_SHFTD", "HW", "BACH")

    model1 = Black(0.20)
    model2 = BlackShifted(0.25, 0.0)
    model3 = SABR(0.013, 0.5, 0.5, 0.5)
    model4 = SABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
    model5 = HWTree(0.30, 0.01)
    model6 = Bachelier(0.01)

    for k in strikes:
        capFloorType = FinCapFloorTypes.CAP
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        cvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        cvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        cvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        cvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        cvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        cvalue6 = capfloor.value(valuation_date, libor_curve, model6)
        testCases.print("CAP", k, cvalue1, cvalue2,
                        cvalue3, cvalue4, cvalue5, cvalue6)

    testCases.header("LABEL", "STRIKE", "BLK", "BLK_SHFTD", "SABR",
                     "SABR_SHFTD", "HW", "BACH")

    for k in strikes:
        capFloorType = FinCapFloorTypes.FLOOR
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        fvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        fvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        fvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        fvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        fvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        fvalue6 = capfloor.value(valuation_date, libor_curve, model6)
        testCases.print("FLR", k, fvalue1, fvalue2,
                        fvalue3, fvalue4, fvalue5, fvalue6)

###############################################################################
# PUT CALL CHECK
###############################################################################

    testCases.header("LABEL", "STRIKE", "BLK", "BLK_SHFTD", "SABR",
                     "SABR SHFTD", "HW", "BACH")

    for k in strikes:
        capFloorType = FinCapFloorTypes.CAP
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        cvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        cvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        cvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        cvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        cvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        cvalue6 = capfloor.value(valuation_date, libor_curve, model6)

        capFloorType = FinCapFloorTypes.FLOOR
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        fvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        fvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        fvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        fvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        fvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        fvalue6 = capfloor.value(valuation_date, libor_curve, model6)

        pcvalue1 = cvalue1 - fvalue1
        pcvalue2 = cvalue2 - fvalue2
        pcvalue3 = cvalue3 - fvalue3
        pcvalue4 = cvalue4 - fvalue4
        pcvalue5 = cvalue5 - fvalue5
        pcvalue6 = cvalue6 - fvalue6

        testCases.print("PUT_CALL", k, pcvalue1, pcvalue2, pcvalue3,
                        pcvalue4, pcvalue5, pcvalue6)
Beispiel #10
0
def test_BondOptionDerivaGem():

    # See https://github.com/domokane/FinancePy/issues/98

    settlement_date = Date(1, 12, 2019)

    rate = 0.05
    dcType = DayCountTypes.THIRTY_360_BOND
    fixedFreq = FrequencyTypes.SEMI_ANNUAL
    discount_curve = DiscountCurveFlat(settlement_date, rate, fixedFreq,
                                       dcType)

    issue_date = Date(1, 12, 2018)
    expiry_date = settlement_date.add_tenor("18m")
    maturity_date = settlement_date.add_tenor("10Y")

    coupon = 0.05
    freqType = FrequencyTypes.SEMI_ANNUAL
    accrualType = DayCountTypes.THIRTY_360_BOND
    bond = Bond(issue_date, maturity_date, coupon, freqType, accrualType)
    strike_price = 100.0
    face = 100.0

    europeanCallBondOption = BondOption(bond, expiry_date, strike_price, face,
                                        OptionTypes.EUROPEAN_CALL)
    cp = bond.clean_price_from_discount_curve(expiry_date, discount_curve)
    fp = bond.full_price_from_discount_curve(expiry_date, discount_curve)
    #    print("Fixed Income Clean Price: %9.3f"% cp)
    #    print("Fixed Income Full  Price: %9.3f"% fp)

    num_steps = 500
    sigma = 0.0125
    a = 0.1
    modelHW = HWTree(sigma, a, num_steps)

    ec = europeanCallBondOption.value(settlement_date, discount_curve, modelHW)

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

    couponTimes = []
    couponFlows = []
    cpn = bond._coupon / bond._frequency

    numFlows = len(bond._flow_dates)
    for i in range(0, numFlows):

        pcd = bond._flow_dates[i - 1]
        ncd = bond._flow_dates[i]

        if ncd > settlement_date:

            if len(couponTimes) == 0:
                flowTime = (pcd - settlement_date) / gDaysInYear
                couponTimes.append(flowTime)
                couponFlows.append(cpn)

            flowTime = (ncd - settlement_date) / gDaysInYear
            couponTimes.append(flowTime)
            couponFlows.append(cpn)

    couponTimes = np.array(couponTimes)
    couponFlows = np.array(couponFlows)

    y = 0.05
    times = np.linspace(0, 10, 21)
    dfs = np.power(1 + y / 2, -times * 2)

    sigma = 0.0125
    a = 0.1
    model = HWTree(sigma, a, None)

    #  Test convergence
    texp = (expiry_date - settlement_date) / gDaysInYear
    tmat = (maturity_date - settlement_date) / gDaysInYear

    # Jamshidian approach
    vjam = model.european_bond_option_jamshidian(texp, strike_price, face,
                                                 couponTimes, couponFlows,
                                                 times, dfs)
    # print("Jamshidian:", vjam)

    model._num_time_steps = 100
    model.build_tree(tmat, times, dfs)
    exerciseType = FinExerciseTypes.EUROPEAN

    vHW = model.bond_option(texp, strike_price, face, couponTimes, couponFlows,
                            exerciseType)
Beispiel #11
0
def test_BondOptionZEROVOLConvergence():

    # Build discount curve
    settlement_date = Date(1, 9, 2019)
    rate = 0.05
    discount_curve = DiscountCurveFlat(settlement_date, rate,
                                       FrequencyTypes.ANNUAL)

    # Bond details
    issue_date = Date(1, 9, 2014)
    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 = Date(1, 12, 2021)
    face = 100.0

    dfExpiry = discount_curve.df(expiry_date)
    fwdCleanValue = bond.clean_price_from_discount_curve(
        expiry_date, discount_curve)
    #    fwdFullValue = bond.full_price_from_discount_curve(expiry_date, discount_curve)
    #    print("BOND FwdCleanBondPx", fwdCleanValue)
    #    print("BOND FwdFullBondPx", fwdFullValue)
    #    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, 100)
    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
            a = 0.1
            model = HWTree(sigma, a, num_steps)

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

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

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

            option_type = OptionTypes.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)
Beispiel #12
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)

    times = np.linspace(0, 10.0, 21)
    dfs = np.exp(-0.05 * times)
    dates = settlement_date.add_years(times)
    discount_curve = DiscountCurve(settlement_date, dates, dfs)

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

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

    strikes = [80, 85, 90, 95, 100, 105, 110, 115, 120]

    option_type = OptionTypes.EUROPEAN_CALL

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

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

    num_time_steps = 100

    testCases.banner("HW EUROPEAN CALL")
    testCases.header("STRIKE", "VALUE")

    for strike_price in strikes:

        sigma = 0.01
        a = 0.1

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

        model = HWTree(sigma, a, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print(strike_price, v)

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

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

        sigma = 0.01
        a = 0.1

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

        model = HWTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print(strike_price, v)

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

    option_type = OptionTypes.EUROPEAN_PUT
    testCases.banner("HW EUROPEAN PUT")
    testCases.header("STRIKE", "VALUE")

    price = bond.clean_price_from_discount_curve(settlement_date,
                                                 discount_curve)

    for strike_price in strikes:

        sigma = 0.01
        a = 0.1

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

        model = HWTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print(strike_price, v)

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

    option_type = OptionTypes.AMERICAN_PUT
    testCases.banner("HW AMERICAN PUT")
    testCases.header("STRIKE", "VALUE")

    price = bond.clean_price_from_discount_curve(settlement_date,
                                                 discount_curve)

    for strike_price in strikes:

        sigma = 0.02
        a = 0.1

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

        model = HWTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print(strike_price, v)
    return libor_curve


valuation_date = Date(1, 1, 2011)

exercise_date = Date(1, 1, 2012)
swapMaturityDate = Date(1, 1, 2017)

swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL
swapFixedDayCountType = DayCountTypes.ACT_365F

model1 = Black(0.00001)
model2 = BlackShifted(0.00001, 0.0)
model3 = SABR(0.013, 0.5, 0.5, 0.5)
model4 = SABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
model5 = HWTree(0.00001, 0.00001)
model6 = BKTree(0.01, 0.01)

settlement_date = valuation_date.add_weekdays(2)

libor_curve = build_curve(valuation_date)


def test_pay():
    libor_curve = build_curve(valuation_date)
    swaptionType = SwapTypes.PAY

    k = 0.02
    swaption = IborSwaption(settlement_date, exercise_date, swapMaturityDate,
                            swaptionType, k, swapFixedFrequencyType,
                            swapFixedDayCountType)
Beispiel #14
0
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.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

    for flow_date in bond._coupon_dates[1:]:

        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)

    ###########################################################################
    # Set up the call and put times and prices
    ###########################################################################

    call_dates = []
    call_prices = []
    callPx = 120.0
    call_dates.append(settlement_date.add_tenor("2Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("3Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("4Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("5Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("6Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("7Y"))
    call_prices.append(callPx)
    call_dates.append(settlement_date.add_tenor("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.add_tenor("2Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("3Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("4Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("5Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("6Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("7Y"))
    put_prices.append(putPx)
    put_dates.append(settlement_date.add_tenor("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._coupon_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_steps_list = [100, 200, 500, 1000]
    tmat = (maturity_date - settlement_date) / gDaysInYear

    testCases.header("NUMSTEPS", "TIME", "BOND_ONLY", "CALLABLE_BOND")

    for num_time_steps in num_steps_list:

        start = time.time()
        model = HWTree(sigma, a, num_time_steps)
        model.build_tree(tmat, times, dfs)

        v2 = model.callable_puttable_bond_tree(coupon_times, coupon_flows,
                                               call_times, call_prices,
                                               put_times, put_prices, 100.0)

        end = time.time()
        period = end - start
        testCases.print(num_time_steps, period, v1, v2)
Beispiel #15
0
def test_BondEmbeddedOptionMATLAB():

    # https://fr.mathworks.com/help/fininst/optembndbyhw.html
    # I FIND THAT THE PRICE CONVERGES TO 102.88 WHICH IS CLOSE TO 102.9127
    # FOUND BY MATLAB ALTHOUGH THEY DO NOT EXAMINE THE ASYMPTOTIC PRICE
    # WHICH MIGHT BE A BETTER MATCH

    settlement_date = Date(1, 1, 2007)
    valuation_date = settlement_date

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

    dcType = DayCountTypes.THIRTY_E_360
    fixedFreq = FrequencyTypes.ANNUAL
    fixed_leg_type = SwapTypes.PAY
    swap1 = IborSwap(settlement_date, "1Y", fixed_leg_type, 0.0350, fixedFreq,
                     dcType)
    swap2 = IborSwap(settlement_date, "2Y", fixed_leg_type, 0.0400, fixedFreq,
                     dcType)
    swap3 = IborSwap(settlement_date, "3Y", fixed_leg_type, 0.0450, fixedFreq,
                     dcType)
    swaps = [swap1, swap2, swap3]
    discount_curve = IborSingleCurve(valuation_date, [], [], swaps)

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

    issue_date = Date(1, 1, 2004)
    maturity_date = Date(1, 1, 2010)

    coupon = 0.0525
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    call_dates = []
    call_prices = []
    put_dates = []
    put_prices = []

    putDate = Date(1, 1, 2008)
    for _ in range(0, 24):
        put_dates.append(putDate)
        put_prices.append(100)
        putDate = putDate.add_months(1)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.clean_price_from_discount_curve(settlement_date, discount_curve)
    testCases.print("Bond Pure Price:", v)

    sigma = 0.01  # basis point volatility
    a = 0.1

    puttableBond = BondEmbeddedOption(issue_date, maturity_date, coupon,
                                      freq_type, accrual_type, call_dates,
                                      call_prices, put_dates, put_prices)

    testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure")

    timeSteps = range(50, 1000, 50)
    values = []
    for num_time_steps in timeSteps:
        model = HWTree(sigma, a, num_time_steps)
        start = time.time()
        v = puttableBond.value(settlement_date, discount_curve, model)
        end = time.time()
        period = end - start
        testCases.print(period, num_time_steps, v['bondwithoption'],
                        v['bondpure'])
        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.plot(timeSteps, values)
Beispiel #16
0
def test_BondEmbeddedOptionQUANTLIB():

    # Based on example at the nice blog on Quantlib at
    # http://gouthamanbalaraman.com/blog/callable-bond-quantlib-python.html
    # I get a price of 68.97 for 1000 time steps which is higher than the
    # 68.38 found in blog article. But this is for 40 grid points.
    # Note also that a basis point vol of 0.120 is 12% which is VERY HIGH!

    valuation_date = Date(16, 8, 2016)
    settlement_date = valuation_date.add_weekdays(3)

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

    discount_curve = DiscountCurveFlat(valuation_date, 0.035,
                                       FrequencyTypes.SEMI_ANNUAL)

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

    issue_date = Date(15, 9, 2010)
    maturity_date = Date(15, 9, 2022)
    coupon = 0.025
    freq_type = FrequencyTypes.QUARTERLY
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    ###########################################################################
    # Set up the call and put times and prices
    ###########################################################################

    nextCallDate = Date(15, 9, 2016)
    call_dates = [nextCallDate]
    call_prices = [100.0]

    for _ in range(1, 24):
        nextCallDate = nextCallDate.add_months(3)
        call_dates.append(nextCallDate)
        call_prices.append(100.0)

    put_dates = []
    put_prices = []

    # the value used in blog of 12% bp vol is unrealistic
    sigma = 0.12  # basis point volatility
    a = 0.03

    puttableBond = BondEmbeddedOption(issue_date, maturity_date, coupon,
                                      freq_type, accrual_type, call_dates,
                                      call_prices, put_dates, put_prices)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.clean_price_from_discount_curve(settlement_date, discount_curve)
    testCases.print("Bond Pure Price:", v)

    testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure")
    timeSteps = range(100, 200, 50)
    values = []
    for num_time_steps in timeSteps:
        model = HWTree(sigma, a, num_time_steps)
        start = time.time()
        v = puttableBond.value(settlement_date, discount_curve, model)
        end = time.time()
        period = end - start
        testCases.print(period, num_time_steps, v['bondwithoption'],
                        v['bondpure'])
        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.title("Puttable Bond Price Convergence")
        plt.plot(timeSteps, values)
Beispiel #17
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)
Beispiel #18
0
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
    ]

    zero_rates = [
        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(zero_rates) / 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.add_tenor("3Y")
    maturity_date = start_date.add_tenor("9Y")

    texp = (expiry_date - start_date) / gDaysInYear
    tmat = (maturity_date - start_date) / gDaysInYear

    num_time_steps = None
    model = HWTree(sigma, a, num_time_steps)
    vAnal = model.option_on_zcb(texp, tmat, strike, face, times, dfs)

    # Test convergence
    num_steps_list = 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 num_time_steps in num_steps_list:

        start = time.time()

        model = HWTree(sigma, a, num_time_steps)
        model.build_tree(texp, times, dfs)
        vTree1 = model.option_on_zero_coupon_bond_tree(texp, tmat, strike,
                                                       face)

        model = HWTree(sigma, a, num_time_steps + 1)
        model.build_tree(texp, times, dfs)
        vTree2 = model.option_on_zero_coupon_bond_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(num_time_steps, period, vTreeCall, vAnal['call'],
                        vTreePut, vAnal['put'], diffC, diffP)
Beispiel #19
0
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.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 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)

    strike_price = 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 = HWTree(sigma, a, None)

    #  Test convergence
    num_steps_list = range(50, 500, 50)
    texp = (expiry_date - settlement_date) / gDaysInYear

    vJam = model.european_bond_option_jamshidian(texp, strike_price, 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 num_time_steps in num_steps_list:

        start = time.time()
        model = HWTree(sigma, a, num_time_steps,
                       FinHWEuropeanCalcType.EXPIRY_ONLY)
        model.build_tree(texp, times, dfs)

        exercise_type = FinExerciseTypes.EUROPEAN

        v1 = model.bond_option(texp, strike_price, face, coupon_times,
                               coupon_flows, exercise_type)

        model = HWTree(sigma, a, num_time_steps,
                       FinHWEuropeanCalcType.EXPIRY_TREE)
        model.build_tree(texp, times, dfs)

        v2 = model.bond_option(texp, strike_price, face, coupon_times,
                               coupon_flows, exercise_type)

        end = time.time()
        period = end - start

        testCases.print(num_time_steps, period, v1, v2, vJam)

#    plt.plot(num_steps_list, treeVector)

    if 1 == 0:
        print("RT")
        print_tree(model._rt, 5)
        print("BOND")
        print_tree(model._bond_values, 5)
        print("OPTION")
        print_tree(model._option_values, 5)
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)
Beispiel #21
0
def test_BondOptionEuropeanConvergence():

    # CONVERGENCE TESTS
    # COMPARE AMERICAN TREE VERSUS JAMSHIDIAN IN EUROPEAN LIMIT TO CHECK THAT
    # TREE HAS BEEN CORRECTLY CONSTRUCTED. FIND VERY GOOD AGREEMENT.

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

    # Bond details
    issue_date = Date(1, 12, 2015)
    maturity_date = Date(1, 12, 2020)
    coupon = 0.05
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    # Option Details - put expiry in the middle of a coupon period
    expiry_date = Date(1, 3, 2020)
    strike_price = 100.0
    face = 100.0

    timeSteps = range(100, 400, 100)
    strike_price = 100.0

    testCases.header("TIME", "N", "PUT_JAM", "PUT_TREE", "CALL_JAM",
                     "CALL_TREE")

    for num_time_steps in timeSteps:

        sigma = 0.05
        a = 0.1

        start = time.time()
        option_type = OptionTypes.EUROPEAN_PUT

        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model1 = HWTree(sigma, a, num_time_steps)
        v1put = bond_option1.value(settlement_date, discount_curve, model1)

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

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_ONLY)
        v2put = bond_option2.value(settlement_date, discount_curve, model2)

        option_type = OptionTypes.EUROPEAN_CALL

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

        model1 = HWTree(sigma, a, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model1)

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

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_TREE)
        v2call = bond_option2.value(settlement_date, discount_curve, model2)

        end = time.time()
        period = end - start
        testCases.print(period, num_time_steps, v1put, v2put, v1call, v2call)
    libor_curve = IborSingleCurve(valuation_date, depos, fras, swaps)

    return libor_curve


todayDate = Date(20, 6, 2019)
valuation_date = todayDate
start_date = todayDate.add_weekdays(2)
maturity_date = start_date.add_tenor("1Y")
libor_curve = build_curve(todayDate)

model1 = Black(0.20)
model2 = BlackShifted(0.25, 0.0)
model3 = SABR(0.013, 0.5, 0.5, 0.5)
model4 = SABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
model5 = HWTree(0.30, 0.01)
model6 = Bachelier(0.01)


def test_cap():
    capFloorType = FinCapFloorTypes.CAP

    k = 0.02
    capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
    cvalue1 = capfloor.value(valuation_date, libor_curve, model1)
    cvalue2 = capfloor.value(valuation_date, libor_curve, model2)
    cvalue3 = capfloor.value(valuation_date, libor_curve, model3)
    cvalue4 = capfloor.value(valuation_date, libor_curve, model4)
    cvalue5 = capfloor.value(valuation_date, libor_curve, model5)
    cvalue6 = capfloor.value(valuation_date, libor_curve, model6)
    assert round(cvalue1, 4) == 28889.2445
def test_IborSwaptionQLExample():

    valuation_date = Date(4, 3, 2014)
    settlement_date = Date(4, 3, 2014)

    depoDCCType = DayCountTypes.THIRTY_E_360_ISDA
    depos = []
    depo = IborDeposit(settlement_date, "1W", 0.0023, depoDCCType)
    depos.append(depo)
    depo = IborDeposit(settlement_date, "1M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = IborDeposit(settlement_date, "3M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = IborDeposit(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_leg_type = SwapTypes.PAY

    swap = IborSwap(settlement_date, "3Y", fixed_leg_type, 0.00790,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "4Y", fixed_leg_type, 0.01200,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "5Y", fixed_leg_type, 0.01570,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "6Y", fixed_leg_type, 0.01865,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "7Y", fixed_leg_type, 0.02160,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "8Y", fixed_leg_type, 0.02350,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "9Y", fixed_leg_type, 0.02540,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "10Y", fixed_leg_type, 0.0273,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "15Y", fixed_leg_type, 0.0297,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "20Y", fixed_leg_type, 0.0316,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "25Y", fixed_leg_type, 0.0335,
                    fixedFreqType, accType)
    swaps.append(swap)
    swap = IborSwap(settlement_date, "30Y", fixed_leg_type, 0.0354,
                    fixedFreqType, accType)
    swaps.append(swap)

    libor_curve = IborSingleCurve(valuation_date, depos, [], swaps,
                                  InterpTypes.LINEAR_ZERO_RATES)

    exercise_date = settlement_date.add_tenor("5Y")
    swapMaturityDate = exercise_date.add_tenor("5Y")
    swapFixedCoupon = 0.040852
    swapFixedFrequencyType = FrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = DayCountTypes.THIRTY_E_360_ISDA
    swapFloatFrequencyType = FrequencyTypes.QUARTERLY
    swapFloatDayCountType = DayCountTypes.ACT_360
    swapNotional = 1000000
    swaptionType = SwapTypes.PAY

    swaption = IborSwaption(settlement_date, exercise_date, swapMaturityDate,
                            swaptionType, swapFixedCoupon,
                            swapFixedFrequencyType, swapFixedDayCountType,
                            swapNotional, swapFloatFrequencyType,
                            swapFloatDayCountType)

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

    model = Black(0.1533)
    v = swaption.value(settlement_date, libor_curve, model)
    testCases.print(model.__class__, v)

    model = BlackShifted(0.1533, -0.008)
    v = swaption.value(settlement_date, libor_curve, model)
    testCases.print(model.__class__, v)

    model = SABR(0.132, 0.5, 0.5, 0.5)
    v = swaption.value(settlement_date, libor_curve, model)
    testCases.print(model.__class__, v)

    model = SABRShifted(0.352, 0.5, 0.15, 0.15, -0.005)
    v = swaption.value(settlement_date, libor_curve, model)
    testCases.print(model.__class__, v)

    model = HWTree(0.010000000, 0.00000000001)
    v = swaption.value(settlement_date, libor_curve, model)
    testCases.print(model.__class__, v)
Beispiel #24
0
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, 2014)
    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(100, 500, 100)

    for num_time_steps in timeSteps:

        sigma = 0.05
        a = 0.1

        start = time.time()

        option_type = OptionTypes.AMERICAN_PUT
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model1 = HWTree(sigma, a, num_time_steps)
        v1put = bond_option1.value(settlement_date, discount_curve, model1)

        option_type = OptionTypes.EUROPEAN_PUT
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_ONLY)
        v2put = bond_option2.value(settlement_date, discount_curve, model2)

        option_type = OptionTypes.AMERICAN_CALL
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model1 = HWTree(sigma, a, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model1)

        option_type = OptionTypes.EUROPEAN_CALL
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_TREE)
        v2call = bond_option2.value(settlement_date, discount_curve, model2)

        end = time.time()

        period = end - start

        testCases.print(period, num_time_steps, v1put, v2put, v1call, v2call)
Beispiel #25
0
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.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)
    expiry_date = settlement_date.add_tenor("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 = HWTree(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 = HWTree(sigma, a, num_steps)

        start = time.time()

        europeanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            OptionTypes.EUROPEAN_CALL)

        v_ec = europeanCallBondOption.value(settlement_date, discount_curve,
                                            hwModel)

        americanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            OptionTypes.AMERICAN_CALL)

        v_ac = americanCallBondOption.value(settlement_date, discount_curve,
                                            hwModel)

        europeanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           OptionTypes.EUROPEAN_PUT)

        v_ep = europeanPutBondOption.value(settlement_date, discount_curve,
                                           hwModel)

        americanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           OptionTypes.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
    ]

    zero_rates = [
        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(zero_rates) / 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.add_tenor("3Y")
    maturity_date = start_date.add_tenor("9Y")

    texp = (expiry_date - start_date) / gDaysInYear
    tmat = (maturity_date - start_date) / gDaysInYear

    num_time_steps = None
    model = HWTree(sigma, a, num_time_steps)
    vAnal = model.option_on_zcb(texp, tmat, strike, face, times, dfs)

    num_time_steps = 200

    model = HWTree(sigma, a, num_time_steps)
    model.build_tree(texp, times, dfs)
    vTree1 = model.option_on_zero_coupon_bond_tree(texp, tmat, strike, face)

    model = HWTree(sigma, a, num_time_steps + 1)
    model.build_tree(texp, times, dfs)
    vTree2 = model.option_on_zero_coupon_bond_tree(texp, tmat, strike, face)

    vTreeCall = (vTree1['call'] + vTree2['call']) / 2.0
    vTreePut = (vTree1['put'] + vTree2['put']) / 2.0

    assert round(vTreeCall, 4) == 1.0450
    assert round(vAnal['call'], 4) == 1.0448
    assert round(vTreePut, 4) == 1.8237
    assert round(vAnal['put'], 4) == 1.8239