Example #1
0
def test_BKExampleOne():

    testCases.banner("=== HULL INITIAL EXAMPLE SECTION 28.7 ED 6 PG 668 ====")

    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)

    startDate = FinDate(1, 12, 2019)
    endDate = FinDate(1, 6, 2021)
    sigma = 0.25
    a = 0.22
    numTimeSteps = 3
    tmat = (endDate - startDate) / gDaysInYear
    model = FinModelRatesBK(sigma, a, numTimeSteps)
    model.buildTree(tmat, times, dfs)

    # Agrees with Figure 28.10 - Not exact as we have dt not exactly 0.50
    if numTimeSteps < 5:
        testCases.header("LABEL", "VALUE")
        testCases.print("QTREE", model._Q)
        testCases.print("RTREE", model._rt)
        printTree(model._rt)
        testCases.print("PU AT LAST TIME", model._pu)
        testCases.print("PDM AT LAST TIME", model._pm)
        testCases.print("PD AT LAST TIME", model._pd)
def test_FinBondOptionAmericanConvergenceONE():

    # Build discount curve
    settlementDate = FinDate(1, 12, 2019)
    discountCurve = FinDiscountCurveFlat(settlementDate, 0.05)

    # Bond details
    maturityDate = FinDate(1, 9, 2025)
    issueDate = FinDate(1, 9, 2016)
    coupon = 0.05
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType)

    # Option Details
    expiryDate = FinDate(1, 12, 2020)
    strikePrice = 100.0
    face = 100.0

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

    timeSteps = range(30, 100, 10)

    for numTimeSteps in timeSteps:

        sigma = 0.20
        a = 0.1

        start = time.time()

        optionType = FinOptionTypes.AMERICAN_PUT
        bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face,
                                    optionType)
        model1 = FinModelRatesBK(sigma, a, numTimeSteps)
        v1put = bondOption1.value(settlementDate, discountCurve, model1)

        optionType = FinOptionTypes.EUROPEAN_PUT
        bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face,
                                    optionType)
        model2 = FinModelRatesBK(sigma, a, numTimeSteps)
        v2put = bondOption2.value(settlementDate, discountCurve, model2)

        optionType = FinOptionTypes.AMERICAN_CALL
        bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face,
                                    optionType)
        model1 = FinModelRatesBK(sigma, a, numTimeSteps)
        v1call = bondOption1.value(settlementDate, discountCurve, model1)

        optionType = FinOptionTypes.EUROPEAN_CALL
        bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face,
                                    optionType)
        model2 = FinModelRatesBK(sigma, a, numTimeSteps)
        v2call = bondOption2.value(settlementDate, discountCurve, model2)

        end = time.time()

        period = end - start

        testCases.print(period, numTimeSteps, v1put, v2put, v1call, v2call)
Example #3
0
def test_FinBondEmbeddedOptionMATLAB():
    # https://fr.mathworks.com/help/fininst/optembndbybk.html
    # I FIND THAT THE PRICE CONVERGES TO 102.365 WHICH IS CLOSE TO 102.382
    # FOUND BY MATLAB ALTHOUGH THEY DO NOT EXAMINE THE ASYMPTOTIC PRICE
    # WHICH MIGHT BE A BETTER MATCH - ALSO THEY DO NOT USE A REALISTIC VOL

    settlementDate = FinDate(1, 1, 2007)

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

    swapType = FinSwapTypes.PAYER
    dcType = FinDayCountTypes.THIRTY_E_360
    fixedFreq = FinFrequencyTypes.ANNUAL
    swap1 = FinIborSwap(settlementDate, "1Y", swapType, 0.0350, fixedFreq,
                        dcType)
    swap2 = FinIborSwap(settlementDate, "2Y", swapType, 0.0400, fixedFreq,
                        dcType)
    swap3 = FinIborSwap(settlementDate, "3Y", swapType, 0.0450, fixedFreq,
                        dcType)
    swaps = [swap1, swap2, swap3]
    discountCurve = FinIborCurve(settlementDate, [], [], swaps)

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

    issueDate = FinDate(1, 1, 2005)
    maturityDate = FinDate(1, 1, 2010)
    coupon = 0.0525
    frequencyType = FinFrequencyTypes.ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)

    callDates = []
    callPrices = []
    putDates = []
    putPrices = []

    putDate = FinDate(1, 1, 2008)
    for _ in range(0, 24):
        putDates.append(putDate)
        putPrices.append(100)
        putDate = putDate.addMonths(1)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.print("Bond Pure Price:", v)

    sigma = 0.01  # This volatility is very small for a BK process
    a = 0.1

    puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon,
                                         frequencyType, accrualType, callDates,
                                         callPrices, putDates, putPrices)

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

    timeSteps = range(100, 200, 10)  # 1000, 10)
    values = []
    for numTimeSteps in timeSteps:
        model = FinModelRatesBK(sigma, a, numTimeSteps)
        start = time.time()
        v = puttableBond.value(settlementDate, discountCurve, model)
        end = time.time()
        period = end - start
        testCases.print(period, numTimeSteps, v['bondwithoption'],
                        v['bondpure'])

        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.plot(timeSteps, values)
