Exemplo n.º 1
0
def test_FinDateTenors():

    startDate = FinDate(2018, 2, 23)

    tenor = "5d"
    print(tenor, startDate.addTenor(tenor))

    tenor = "7D"
    print(tenor, startDate.addTenor(tenor))

    tenor = "1W"
    print(tenor, startDate.addTenor(tenor))

    tenor = "4W"
    print(tenor, startDate.addTenor(tenor))

    tenor = "1M"
    print(tenor, startDate.addTenor(tenor))

    tenor = "24M"
    print(tenor, startDate.addTenor(tenor))

    tenor = "2Y"
    print(tenor, startDate.addTenor(tenor))

    tenor = "10y"
    print(tenor, startDate.addTenor(tenor))

    tenor = "0m"
    print(tenor, startDate.addTenor(tenor))

    tenor = "20Y"
    print(tenor, startDate.addTenor(tenor))
Exemplo n.º 2
0
def test_FinDateTenors():

    startDate = FinDate(23, 2, 2018)

    testCases.header("TENOR", "DATE")
    tenor = "5d"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "7D"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "1W"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "4W"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "1M"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "24M"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "2Y"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "10y"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "0m"
    testCases.print(tenor, startDate.addTenor(tenor))

    tenor = "20Y"
    testCases.print(tenor, startDate.addTenor(tenor))
Exemplo n.º 3
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)
Exemplo n.º 4
0
def test_HullWhiteExampleTwo():
    # HULL BOOK ZERO COUPON BOND EXAMPLE 28.1 SEE TABLE 28.3
    # Replication may not be exact as I am using dates rather than times

    zeroDays = [
        0, 3, 31, 62, 94, 185, 367, 731, 1096, 1461, 1826, 2194, 2558, 2922,
        3287, 3653
    ]

    zeroRates = [
        5.0, 5.01772, 4.98282, 4.97234, 4.96157, 4.99058, 5.09389, 5.79733,
        6.30595, 6.73464, 6.94816, 7.08807, 7.27527, 7.30852, 7.39790, 7.49015
    ]

    times = np.array(zeroDays) / 365.0
    zeros = np.array(zeroRates) / 100.0
    dfs = np.exp(-zeros * times)

    startDate = FinDate(1, 12, 2019)
    sigma = 0.01
    a = 0.1
    strike = 63.0
    face = 100.0

    expiryDate = startDate.addTenor("3Y")
    maturityDate = startDate.addTenor("9Y")

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

    model = FinHullWhiteRateModel(a, sigma)
    vAnal = model.optionOnZeroCouponBond(texp, tmat, strike, face, times, dfs)

    # Test convergence
    numStepsList = range(100, 500, 10)
    analVector = []
    treeVector = []

    for numTimeSteps in numStepsList:
        start = time.time()
        model.buildTree(texp, numTimeSteps, times, dfs)
        vTree = model.optionOnZeroCouponBond_Tree(texp, tmat, strike, face)
        end = time.time()
        period = end - start
        treeVector.append(vTree[1])
        analVector.append(vAnal[1])
        print(numTimeSteps, vTree, vAnal, period)

    plt.plot(numStepsList, treeVector)
    plt.plot(numStepsList, analVector)
Exemplo n.º 5
0
def test_FinBondMortgage():

    principal = 130000
    startDate = FinDate(23, 2, 2018)
    endDate = startDate.addTenor("10Y")
    mortgage = FinBondMortgage(startDate, endDate, principal)

    rate = 0.035
    mortgage.generateFlows(rate, FinBondMortgageTypes.REPAYMENT)

    numFlows = len(mortgage._schedule._adjustedDates)

    testCases.header("PAYMENT DATE", "INTEREST", "PRINCIPAL", "OUTSTANDING",
                     "TOTAL")

    for i in range(0, numFlows):
        testCases.print(mortgage._schedule._adjustedDates[i],
                        mortgage._interestFlows[i],
                        mortgage._principalFlows[i],
                        mortgage._principalRemaining[i],
                        mortgage._totalFlows[i])

    mortgage.generateFlows(rate, FinBondMortgageTypes.INTEREST_ONLY)

    testCases.header("PAYMENT DATE", "INTEREST", "PRINCIPAL", "OUTSTANDING",
                     "TOTAL")

    for i in range(0, numFlows):
        testCases.print(mortgage._schedule._adjustedDates[i],
                        mortgage._interestFlows[i],
                        mortgage._principalFlows[i],
                        mortgage._principalRemaining[i],
                        mortgage._totalFlows[i])
