Example #1
0
def test_FinInterpolatedForwards():

    import matplotlib.pyplot as plt

    tValues = np.array([0.0, 3.0, 5.0, 10.0])
    rValues = np.array([0.04, 0.07, 0.08, 0.09])
    dfValues = np.exp(-tValues*rValues)
    tInterpValues = np.linspace(0.0, 12.0, 200)

    print(tValues)
    print(rValues)
    print(dfValues)

    curveDate = FinDate(2019,1,3)
    for method in FinInterpMethods:

        discountCurve = FinDiscountCurve(curveDate, tValues, dfValues, method)
        dfInterpValues = discountCurve.df(tInterpValues)
        fwdInterpValues = discountCurve.fwd(tInterpValues)
        zeroInterpValues = discountCurve.zeroRate(tInterpValues)

        if PLOT_GRAPHS:
            plt.figure(figsize=(8, 6))
            plt.plot(tValues, dfValues, 'o', color='g', label="DFS:")
            plt.plot(tInterpValues, dfInterpValues, color='r', label="DF:" + str(method))
            plt.legend()
            plt.figure(figsize=(8, 6))
            plt.plot(tInterpValues, fwdInterpValues, color='r', label="FWD:" + str(method))
            plt.plot(tInterpValues, zeroInterpValues, color='b', label="ZERO:" + str(method))
            plt.plot(tValues, rValues, 'o', color='g',  label="ZERO RATES")
            plt.legend()
Example #2
0
def test_FinDiscountCurve():

    startDate = FinDate(2018, 1, 1)
    times = np.linspace(0, 10.0, 10)
    rate = 0.05
    values = np.exp(-rate * times)

    curve = FinDiscountCurve(startDate, times, values,
                             FinInterpMethods.FLAT_FORWARDS)

    testCases.header("T", "DF")

    for t in np.linspace(0, 10, 21):
        df = curve.df(t)
        testCases.print(t, df)
Example #3
0
def test_CDSFastApproximation():

    valueDate = FinDate(2018, 6, 20)
    # I build a discount curve that requires no bootstrap
    times = np.linspace(0, 10.0, 11)
    r = 0.05

    discountFactors = np.power((1.0 + r), -times)
    dates = valueDate.addYears(times)

    liborCurve = FinDiscountCurve(valueDate,
                                  dates,
                                  discountFactors,
                                  FinInterpTypes.FLAT_FWD_RATES)

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

    maturityDate = valueDate.nextCDSDate(120)
    t = (maturityDate - valueDate) / 365.242
    z = liborCurve.df(maturityDate)
    r = -np.log(z) / t

    recoveryRate = 0.40

    contractCoupon = 0.010

    testCases.header("MKT_SPD", "EXACT_VALUE", "APPROX_VALUE", "DIFF(%NOT)")

    for mktCoupon in np.linspace(0.000, 0.05, 21):

        cdsContracts = []

        cdsMkt = FinCDS(valueDate, maturityDate, mktCoupon, ONE_MILLION)

        cdsContracts.append(cdsMkt)

        issuerCurve = FinCDSCurve(valueDate,
                                  cdsContracts,
                                  liborCurve,
                                  recoveryRate)

        cdsContract = FinCDS(valueDate, maturityDate, contractCoupon)
        v_exact = cdsContract.value(
            valueDate, issuerCurve, recoveryRate)['full_pv']
        v_approx = cdsContract.valueFastApprox(
            valueDate, r, mktCoupon, recoveryRate)[0]
        pctdiff = (v_exact - v_approx) / ONE_MILLION * 100.0
        testCases.print(mktCoupon * 10000, v_exact, v_approx, pctdiff)
Example #4
0
def test_BlackKarasinskiExampleTwo():
    # 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)
    expiryDate = settlementDate.addTenor("18m")
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    frequencyType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(maturityDate, coupon, frequencyType, accrualType)

    bond.calculateFlowDates(settlementDate)
    couponTimes = []
    couponFlows = []
    cpn = bond._coupon / bond._frequency
    for flowDate in bond._flowDates:
        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, 20)
    dfs = np.exp(-0.05 * times)
    curve = FinDiscountCurve(settlementDate, times, dfs)

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

    sigma = 0.20
    a = 0.05

    # Test convergence
    numStepsList = [100]  #,101,200,300,400,500,600,700,800,900,1000]
    isAmerican = True

    treeVector = []
    for numTimeSteps in numStepsList:
        start = time.time()
        model = FinModelRatesBlackKarasinski(a, sigma)
        model.buildTree(tmat, int(numTimeSteps), times, dfs)
        v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows,
                             isAmerican)
        end = time.time()
        period = end - start
        treeVector.append(v[0])
        print(numTimeSteps, v, period)