Example #4
0
def test_FinBondEmbeddedOptionQUANTLIB():

    # 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!

    valueDate = FinDate(16, 8, 2016)
    settlementDate = valueDate.addWeekDays(3)

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

    discountCurve = FinDiscountCurveFlat(valueDate, 0.035,
                                         FinFrequencyTypes.SEMI_ANNUAL)

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

    issueDate = FinDate(15, 9, 2010)
    maturityDate = FinDate(15, 9, 2022)
    coupon = 0.025
    frequencyType = FinFrequencyTypes.QUARTERLY
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)

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

    nextCallDate = FinDate(15, 9, 2016)
    callDates = [nextCallDate]
    callPrices = [100.0]

    for _ in range(1, 24):
        nextCallDate = nextCallDate.addMonths(3)
        callDates.append(nextCallDate)
        callPrices.append(100.0)

    putDates = []
    putPrices = []

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

    puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon,
                                         frequencyType, accrualType, callDates,
                                         callPrices, putDates, putPrices)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.print("Bond Pure Price:", v)

    testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure")
    timeSteps = range(100, 200, 20)  # 1000, 10)
    values = []
    for numTimeSteps in timeSteps:
        model = FinModelRatesBK(sigma, a, numTimeSteps)
        start = time.time()
        v = puttableBond.value(settlementDate, discountCurve, model)
        end = time.time()
        period = end - start
        testCases.print(period, numTimeSteps, v['bondwithoption'],
                        v['bondpure'])
        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.title("Puttable Bond Price Convergence")
        plt.plot(timeSteps, values)
Example #5
0
def test_BKExampleTwo():
    # Valuation of a European option on a coupon bearing bond
    # This follows example in Fig 28.11 of John Hull's book but does not
    # have the exact same dt so there are some differences

    settlementDate = FinDate(1, 12, 2019)
    issueDate = FinDate(1, 12, 2018)
    expiryDate = settlementDate.addTenor("18m")
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    frequencyType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)

    couponTimes = []
    couponFlows = []
    cpn = bond._coupon / bond._frequency
    numFlows = len(bond._flowDates)

    for i in range(1, numFlows):
        pcd = bond._flowDates[i - 1]
        ncd = bond._flowDates[i]
        if pcd < settlementDate and ncd > settlementDate:
            flowTime = (pcd - settlementDate) / gDaysInYear
            couponTimes.append(flowTime)
            couponFlows.append(cpn)

    for flowDate in bond._flowDates:
        if flowDate > settlementDate:
            flowTime = (flowDate - settlementDate) / gDaysInYear
            couponTimes.append(flowTime)
            couponFlows.append(cpn)

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

    strikePrice = 105.0
    face = 100.0

    tmat = (maturityDate - settlementDate) / gDaysInYear
    texp = (expiryDate - settlementDate) / gDaysInYear
    times = np.linspace(0, tmat, 11)
    dates = settlementDate.addYears(times)
    dfs = np.exp(-0.05 * times)
    curve = FinDiscountCurve(settlementDate, dates, dfs)

    price = bond.cleanPriceFromDiscountCurve(settlementDate, curve)
    testCases.header("LABEL", "VALUE")
    testCases.print("Fixed Income Price:", price)

    sigma = 0.20
    a = 0.05
    numTimeSteps = 26

    model = FinModelRatesBK(sigma, a, numTimeSteps)
    model.buildTree(tmat, times, dfs)
    exerciseType = FinOptionExerciseTypes.AMERICAN
    v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows,
                         exerciseType)

    # Test convergence
    numStepsList = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
    exerciseType = FinOptionExerciseTypes.AMERICAN

    testCases.header("TIMESTEPS", "VALUE", "TIME")
    treeVector = []
    for numTimeSteps in numStepsList:
        start = time.time()
        model = FinModelRatesBK(sigma, a, numTimeSteps)
        model.buildTree(tmat, times, dfs)
        v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows,
                             exerciseType)
        end = time.time()
        period = end - start
        treeVector.append(v)
        testCases.print(numTimeSteps, v, period)