Exemplo n.º 6
0
def test_FinScheduleAlignmentEff31():
    ''' EOM schedule so all unadjusted dates fall on month end.'''

    eomFlag = True
    valuationDate = FinDate(29, 7, 2006)
    effDate = valuationDate.addTenor("2D")
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    busDayAdjustType = FinBusDayAdjustTypes.MODIFIED_FOLLOWING
    dateGenRuleType = FinDateGenRuleTypes.BACKWARD
    calendarType = FinCalendarTypes.UNITED_STATES
    adjustTerminationDate = True

    matDate1 = effDate.addTenor("4Y")
    matDate2 = effDate.addTenor("50Y")

    #    print(matDate1, matDate2)

    sched1 = FinSchedule(effDate, matDate1, freqType, calendarType,
                         busDayAdjustType, dateGenRuleType,
                         adjustTerminationDate, eomFlag)

    sched2 = FinSchedule(effDate, matDate2, freqType, calendarType,
                         busDayAdjustType, dateGenRuleType,
                         adjustTerminationDate, eomFlag)

    #    print(sched1._adjustedDates)
    #    print(sched2._adjustedDates[:len(sched1._adjustedDates)])

    compare = (sched1._adjustedDates[-1] == sched2._adjustedDates[
        len(sched1._adjustedDates) - 1])
    assert (compare == True)
Exemplo n.º 7
0
def test_FinScheduleAlignmentLeapYearNotEOM():
    ''' Effective date on leap year. Not EOM. '''

    eomFlag = False

    valuationDate = FinDate(26, 2, 2006)
    effDate = valuationDate.addTenor("2D")
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    busDayAdjustType = FinBusDayAdjustTypes.MODIFIED_FOLLOWING
    dateGenRuleType = FinDateGenRuleTypes.BACKWARD
    calendarType = FinCalendarTypes.UNITED_STATES
    adjustTerminationDate = True

    matDate1 = effDate.addTenor("4Y")
    matDate2 = effDate.addTenor("50Y")

    #    print(matDate1, matDate2)

    sched1 = FinSchedule(effDate, matDate1, freqType, calendarType,
                         busDayAdjustType, dateGenRuleType,
                         adjustTerminationDate, eomFlag)

    sched2 = FinSchedule(effDate, matDate2, freqType, calendarType,
                         busDayAdjustType, dateGenRuleType,
                         adjustTerminationDate, eomFlag)

    #    print(sched1._adjustedDates)
    #    print(sched2._adjustedDates[:len(sched1._adjustedDates)])

    compare = (sched1._adjustedDates[-1] == sched2._adjustedDates[
        len(sched1._adjustedDates) - 1])
    assert (compare == True)
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
def test_FinBondMortgage():

    principal = 130000
    startDate = FinDate(23, 2, 2018)
    endDate = startDate.addTenor("10Y")
    mortgage = FinBondMortgage(startDate, endDate, principal)

    rate = 0.035
    mortgage.generateFlows(rate, FinBondMortgageType.REPAYMENT)
    mortgage.print()

    mortgage.generateFlows(rate, FinBondMortgageType.INTEREST_ONLY)
    mortgage.print()