Example #5
0
def test_IssuerCurveBuild():
    ''' Test issuer curve build with simple libor curve to isolate cds
    curve building time cost. '''

    valuationDate = FinDate(20, 6, 2018)

    times = np.linspace(0.0, 10.0, 11)
    r = 0.05
    discountFactors = np.power((1.0 + r), -times)
    dates = valuationDate.addYears(times)
    liborCurve = FinDiscountCurve(valuationDate,
                                  dates,
                                  discountFactors,
                                  FinInterpTypes.FLAT_FWD_RATES)
    recoveryRate = 0.40

    cdsContracts = []

    cdsCoupon = 0.005  # 50 bps
    maturityDate = valuationDate.addMonths(12)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0055
    maturityDate = valuationDate.addMonths(24)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0060
    maturityDate = valuationDate.addMonths(36)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0065
    maturityDate = valuationDate.addMonths(60)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0070
    maturityDate = valuationDate.addMonths(84)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0073
    maturityDate = valuationDate.addMonths(120)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    issuerCurve = FinCDSCurve(valuationDate,
                              cdsContracts,
                              liborCurve,
                              recoveryRate)

    return cdsContracts, issuerCurve
Example #6
0
def test_FinInterpolatedForwards():

    import matplotlib.pyplot as plt

    tValues = np.array([0.0, 3.0, 5.0, 10.0])
    rValues = np.array([0.04, 0.07, 0.08, 0.09])
    dfValues = np.exp(-tValues * rValues)
    tInterpValues = np.linspace(0.0, 12.0, 49)

    curveDate = FinDate(1, 1, 2019)

    tDates = curveDate.addYears(tValues)
    tInterpDates = curveDate.addYears(tInterpValues)

    for interpType in FinInterpTypes:

        discountCurve = FinDiscountCurve(curveDate, tDates, dfValues,
                                         interpType)
        dfInterpValues = discountCurve.df(tInterpDates)
        fwdInterpValues = discountCurve.fwd(tInterpDates)
        zeroInterpValues = discountCurve.zeroRate(tInterpDates)

        if PLOT_GRAPHS:
            plt.figure(figsize=(8, 6))
            plt.plot(tValues, dfValues, 'o', color='g', label="DFS:")
            plt.plot(tInterpValues,
                     dfInterpValues,
                     color='r',
                     label="DF:" + str(interpType))
            plt.legend()
            plt.figure(figsize=(8, 6))
            plt.plot(tInterpValues,
                     fwdInterpValues,
                     color='r',
                     label="FWD:" + str(interpType))
            plt.plot(tInterpValues,
                     zeroInterpValues,
                     color='b',
                     label="ZERO:" + str(interpType))
            plt.plot(tValues, rValues, 'o', color='g', label="ZERO RATES")
            plt.legend()
def test_dp_example():

    #  http://www.derivativepricing.com/blogpage.asp?id=8

    startDate = FinDate(14, 11, 2011)
    endDate = FinDate(14, 11, 2016)
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL
    swapCalendarType = FinCalendarTypes.TARGET
    busDayAdjustType = FinBusDayAdjustTypes.MODIFIED_FOLLOWING
    dateGenRuleType = FinDateGenRuleTypes.BACKWARD
    fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    swapType = FinLiborSwapTypes.PAYER
    fixedCoupon = 0.0124
    notional = ONE_MILLION

    swap = FinLiborSwap(startDate,
                        endDate,
                        swapType,
                        fixedCoupon=fixedCoupon,
                        fixedFreqType=fixedFreqType,
                        fixedDayCountType=fixedDayCountType,
                        floatFreqType=FinFrequencyTypes.SEMI_ANNUAL,
                        floatDayCountType=FinDayCountTypes.ACT_360,
                        notional=notional,
                        calendarType=swapCalendarType,
                        busDayAdjustType=busDayAdjustType,
                        dateGenRuleType=dateGenRuleType)