#    plt.plot(numStepsList, treeVector)

# Value in Hill converges to 0.699 with 100 time steps while I get 0.700

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

    valuationDate = FinDate(1, 1, 2011)
    settlementDate = valuationDate
    exerciseDate = settlementDate.addYears(1)
    swapMaturityDate = settlementDate.addYears(4)

    swapFixedCoupon = 0.060
    swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = FinDayCountTypes.ACT_365F

    liborCurve = FinDiscountCurveFlat(valuationDate,
                                      0.0625,
                                      FinFrequencyTypes.SEMI_ANNUAL)

    fwdPAYSwap = FinIborSwap(exerciseDate,
                                swapMaturityDate,
                                FinSwapTypes.PAY,
                                swapFixedCoupon,
                                swapFixedFrequencyType,
                                swapFixedDayCountType)

    fwdSwapValue = fwdPAYSwap.value(settlementDate, liborCurve, liborCurve)

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

    # fwdPAYSwap.printFixedLegPV()

    # Now we create the European swaptions
    fixedLegType = FinSwapTypes.PAY
    europeanSwaptionPay = FinIborSwaption(settlementDate,
                                           exerciseDate,
                                           swapMaturityDate,
                                           fixedLegType,
                                           swapFixedCoupon,
                                           swapFixedFrequencyType,
                                           swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    europeanSwaptionRec = FinIborSwaption(settlementDate,
                                           exerciseDate,
                                           swapMaturityDate,
                                           fixedLegType,
                                           swapFixedCoupon,
                                           swapFixedFrequencyType,
                                           swapFixedDayCountType)
    
    ###########################################################################
    ###########################################################################
    ###########################################################################
    # BLACK'S MODEL
    ###########################################################################
    ###########################################################################
    ###########################################################################

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

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

    valueRec = europeanSwaptionRec.value(settlementDate, liborCurve, 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 = FinModelBlack(0.20)
    testCases.print("Black Model", model._volatility)

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

    valueRec = europeanSwaptionRec.value(settlementDate, liborCurve, 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.00001
    a = 0.01
    numTimeSteps = 200
    model = FinModelRatesBK(sigma, a, numTimeSteps)

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBK(sigma, a, numTimeSteps)

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

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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
    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.EUROPEAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    exerciseType = FinExerciseTypes.EUROPEAN

    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   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 = FinModelRatesBK(sigma, a, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBK(sigma, a, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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
    ###########################################################################

    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.BERMUDAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    exerciseType = FinExerciseTypes.BERMUDAN

    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   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 = FinModelRatesBK(sigma, a, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBK(sigma, a, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BK PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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
    numTimeSteps = 200
    model = FinModelRatesBDT(sigma, numTimeSteps)

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBDT(sigma, numTimeSteps)

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

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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
    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.EUROPEAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)
   
    testCases.banner("======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BDT MODEL ========")

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

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBDT(sigma, numTimeSteps)

    testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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
    ###########################################################################

    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.BERMUDAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   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 = FinModelRatesBDT(sigma, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesBDT(sigma, numTimeSteps)

#    print("BDT MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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
    numTimeSteps = 200
    model = FinModelRatesHW(sigma, a, numTimeSteps)

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesHW(sigma, a, numTimeSteps)

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

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

    valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, 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
    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.EUROPEAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)
   
    testCases.banner("======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE HW MODEL ========")

    sigma = 0.000001
    model = FinModelRatesHW(sigma, a, numTimeSteps)

    testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesHW(sigma, a, numTimeSteps)

    testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN BDT PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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
    ###########################################################################

    fixedLegType = FinSwapTypes.PAY
    exerciseType = FinExerciseTypes.BERMUDAN

    bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   swapFixedCoupon,
                                                   swapFixedFrequencyType,
                                                   swapFixedDayCountType)

    fixedLegType = FinSwapTypes.RECEIVE
    bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate,
                                                   exerciseDate,
                                                   swapMaturityDate,
                                                   fixedLegType,
                                                   exerciseType,
                                                   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 = FinModelRatesHW(sigma, a, numTimeSteps)

    testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN HW PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, 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 = FinModelRatesHW(sigma, a, numTimeSteps)

    testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE")
    valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN HW PAY VALUE:", valuePay)

    valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model)
    testCases.print("BERMUDAN HW REC VALUE:", valueRec)

    payRec = valuePay - valueRec
    testCases.print("PAY MINUS RECEIVER :", payRec)
Example #7
0
def testFinLiborSwaptionModels():

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

    valuationDate = FinDate(2011, 1, 1)
    liborCurve = test_FinLiborDepositsAndSwaps(valuationDate)

    exerciseDate = FinDate(2012, 1, 1)
    swapMaturityDate = FinDate(2017, 1, 1)

    swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = FinDayCountTypes.ACT_365F

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

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

    model1 = FinModelBlack(0.00001)
    model2 = FinModelBlackShifted(0.00001, 0.0)
    model3 = FinModelSABR(0.013, 0.5, 0.5, 0.5)
    model4 = FinModelSABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
    model5 = FinModelRatesHW(0.00001, 0.00001)
    model6 = FinModelRatesBK(0.01, 0.01)

    settlementDate = valuationDate.addWorkDays(2)

    for k in strikes:
        swaptionType = FinLiborSwapTypes.PAYER
        swaption = FinLiborSwaption(settlementDate, exerciseDate,
                                    swapMaturityDate, swaptionType, k,
                                    swapFixedFrequencyType,
                                    swapFixedDayCountType)

        swap1 = swaption.value(valuationDate, liborCurve, model1)
        swap2 = swaption.value(valuationDate, liborCurve, model2)
        swap3 = swaption.value(valuationDate, liborCurve, model3)
        swap4 = swaption.value(valuationDate, liborCurve, model4)
        swap5 = swaption.value(valuationDate, liborCurve, model5)
        swap6 = swaption.value(valuationDate, liborCurve, 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 = FinLiborSwapTypes.RECEIVER
        swaption = FinLiborSwaption(settlementDate, exerciseDate,
                                    swapMaturityDate, swaptionType, k,
                                    swapFixedFrequencyType,
                                    swapFixedDayCountType)

        swap1 = swaption.value(valuationDate, liborCurve, model1)
        swap2 = swaption.value(valuationDate, liborCurve, model2)
        swap3 = swaption.value(valuationDate, liborCurve, model3)
        swap4 = swaption.value(valuationDate, liborCurve, model4)
        swap5 = swaption.value(valuationDate, liborCurve, model5)
        swap6 = swaption.value(valuationDate, liborCurve, model6)
        testCases.print("REC", k, swap1, swap2, swap3, swap4, swap5, swap6)
Example #8
0
def testFinLiborSwaptionMatlabExamples():

    # 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("=======================================")

    valuationDate = FinDate(1, 1, 2010)
    liborCurve = FinDiscountCurveFlat(valuationDate, 0.06,
                                      FinFrequencyTypes.CONTINUOUS,
                                      FinDayCountTypes.THIRTY_E_360)

    settlementDate = FinDate(1, 1, 2011)
    exerciseDate = FinDate(1, 1, 2016)
    maturityDate = FinDate(1, 1, 2019)

    fixedCoupon = 0.062
    fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    # Pricing a PAYER
    swaptionType = FinLiborSwapTypes.PAYER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional)

    model = FinModelBlack(0.20)
    v_finpy = swaption.value(valuationDate, liborCurve, 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("===================================")

    valuationDate = FinDate(1, 1, 2010)

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

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

    contFreq = FinFrequencyTypes.CONTINUOUS
    interpType = FinInterpTypes.LINEAR_ZERO_RATES
    dayCountType = FinDayCountTypes.THIRTY_E_360

    liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates,
                                       contFreq, dayCountType, interpType)

    settlementDate = FinDate(1, 1, 2011)
    exerciseDate = FinDate(1, 1, 2012)
    maturityDate = FinDate(1, 1, 2017)
    fixedCoupon = 0.03

    fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360
    floatFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    floatDayCountType = FinDayCountTypes.THIRTY_E_360
    notional = 1000.0

    # Pricing a put
    swaptionType = FinLiborSwapTypes.RECEIVER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional,
                                floatFrequencyType, floatDayCountType)

    model = FinModelBlack(0.21)
    v_finpy = swaption.value(valuationDate, liborCurve, 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("===================================")

    valuationDate = FinDate(1, 1, 2016)

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

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

    contFreq = FinFrequencyTypes.ANNUAL
    interpType = FinInterpTypes.LINEAR_ZERO_RATES
    dayCountType = FinDayCountTypes.THIRTY_E_360

    liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates,
                                       contFreq, dayCountType, interpType)

    settlementDate = FinDate(1, 1, 2016)
    exerciseDate = FinDate(1, 1, 2017)
    maturityDate = FinDate(1, 1, 2020)
    fixedCoupon = -0.003

    fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    floatFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    floatDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    notional = 1000.0

    # Pricing a PAYER
    swaptionType = FinLiborSwapTypes.PAYER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional,
                                floatFrequencyType, floatDayCountType)

    model = FinModelBlackShifted(0.31, 0.008)
    v_finpy = swaption.value(valuationDate, liborCurve, 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

    valuationDate = FinDate(1, 1, 2007)

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

    zeroRates = np.array([0.075] * 11)
    interpType = FinInterpTypes.FLAT_FORWARDS
    dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    contFreq = FinFrequencyTypes.SEMI_ANNUAL

    liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates,
                                       contFreq, dayCountType, interpType)

    settlementDate = valuationDate
    exerciseDate = FinDate(1, 1, 2010)
    maturityDate = FinDate(1, 1, 2012)
    fixedCoupon = 0.04

    fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    swaptionType = FinLiborSwapTypes.RECEIVER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional)

    model = FinModelRatesHW(0.05, 0.01)
    v_finpy = swaption.value(valuationDate, liborCurve, 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
    valuationDate = FinDate(1, 1, 2007)

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

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

    interpType = FinInterpTypes.FLAT_FORWARDS
    dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    contFreq = FinFrequencyTypes.SEMI_ANNUAL

    liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates,
                                       contFreq, dayCountType, interpType)

    settlementDate = valuationDate
    exerciseDate = FinDate(1, 1, 2011)
    maturityDate = FinDate(1, 1, 2012)

    fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    model = FinModelRatesBK(0.1, 0.05, 200)

    fixedCoupon = 0.07
    swaptionType = FinLiborSwapTypes.PAYER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional)

    v_finpy = swaption.value(valuationDate, liborCurve, 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)

    fixedCoupon = 0.0725
    swaptionType = FinLiborSwapTypes.RECEIVER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional)

    v_finpy = swaption.value(valuationDate, liborCurve, 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

    valuationDate = FinDate(1, 1, 2007)

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

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

    interpType = FinInterpTypes.FLAT_FORWARDS
    dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    contFreq = FinFrequencyTypes.ANNUAL

    liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates,
                                       contFreq, dayCountType, interpType)

    settlementDate = valuationDate
    exerciseDate = FinDate(1, 1, 2012)
    maturityDate = FinDate(1, 1, 2015)

    fixedFrequencyType = FinFrequencyTypes.ANNUAL
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    fixedCoupon = 0.062
    swaptionType = FinLiborSwapTypes.PAYER
    swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate,
                                swaptionType, fixedCoupon, fixedFrequencyType,
                                fixedDayCountType, notional)

    model = FinModelRatesBDT(0.20, 200)
    v_finpy = swaption.value(valuationDate, liborCurve, 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)