Exemplo n.º 10
0
def test_FinScheduleAlignment(eomFlag):
        
    valuationDate = FinDate(29, 3, 2005)
    effDate = valuationDate.addTenor("2d")
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    busDayAdjustType = FinBusDayAdjustTypes.MODIFIED_FOLLOWING
    dateGenRuleType = FinDateGenRuleTypes.BACKWARD
    calendarType = FinCalendarTypes.UNITED_STATES
    adjustTerminationDate = False

    matDate1 = effDate.addTenor("4Y")
    matDate2 = effDate.addTenor("50Y")

#    print(matDate1)
#    print(matDate2)

    myCal = FinCalendar(calendarType)

    adjustedMatDate1 = myCal.adjust(matDate1, busDayAdjustType)
    adjustedMatDate2 = myCal.adjust(matDate2, busDayAdjustType)

#    print(adjustedMatDate1)
#    print(adjustedMatDate2)
    
    sched1 = FinSchedule(effDate,
                         adjustedMatDate1,
                         freqType,
                         calendarType,
                         busDayAdjustType,
                         dateGenRuleType,
                         adjustTerminationDate, 
                         eomFlag)
    
#    print(sched1)
    
    sched2 = FinSchedule(effDate,
                         adjustedMatDate2,
                         freqType,
                         calendarType,
                         busDayAdjustType,
                         dateGenRuleType,
                         adjustTerminationDate, 
                         eomFlag)

    compare = (sched1._adjustedDates[-1] == sched2._adjustedDates[len(sched1._adjustedDates)-1])
    assert(compare == eomFlag)
Exemplo n.º 11
0
def test_HullWhiteCallableBond():
    # Valuation of a European option on a coupon bearing bond

    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)

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

    for flowDate in bond._flowDates[1:]:

        if flowDate > settlementDate:
            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("2Y"))
    callPrices.append(callPx)
    callDates.append(settlementDate.addTenor("3Y"))
    callPrices.append(callPx)
    callDates.append(settlementDate.addTenor("4Y"))
    callPrices.append(callPx)
    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("2Y"))
    putPrices.append(putPx)
    putDates.append(settlementDate.addTenor("3Y"))
    putPrices.append(putPx)
    putDates.append(settlementDate.addTenor("4Y"))
    putPrices.append(putPx)
    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
    curve = FinDiscountCurveFlat(settlementDate, 0.05,
                                 FinFrequencyTypes.CONTINUOUS)

    dfs = []
    times = []

    for dt in bond._flowDates:
        if dt > settlementDate:
            t = (dt - settlementDate) / gDaysInYear
            df = curve.df(dt)
            times.append(t)
            dfs.append(df)

    dfs = np.array(dfs)
    times = np.array(times)

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

    v1 = bond.cleanPriceFromDiscountCurve(settlementDate, curve)

    sigma = 0.02  # basis point volatility
    a = 0.01

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

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

    for numTimeSteps in numStepsList:

        start = time.time()
        model = FinModelRatesHW(sigma, a, numTimeSteps)
        model.buildTree(tmat, times, dfs)

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

        end = time.time()
        period = end - start
        testCases.print(numTimeSteps, v1, v2, period)