#    swap.printFixedLegFlows()

    dts = [FinDate(14, 11, 2011), FinDate(14, 5, 2012), FinDate(14, 11, 2012),
           FinDate(14, 5, 2013), FinDate(14, 11, 2013), FinDate(14, 5, 2014),
           FinDate(14, 11, 2014), FinDate(14, 5, 2015), FinDate(16, 11, 2015),
           FinDate(16, 5, 2016), FinDate(14, 11, 2016)]

    dfs = [0.9999843, 0.9966889, 0.9942107, 0.9911884, 0.9880738, 0.9836490,
           0.9786276, 0.9710461, 0.9621778, 0.9514315, 0.9394919]

    valuationDate = startDate

    curve = FinDiscountCurve(valuationDate, dts, np.array(dfs),
                             FinInterpTypes.FLAT_FORWARDS)

    v = swap.value(valuationDate, curve, curve)

#    swap.printFixedLegPV()
#    swap.printFloatLegPV()

    # This is essentially zero
    testCases.header("LABEL", "VALUE")
    testCases.print("Swap Value on a Notional of $1M:", v)
Example #8
0
def test_CurveBuild():

    valuationDate = FinDate(2018, 6, 20)

    times = np.linspace(0.0, 10.0, 10)
    r = 0.05
    discountFactors = np.power((1.0 + r), -times)
    liborCurve = FinDiscountCurve(valuationDate, times, discountFactors,
                                  FinInterpMethods.FLAT_FORWARDS)
    recoveryRate = 0.40

    cdsContracts = []

    cdsCoupon = 0.005  # 50 bps
    maturityDate = valuationDate.addMonths(12)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0055
    maturityDate = valuationDate.addMonths(24)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0060
    maturityDate = valuationDate.addMonths(36)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0065
    maturityDate = valuationDate.addMonths(60)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0070
    maturityDate = valuationDate.addMonths(84)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    cdsCoupon = 0.0073
    maturityDate = valuationDate.addMonths(120)
    cds = FinCDS(valuationDate, maturityDate, cdsCoupon)
    cdsContracts.append(cds)

    issuerCurve = FinCDSCurve(valuationDate, cdsContracts, liborCurve,
                              recoveryRate)

    return cdsContracts, issuerCurve
def test_FinBondOption():

    settlementDate = FinDate(1, 12, 2019)

    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    frequencyType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(maturityDate, coupon, frequencyType, accrualType)

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

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

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

    for strikePrice in [90, 95, 100, 105, 110]:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesHullWhite(a, sigma)
        v = bondOption.value(settlementDate, discountCurve, model)
        print("HW", strikePrice, v)

    for strikePrice in [90, 95, 100, 105, 110]:

        sigma = 0.20
        a = 0.05

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBlackKarasinski(a, sigma)
        v = bondOption.value(settlementDate, discountCurve, model)
        print("BK", strikePrice, v)
Example #10
0
def test_BlackKarasinskiExampleOne():
    # 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)

    startDate = FinDate(1, 12, 2019)
    curve = FinDiscountCurve(startDate, times, dfs)
    endDate = FinDate(1, 12, 2022)
    sigma = 0.25
    a = 0.22
    numTimeSteps = 6
    tmat = (endDate - startDate) / gDaysInYear
    model = FinModelRatesBlackKarasinski(a, sigma)
    model.buildTree(tmat, numTimeSteps, times, dfs)
    printTree(model._Q)
    print("")
    printTree(model._rt)
    print("")