Example #9
0
def test_FinBondOptionZEROVOLConvergence():

    # Build discount curve
    settlementDate = FinDate(1, 9, 2019)
    rate = 0.05
    discountCurve = FinDiscountCurveFlat(settlementDate, rate, FinFrequencyTypes.ANNUAL)

    # Bond details
    issueDate = FinDate(1, 9, 2014)
    maturityDate = FinDate(1, 9, 2025)
    coupon = 0.06
    frequencyType = FinFrequencyTypes.ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)

    # Option Details
    expiryDate = FinDate(1, 12, 2021)
    face = 100.0

    dfExpiry = discountCurve.df(expiryDate)
    fwdCleanValue = bond.cleanPriceFromDiscountCurve(expiryDate, discountCurve)
    fwdFullValue = bond.fullPriceFromDiscountCurve(expiryDate, discountCurve)
    print("BOND FwdCleanBondPx", fwdCleanValue)
    print("BOND FwdFullBondPx", fwdFullValue)
    print("BOND Accrued:", bond._accruedInterest)

    spotCleanValue = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)

    testCases.header("STRIKE", "STEPS",
                     "CALL_INT", "CALL_INT_PV", "CALL_EUR", "CALL_AMER",
                     "PUT_INT", "PUT_INT_PV", "PUT_EUR", "PUT_AMER") 

    numTimeSteps = range(50, 1000, 50)
    strikePrices = [90, 100, 110, 120]

    for strikePrice in strikePrices:
        
        callIntrinsic = max(spotCleanValue - strikePrice, 0)
        putIntrinsic = max(strikePrice - spotCleanValue, 0)
        callIntrinsicPV = max(fwdCleanValue - strikePrice, 0) * dfExpiry
        putIntrinsicPV = max(strikePrice - fwdCleanValue, 0) * dfExpiry

        for numSteps in numTimeSteps:

            sigma = 0.0000001
            a = 0.1
            model = FinModelRatesBK(sigma, a, numSteps)
        
            optionType = FinOptionTypes.EUROPEAN_CALL
            bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face, optionType)    
            v1 = bondOption1.value(settlementDate, discountCurve, model)
    
            optionType = FinOptionTypes.AMERICAN_CALL
            bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face, optionType)   
            v2 = bondOption2.value(settlementDate, discountCurve, model)

            optionType = FinOptionTypes.EUROPEAN_PUT
            bondOption3 = FinBondOption(bond, expiryDate, strikePrice, face, optionType)    
            v3 = bondOption3.value(settlementDate, discountCurve, model)
        
            optionType = FinOptionTypes.AMERICAN_PUT
            bondOption4 = FinBondOption(bond, expiryDate, strikePrice, face, optionType)    
            v4 = bondOption4.value(settlementDate, discountCurve, model)
        
            testCases.print(strikePrice, numSteps,
                            callIntrinsic, callIntrinsicPV, v1, v2,
                            putIntrinsic, putIntrinsicPV, v3, v4)