Exemplo n.º 12
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)
Exemplo n.º 13
0
def testFinLiborCashSettledSwaption():

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

    valuationDate = FinDate(1, 1, 2020)
    settlementDate = FinDate(1, 1, 2020)

    depoDCCType = FinDayCountTypes.THIRTY_E_360_ISDA
    depos = []
    depo = FinLiborDeposit(settlementDate, "1W", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "1M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "3M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "6M", 0.0023, depoDCCType)
    depos.append(depo)

    # No convexity correction provided so I omit interest rate futures

    settlementDate = FinDate(2, 1, 2020)

    swaps = []
    accType = FinDayCountTypes.ACT_365F
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL
    swapType = FinLiborSwapTypes.PAYER

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

    liborCurve = FinLiborCurve(valuationDate, depos, [], swaps,
                               FinInterpTypes.LINEAR_ZERO_RATES)

    exerciseDate = settlementDate.addTenor("5Y")
    swapMaturityDate = exerciseDate.addTenor("5Y")
    swapFixedCoupon = 0.040852
    swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    swapFloatFrequencyType = FinFrequencyTypes.QUARTERLY
    swapFloatDayCountType = FinDayCountTypes.ACT_360
    swapNotional = 1000000
    swaptionType = FinLiborSwapTypes.PAYER

    swaption = FinLiborSwaption(settlementDate, exerciseDate, swapMaturityDate,
                                swaptionType, swapFixedCoupon,
                                swapFixedFrequencyType, swapFixedDayCountType,
                                swapNotional, swapFloatFrequencyType,
                                swapFloatDayCountType)

    model = FinModelBlack(0.1533)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print("Swaption No-Arb Value:", v)

    fwdSwapRate = liborCurve.swapRate(valuationDate, swapMaturityDate,
                                      swapFixedFrequencyType,
                                      swapFixedDayCountType)

    testCases.print("Fwd Swap Rate:", fwdSwapRate)

    model = FinModelBlack(0.1533)

    v = swaption.cashSettledValue(valuationDate, liborCurve, fwdSwapRate,
                                  model)

    testCases.print("Swaption Cash Settled Value:", v)
Exemplo n.º 14
0
def test_FinLiborSwaptionQLExample():

    #   valuationDate = FinDate(28, 2, 2014)
    settlementDate = FinDate(4, 3, 2014)

    depoDCCType = FinDayCountTypes.THIRTY_E_360_ISDA
    depos = []
    depo = FinLiborDeposit(settlementDate, "1W", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "1M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "3M", 0.0023, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "6M", 0.0023, depoDCCType)
    depos.append(depo)

    # No convexity correction provided so I omit interest rate futures

    swaps = []
    accType = FinDayCountTypes.ACT_365F
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL
    swapType = FinLiborSwapTypes.PAYER

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

    liborCurve = FinLiborCurve(settlementDate, depos, [], swaps,
                               FinInterpTypes.LINEAR_ZERO_RATES)

    exerciseDate = settlementDate.addTenor("5Y")
    swapMaturityDate = exerciseDate.addTenor("5Y")
    swapFixedCoupon = 0.040852
    swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    swapFloatFrequencyType = FinFrequencyTypes.QUARTERLY
    swapFloatDayCountType = FinDayCountTypes.ACT_360
    swapNotional = 1000000
    swaptionType = FinLiborSwapTypes.PAYER

    swaption = FinLiborSwaption(settlementDate, exerciseDate, swapMaturityDate,
                                swaptionType, swapFixedCoupon,
                                swapFixedFrequencyType, swapFixedDayCountType,
                                swapNotional, swapFloatFrequencyType,
                                swapFloatDayCountType)

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

    model = FinModelBlack(0.1533)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print(model.__class__, v)

    model = FinModelBlackShifted(0.1533, -0.008)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print(model.__class__, v)

    model = FinModelSABR(0.132, 0.5, 0.5, 0.5)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print(model.__class__, v)

    model = FinModelSABRShifted(0.352, 0.5, 0.15, 0.15, -0.005)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print(model.__class__, v)

    model = FinModelRatesHW(0.010000000, 0.00000000001)
    v = swaption.value(settlementDate, liborCurve, model)
    testCases.print(model.__class__, v)
Exemplo n.º 15
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)
Exemplo n.º 16
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)

    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)