Example #11
0
def test_BDTExampleThree():
    # Valuation of a swaption as in Leif Andersen's paper - see Table 1 on
    # SSRN-id155208.pdf

    testCases.banner("===================== ANDERSEN PAPER ==============")

    # This is a sanity check
    testBlackModelCheck()

    settlementDate = FinDate(1, 1, 2020)
    times = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
    dates = settlementDate.addYears(times)
    rate = 0.06
    dfs = 1.0 / (1.0 + rate / 2.0)**(2.0 * times)
    curve = FinDiscountCurve(settlementDate, dates, dfs)

    coupon = 0.06
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    strikePrice = 100.0
    face = 100.0
    # Andersen paper
    numTimeSteps = 200

    testCases.header("ExerciseType", "Sigma", "NumSteps", "Texp", "Tmat",
                     "V_Fixed", "V_pay", "V_rec")

    for exerciseType in [FinExerciseTypes.EUROPEAN, FinExerciseTypes.BERMUDAN]:

        for maturityYears in [4.0, 5.0, 10.0, 20.0]:

            maturityDate = settlementDate.addYears(maturityYears)
            issueDate = FinDate(maturityDate._d, maturityDate._m, 2000)

            if maturityYears == 4.0 or maturityYears == 5.0:
                sigma = 0.2012
            elif maturityYears == 10.0:
                sigma = 0.1522
            elif maturityYears == 20.0:
                sigma = 0.1035

            for expiryYears in range(
                    int(maturityYears / 2) - 1, int(maturityYears)):

                expiryDate = settlementDate.addYears(expiryYears)

                tmat = (maturityDate - settlementDate) / gDaysInYear
                texp = (expiryDate - settlementDate) / gDaysInYear

                bond = FinBond(issueDate, maturityDate, coupon, freqType,
                               accrualType)

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

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

                price = bond.cleanPriceFromDiscountCurve(settlementDate, curve)

                model = FinModelRatesBDT(sigma, numTimeSteps)
                model.buildTree(tmat, times, dfs)

                v = model.bermudanSwaption(texp, tmat, strikePrice, face,
                                           couponTimes, couponFlows,
                                           exerciseType)

                testCases.print("%s" % exerciseType, "%9.5f" % sigma,
                                "%9.5f" % numTimeSteps, "%9.5f" % expiryYears,
                                "%9.5f" % maturityYears, "%9.5f" % price,
                                "%9.2f" % (v['pay'] * 100.0),
                                "%9.2f" % (v['rec'] * 100.0))
Example #12
0
def test_BDTExampleTwo():
    # Valuation of a European option on a coupon bearing bond
    # This follows example in Fig 28.11 of John Hull's book (6th Edition)
    # but does not have the exact same dt so there are some differences

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

    settlementDate = FinDate(1, 12, 2019)
    issueDate = FinDate(1, 12, 2015)
    expiryDate = settlementDate.addTenor("18m")
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, freqType, 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)

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

    curve = FinDiscountCurve(settlementDate, dates, dfs)

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

    sigma = 0.20

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

    testCases.header("Values")
    treeVector = []
    for numTimeSteps in numStepsList:
        model = FinModelRatesBDT(sigma, numTimeSteps)
        model.buildTree(tmat, times, dfs)
        v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows,
                             exerciseType)

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

    if PLOT_GRAPHS:
        plt.plot(numStepsList, treeVector)

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

    if 1 == 0:
        print("RT")
        printTree(model._rt, 5)
        print("Q")
        printTree(model._Q, 5)