Example #10
0
def test_FinBondOption():

    settlementDate = FinDate(1, 12, 2019)
    issueDate = FinDate(1, 12, 2018)
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    frequencyType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)

    tmat = (maturityDate - settlementDate) / gDaysInYear
    times = np.linspace(0, tmat, 20)
    dates = settlementDate.addYears(times)
    dfs = np.exp(-0.05*times)
    discountCurve = FinDiscountCurve(settlementDate, dates, dfs)

    expiryDate = settlementDate.addTenor("18m")
    strikePrice = 105.0
    face = 100.0

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

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

    optionType = FinOptionTypes.EUROPEAN_CALL

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

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.print("Fixed Income Price:", price)

    numTimeSteps = 20

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

    for strikePrice in strikes:

        sigma = 0.20
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a, numTimeSteps)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("EUROPEAN CALL - BK", strikePrice, v)

    for strikePrice in strikes:

        sigma = 0.20
        a = 0.05

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a, numTimeSteps)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("EUROPEAN CALL - BK", strikePrice, v)

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

    optionType = FinOptionTypes.AMERICAN_CALL

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.header("LABEL", "VALUE")
    testCases.print("Fixed Income Price:", price)

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

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN CALL - BK", strikePrice, v)

    for strikePrice in strikes:

        sigma = 0.20
        a = 0.05

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN CALL - BK", strikePrice, v)

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

    optionType = FinOptionTypes.EUROPEAN_PUT

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("EUROPEAN PUT - BK", strikePrice, v)

    for strikePrice in strikes:

        sigma = 0.20
        a = 0.05

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("EUROPEAN PUT - BK", strikePrice, v)

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

    optionType = FinOptionTypes.AMERICAN_PUT

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.02
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN PUT - BK", strikePrice, v)

    for strikePrice in strikes:

        sigma = 0.20
        a = 0.05

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType)
        model = FinModelRatesBK(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN PUT - BK", strikePrice, v)
Example #11
0
def test_FinBondOptionAmericanConvergenceTWO():

    # Build discount curve
    settlementDate = FinDate(1, 12, 2019)
    discountCurve = FinDiscountCurveFlat(settlementDate,
                                         0.05,
                                         FinFrequencyTypes.CONTINUOUS)

    # Bond details
    issueDate = FinDate(1, 9, 2014)
    maturityDate = FinDate(1, 9, 2025)
    coupon = 0.05
    frequencyType = FinFrequencyTypes.ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)
    expiryDate = settlementDate.addTenor("18m")
    face = 100.0

    spotValue = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.header("LABEL", "VALUE")
    testCases.print("BOND PRICE", spotValue)

    testCases.header("PERIOD", "N", "EUR_CALL", "AMER_CALL",
                     "EUR_PUT", "AMER_PUT")

    sigma = 0.2
    a = 0.1
    bkModel = FinModelRatesBK(sigma, a)
    K = 101.0

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

    if 1 == 1:
        K = 100.0
        bkModel = FinModelRatesBK(sigma, a, 100)
        europeanCallBondOption = FinBondOption(bond, expiryDate, K, face,
                                               FinOptionTypes.EUROPEAN_CALL)

        v_ec = europeanCallBondOption.value(settlementDate, discountCurve,
                                            bkModel)
        testCases.header("LABEL", "VALUE")
        testCases.print("OPTION", v_ec)

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

    for numSteps in numStepsVector:

        bkModel = FinModelRatesBK(sigma, a, numSteps)

        start = time.time()

        europeanCallBondOption = FinBondOption(bond, expiryDate, K, face,
                                               FinOptionTypes.EUROPEAN_CALL)
        v_ec = europeanCallBondOption.value(settlementDate, discountCurve,
                                            bkModel)

        americanCallBondOption = FinBondOption(bond, expiryDate, K, face,
                                               FinOptionTypes.AMERICAN_CALL)
        v_ac = americanCallBondOption.value(settlementDate, discountCurve,
                                            bkModel)

        europeanPutBondOption = FinBondOption(bond, expiryDate, K, face,
                                              FinOptionTypes.EUROPEAN_PUT)
        v_ep = europeanPutBondOption.value(settlementDate, discountCurve,
                                           bkModel)

        americanPutBondOption = FinBondOption(bond, expiryDate, K, face,
                                              FinOptionTypes.AMERICAN_PUT)
        v_ap = americanPutBondOption.value(settlementDate, discountCurve,
                                           bkModel)

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

        testCases.print(period, numSteps, 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(numStepsVector, vec_ec, label="European Call")
        plt.legend()

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

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

        plt.figure()
        plt.plot(numStepsVector, vec_ap, label="American Put")
        plt.legend()