Exemplo n.º 17
0
def test_FinBondOptionZEROVOLConvergence():

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

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

    # Option Details
    expiryDate = settlementDate.addTenor("18m")  # FinDate(1, 12, 2021)
    #    print("EXPIRY:", expiryDate)
    face = 100.0

    dfExpiry = discountCurve.df(expiryDate)
    spotCleanValue = bond.cleanPriceFromDiscountCurve(settlementDate,
                                                      discountCurve)
    fwdCleanValue = bond.cleanPriceFromDiscountCurve(expiryDate, discountCurve)
    #    print("BOND SpotCleanBondPx", spotCleanValue)
    #    print("BOND FwdCleanBondPx", fwdCleanValue)
    #    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(100, 1000, 200)
    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
            model = FinModelRatesBDT(sigma, 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)
Exemplo n.º 18
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
    freqType = FinFrequencyTypes.ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType)
    expiryDate = settlementDate.addTenor("18m")
    face = 100.0

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

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

    sigma = 0.2
    model = FinModelRatesBDT(sigma)
    K = 101.0

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

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

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

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

    for numSteps in numStepsVector:

        bkModel = FinModelRatesBDT(sigma, 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()
Exemplo n.º 19
0
def test_HullWhiteBondOption():
    # Valuation of a European option on a coupon bearing bond

    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 ncd > settlementDate:

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

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

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

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

    sigma = 0.0000001
    a = 0.1
    model = FinModelRatesHW(sigma, a, None)

    #  Test convergence
    numStepsList = range(20, 500, 10)
    texp = (expiryDate - settlementDate) / gDaysInYear

    vJam = model.europeanBondOptionJamshidian(texp, strikePrice, face,
                                              couponTimes, couponFlows, times,
                                              dfs)

    testCases.banner(
        "Pricing bond option on tree that goes to bond maturity and one using european bond option tree that goes to expiry."
    )

    testCases.header("NUMSTEPS", "EXPIRY_ONLY", "EXPIRY_TREE", "JAMSHIDIAN",
                     "TIME")

    for numTimeSteps in numStepsList:

        start = time.time()
        model = FinModelRatesHW(sigma, a, numTimeSteps,
                                FinHWEuropeanCalcType.EXPIRY_ONLY)
        model.buildTree(texp, times, dfs)

        exerciseType = FinOptionExerciseTypes.EUROPEAN

        v1 = model.bondOption(texp, strikePrice, face, couponTimes,
                              couponFlows, exerciseType)

        model = FinModelRatesHW(sigma, a, numTimeSteps,
                                FinHWEuropeanCalcType.EXPIRY_TREE)
        model.buildTree(texp, times, dfs)

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

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

        testCases.print(numTimeSteps, v1, v2, vJam, 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)
Exemplo n.º 20
0
print("ADD WORKDAYS")
print(dt1, dt1.addWorkDays(2))

# The weekend has now been skipped
# To add a month do

print("ADD MONTHS")
print(dt1, dt1.addMonths(2))

# An invalid date will throw an error
# dt5 = FinDate(2019, 1, 31)
# print(dt5)

# You can use tenors - a number and a 'd', 'm' or 'y' in upper or lower case
print("TENORS")
print(dt1.addTenor("1d"))
print(dt1.addTenor("2D"))
print(dt1.addTenor("3M"))
print(dt1.addTenor("4m"))
print(dt1.addTenor("5Y"))
print(dt1.addTenor("6y"))

# You can subtract dates
print("SUBTRACT DATES")
dt6 = dt1.addTenor("5Y")
dt7 = dt1.addTenor("10Y")
dd = dt7 - dt6
print(dt6, dt7, dd)

# check if a date is on a weekend
print("WEEKEND TEST")
Exemplo n.º 21
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)
Exemplo n.º 22
0
def test_HullWhiteExampleTwo():
    # HULL BOOK ZERO COUPON BOND EXAMPLE 28.1 SEE TABLE 28.3
    # Replication may not be exact as I am using dates rather than times

    zeroDays = [
        0, 3, 31, 62, 94, 185, 367, 731, 1096, 1461, 1826, 2194, 2558, 2922,
        3287, 3653
    ]

    zeroRates = [
        5.0, 5.01772, 4.98282, 4.97234, 4.96157, 4.99058, 5.09389, 5.79733,
        6.30595, 6.73464, 6.94816, 7.08807, 7.27527, 7.30852, 7.39790, 7.49015
    ]

    times = np.array(zeroDays) / 365.0
    zeros = np.array(zeroRates) / 100.0
    dfs = np.exp(-zeros * times)

    startDate = FinDate(1, 12, 2019)
    sigma = 0.01
    a = 0.1
    strike = 63.0
    face = 100.0

    expiryDate = startDate.addTenor("3Y")
    maturityDate = startDate.addTenor("9Y")

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

    numTimeSteps = None
    model = FinModelRatesHW(sigma, a, numTimeSteps)
    vAnal = model.optionOnZCB(texp, tmat, strike, face, times, dfs)

    # Test convergence
    numStepsList = range(100, 500, 50)
    analVector = []
    treeVector = []

    testCases.banner("Comparing option on zero coupon bond analytical vs Tree")

    testCases.header("NUMTIMESTEP", "VTREE_CALL", "VTREE_PUT", "VANAL CALL",
                     "VANAL_PUT", "CALLDIFF", "PUTDIFF", "PERIOD")

    for numTimeSteps in numStepsList:

        start = time.time()

        model = FinModelRatesHW(sigma, a, numTimeSteps)
        model.buildTree(texp, times, dfs)
        vTree1 = model.optionOnZeroCouponBond_Tree(texp, tmat, strike, face)

        model = FinModelRatesHW(sigma, a, numTimeSteps + 1)
        model.buildTree(texp, times, dfs)
        vTree2 = model.optionOnZeroCouponBond_Tree(texp, tmat, strike, face)

        end = time.time()
        period = end - start
        treeVector.append(vTree1['put'])
        analVector.append(vAnal['put'])
        vTreeCall = (vTree1['call'] + vTree2['call']) / 2.0
        vTreePut = (vTree1['put'] + vTree2['put']) / 2.0
        diffC = vTreeCall - vAnal['call']
        diffP = vTreePut - vAnal['put']

        testCases.print(numTimeSteps, vTreeCall, vAnal['call'], vTreePut,
                        vAnal['put'], diffC, diffP, period)