Example #13
0
def test_FinBondOption():

    settlementDate = FinDate(1, 12, 2019)
    issueDate = FinDate(1, 12, 2018)
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, freqType, 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, 90, 100, 110, 120]

    optionType = FinOptionTypes.EUROPEAN_CALL

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

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

    numTimeSteps = 100

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

    for strikePrice in strikes:

        sigma = 0.20

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

    for strikePrice in strikes:

        sigma = 0.20

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBDT(sigma, 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.20

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

    for strikePrice in strikes:

        sigma = 0.20

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBDT(sigma, numTimeSteps)
        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

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

    for strikePrice in strikes:

        sigma = 0.20

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBDT(sigma, numTimeSteps)
        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

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

    for strikePrice in strikes:

        sigma = 0.20

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBDT(sigma, numTimeSteps)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN PUT - BK", strikePrice, v)
def test_FinDiscountCurve():

    # Create a curve from times and discount factors
    startDate = FinDate(1, 1, 2018)
    years = np.linspace(0, 10, 6)
    rate = 0.05 + 0.005*years - 0.0003*years*years
    dfs = np.exp(-rate * years)
    dates = startDate.addYears(years)

    curve = FinDiscountCurve(startDate, dates, dfs, FinInterpTypes.FLAT_FORWARDS)

    testCases.header("T", "DF", "ZERORATE", "CC_FWD", "MM_FWD", "SURVPROB")

    plotYears = np.linspace(0, 12, 12*12+1)
    plotDates = startDate.addYears(plotYears)

    # Examine dependency of curve on compounding rate
    zeroRates_A = curve.zeroRate(plotDates, FinFrequencyTypes.ANNUAL)
    zeroRates_S = curve.zeroRate(plotDates, FinFrequencyTypes.SEMI_ANNUAL)
    zeroRates_Q = curve.zeroRate(plotDates, FinFrequencyTypes.QUARTERLY)
    zeroRates_M = curve.zeroRate(plotDates, FinFrequencyTypes.MONTHLY)
    zeroRates_C = curve.zeroRate(plotDates, FinFrequencyTypes.CONTINUOUS)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(plotYears, scale(zeroRates_A, 100), label='A')
        plt.plot(plotYears, scale(zeroRates_S, 100), label='S')
        plt.plot(plotYears, scale(zeroRates_Q, 100), label='Q')
        plt.plot(plotYears, scale(zeroRates_M, 100), label='M')
        plt.plot(plotYears, scale(zeroRates_C, 100), label='C')
        plt.ylim((5, 8))

        plt.title('Discount Curves')
        plt.xlabel('Time (years)')
        plt.ylabel('Zero Rate (%)')
        plt.legend(loc='lower right', frameon=False)

    # Examine dependency of fwd curve on the interpolation scheme

    for interp in FinInterpTypes:

        curve = FinDiscountCurve(startDate, dates, dfs, interp)
        fwdRates = curve.fwd(plotDates)
        zeroRates = curve.zeroRate(plotDates, FinFrequencyTypes.ANNUAL)
        parRates = curve.swapRate(startDate, plotDates, FinFrequencyTypes.ANNUAL)

        if PLOT_GRAPHS:
            plt.figure(figsize=(6, 4))
            plt.plot(plotYears, scale(fwdRates, 100), label='FWD RATES')
            plt.plot(plotYears, scale(zeroRates, 100), label='ZERO RATES')
            plt.plot(plotYears, scale(parRates, 100), label='PAR RATES')
            plt.ylim((3.0, 8.5))

            plt.title('Forward Curves using ' + str(interp))
            plt.xlabel('Time (years)')
            plt.ylabel('Fwd Rate (%)')
            plt.legend(loc='lower right', frameon=False)
Example #15
0
def test_HullWhiteCallableBond():
    # Valuation of a European option on a coupon bearing bond

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

    bond.calculateFlowDates(settlementDate)
    couponTimes = []
    couponFlows = []
    cpn = bond._coupon / bond._frequency
    for flowDate in bond._flowDates[1:]:
        flowTime = (flowDate - settlementDate) / gDaysInYear
        couponTimes.append(flowTime)
        couponFlows.append(cpn)
    couponTimes = np.array(couponTimes)
    couponFlows = np.array(couponFlows)

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

    callDates = []
    callPrices = []
    callPx = 120.0
    callDates.append(settlementDate.addTenor("5Y"))
    callPrices.append(callPx)
    callDates.append(settlementDate.addTenor("6Y"))
    callPrices.append(callPx)
    callDates.append(settlementDate.addTenor("7Y"))
    callPrices.append(callPx)
    callDates.append(settlementDate.addTenor("8Y"))
    callPrices.append(callPx)

    callTimes = []
    for dt in callDates:
        t = (dt - settlementDate) / gDaysInYear
        callTimes.append(t)

    putDates = []
    putPrices = []
    putPx = 98.0
    putDates.append(settlementDate.addTenor("5Y"))
    putPrices.append(putPx)
    putDates.append(settlementDate.addTenor("6Y"))
    putPrices.append(putPx)
    putDates.append(settlementDate.addTenor("7Y"))
    putPrices.append(putPx)
    putDates.append(settlementDate.addTenor("8Y"))
    putPrices.append(putPx)

    putTimes = []
    for dt in putDates:
        t = (dt - settlementDate) / gDaysInYear
        putTimes.append(t)

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

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

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

    v1 = bond.fullPriceFromDiscountCurve(settlementDate, curve)

    sigma = 0.02  # basis point volatility
    a = 0.1

    # Test convergence
    numStepsList = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
    tmat = (maturityDate - settlementDate) / gDaysInYear

    print("NUMSTEPS", "BOND_ONLY", "CALLABLE_BOND", "TIME")

    for numTimeSteps in numStepsList:
        start = time.time()
        model = FinModelRatesHullWhite(a, sigma)
        model.buildTree(tmat, numTimeSteps, times, dfs)

        v2 = model.callablePuttableBond_Tree(couponTimes, couponFlows,
                                             callTimes, callPrices, putTimes,
                                             putPrices)

        end = time.time()
        period = end - start
        print(numTimeSteps, v1, v2, period)

    if 1 == 0:
        print("RT")
        printTree(model._rt, 5)
        print("BOND")
        printTree(model._bondValues, 5)
        print("OPTION")
        printTree(model._optionValues, 5)
def test_FinBondOption():

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

    times = np.linspace(0, 10.0, 21)
    dfs = np.exp(-0.05 * times)
    dates = settlementDate.addYears(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.cleanPriceFromDiscountCurve(settlementDate, discountCurve)
    testCases.print("Fixed Income Price:", price)

    numTimeSteps = 100

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

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)

        model = FinModelRatesHW(sigma, a, numTimeSteps)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print(strikePrice, v)

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

    optionType = FinOptionTypes.AMERICAN_CALL

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

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

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)

        model = FinModelRatesHW(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print(strikePrice, v)

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

    optionType = FinOptionTypes.EUROPEAN_PUT
    testCases.banner("HW EUROPEAN PUT")
    testCases.header("STRIKE", "VALUE")

    price = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)

        model = FinModelRatesHW(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print(strikePrice, v)

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

    optionType = FinOptionTypes.AMERICAN_PUT
    testCases.banner("HW AMERICAN PUT")
    testCases.header("STRIKE", "VALUE")

    price = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.02
        a = 0.1

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)

        model = FinModelRatesHW(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print(strikePrice, v)
Example #17
0
def test_FinDiscountCurves():

    # Create a curve from times and discount factors
    valuationDate = FinDate(1, 1, 2018)
    years = [1.0, 2.0, 3.0, 4.0, 5.0]
    dates = valuationDate.addYears(years)
    years2 = []

    for dt in dates:
        y = (dt - valuationDate) / gDaysInYear
        years2.append(y)

    rates = np.array([0.05, 0.06, 0.065, 0.07, 0.075])
    discountFactors = np.exp(-np.array(rates) * np.array(years2))
    curvesList = []

    finDiscountCurve = FinDiscountCurve(valuationDate, dates, discountFactors,
                                        FinInterpTypes.FLAT_FORWARDS)
    curvesList.append(finDiscountCurve)

    finDiscountCurveFlat = FinDiscountCurveFlat(valuationDate, 0.05)
    curvesList.append(finDiscountCurveFlat)

    finDiscountCurveNS = FinDiscountCurveNS(valuationDate, 0.0305, -0.01, 0.08,
                                            10.0)
    curvesList.append(finDiscountCurveNS)

    finDiscountCurveNSS = FinDiscountCurveNSS(valuationDate, 0.035, -0.02,
                                              0.09, 0.1, 1.0, 2.0)
    curvesList.append(finDiscountCurveNSS)

    finDiscountCurvePoly = FinDiscountCurvePoly(valuationDate,
                                                [0.05, 0.002, -0.00005])
    curvesList.append(finDiscountCurvePoly)

    finDiscountCurvePWF = FinDiscountCurvePWF(valuationDate, dates, rates)
    curvesList.append(finDiscountCurvePWF)

    finDiscountCurvePWL = FinDiscountCurvePWL(valuationDate, dates, rates)
    curvesList.append(finDiscountCurvePWL)

    finDiscountCurveZeros = FinDiscountCurveZeros(valuationDate, dates, rates)
    curvesList.append(finDiscountCurveZeros)

    curveNames = []
    for curve in curvesList:
        curveNames.append(type(curve).__name__)

    testCases.banner("SINGLE CALLS NO VECTORS")
    testCases.header("CURVE", "DATE", "ZERO", "DF", "CCFWD", "MMFWD", "SWAP")

    years = np.linspace(1, 10, 10)
    fwdMaturityDates = valuationDate.addYears(years)

    testCases.banner("######################################################")
    testCases.banner("SINGLE CALLS")
    testCases.banner("######################################################")

    for name, curve in zip(curveNames, curvesList):
        for fwdMaturityDate in fwdMaturityDates:
            tenor = "3M"
            zeroRate = curve.zeroRate(fwdMaturityDate)
            fwd = curve.fwd(fwdMaturityDate)
            fwdRate = curve.fwdRate(fwdMaturityDate, tenor)
            swapRate = curve.swapRate(valuationDate, fwdMaturityDate)
            df = curve.df(fwdMaturityDate)

            testCases.print("%-20s" % name, "%-12s" % fwdMaturityDate,
                            "%7.6f" % (zeroRate), "%8.7f" % (df),
                            "%7.6f" % (fwd), "%7.6f" % (fwdRate),
                            "%7.6f" % (swapRate))

    # Examine vectorisation
    testCases.banner("######################################################")
    testCases.banner("VECTORISATIONS")
    testCases.banner("######################################################")

    for name, curve in zip(curveNames, curvesList):
        tenor = "3M"
        zeroRate = curve.zeroRate(fwdMaturityDates)
        fwd = curve.fwd(fwdMaturityDates)
        fwdRate = curve.fwdRate(fwdMaturityDates, tenor)
        swapRate = curve.swapRate(valuationDate, fwdMaturityDates)
        df = curve.df(fwdMaturityDates)

        for i in range(0, len(fwdMaturityDates)):
            testCases.print("%-20s" % name, "%-12s" % fwdMaturityDate,
                            "%7.6f" % (zeroRate[i]), "%8.7f" % (df[i]),
                            "%7.6f" % (fwd[i]), "%7.6f" % (fwdRate[i]),
                            "%7.6f" % (swapRate[i]))

    if PLOT_GRAPHS:

        years = np.linspace(0, 10, 121)
        years2 = years + 1.0
        fwdDates = valuationDate.addYears(years)
        fwdDates2 = valuationDate.addYears(years2)

        plt.figure()
        for name, curve in zip(curveNames, curvesList):
            zeroRates = curve.zeroRate(fwdDates)
            plt.plot(years, zeroRates, label=name)
        plt.legend()
        plt.title("Zero Rates")

        plt.figure()
        for name, curve in zip(curveNames, curvesList):
            fwdRates = curve.fwd(fwdDates)
            plt.plot(years, fwdRates, label=name)
        plt.legend()
        plt.title("CC Fwd Rates")

        plt.figure()
        for name, curve in zip(curveNames, curvesList):
            fwdRates = curve.fwdRate(fwdDates, fwdDates2)
            plt.plot(years, fwdRates, label=name)
        plt.legend()
        plt.title("CC Fwd Rates")

        plt.figure()
        for name, curve in zip(curveNames, curvesList):
            dfs = curve.df(fwdDates)
            plt.plot(years, dfs, label=name)
        plt.legend()
        plt.title("Discount Factors")
Example #18
0
def test_HullWhiteBondOption():
    # Valuation of a European option on a coupon bearing bond

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

    bond.calculateFlowDates(settlementDate)
    couponTimes = []
    couponFlows = []
    cpn = bond._coupon / bond._frequency
    for flowDate in bond._flowDates[1:]:
        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
    times = np.linspace(0, tmat, 20)
    dfs = np.exp(-0.05 * times)
    curve = FinDiscountCurve(settlementDate, times, dfs)

    price = bond.fullPriceFromDiscountCurve(settlementDate, curve)
    print("Spot Bond Price:", price)

    price = bond.fullPriceFromDiscountCurve(expiryDate, curve)
    print("Fwd Bond Price:", price)

    sigma = 0.01
    a = 0.1

    # Test convergence
    numStepsList = [100, 200, 300, 400, 500]
    texp = (expiryDate - settlementDate) / gDaysInYear

    print("NUMSTEPS", "FAST TREE", "FULLTREE", "TIME")

    for numTimeSteps in numStepsList:
        start = time.time()
        model = FinModelRatesHullWhite(a, sigma)
        model.buildTree(texp, numTimeSteps, times, dfs)

        americanExercise = False
        v1 = model.americanBondOption_Tree(texp, strikePrice, face,
                                           couponTimes, couponFlows,
                                           americanExercise)

        v2 = model.europeanBondOption_Tree(texp, strikePrice, face,
                                           couponTimes, couponFlows)

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

        print(numTimeSteps, v1, v2, period)

#    plt.plot(numStepsList, treeVector)

    if 1 == 0:
        print("RT")
        printTree(model._rt, 5)
        print("BOND")
        printTree(model._bondValues, 5)
        print("OPTION")
        printTree(model._optionValues, 5)

    v = model.europeanBondOption_Jamshidian(texp, strikePrice, face,
                                            couponTimes, couponFlows, times,
                                            dfs)

    print("EUROPEAN BOND JAMSHIDIAN DECOMP", v)