Exemplo n.º 23
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)
Exemplo n.º 24
0
def test_FinBondOptionAmericanConvergenceTWO():

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

    # Bond details
    issueDate = FinDate(1, 12, 2015)
    maturityDate = settlementDate.addTenor("10Y")
    coupon = 0.05
    frequencyType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType)
    expiryDate = settlementDate.addTenor("18m")
    face = 100.0

    spotValue = bond.cleanPriceFromDiscountCurve(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.01
    a = 0.1
    hwModel = FinModelRatesHW(sigma, a)
    K = 102.0

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

    numStepsVector = range(10, 500, 10)

    for numSteps in numStepsVector:
        hwModel = FinModelRatesHW(sigma, a, numSteps)

        start = time.time()

        europeanCallBondOption = FinBondOption(bond, expiryDate, K, face,
                                               FinOptionTypes.EUROPEAN_CALL)

        v_ec = europeanCallBondOption.value(settlementDate, discountCurve,
                                            hwModel)

        americanCallBondOption = FinBondOption(bond, expiryDate, K, face,
                                               FinOptionTypes.AMERICAN_CALL)

        v_ac = americanCallBondOption.value(settlementDate, discountCurve,
                                            hwModel)

        europeanPutBondOption = FinBondOption(bond, expiryDate, K, face,
                                              FinOptionTypes.EUROPEAN_PUT)

        v_ep = europeanPutBondOption.value(settlementDate, discountCurve,
                                           hwModel)

        americanPutBondOption = FinBondOption(bond, expiryDate, K, face,
                                              FinOptionTypes.AMERICAN_PUT)

        v_ap = americanPutBondOption.value(settlementDate, discountCurve,
                                           hwModel)

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

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