Ejemplo n.º 1
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(50, 500, 50)
    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", "TIME", "EXPIRY_ONLY", "EXPIRY_TREE", "JAMSHIDIAN")

    for numTimeSteps in numStepsList:

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

        exerciseType = FinExerciseTypes.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, period, v1, v2, vJam)

#    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)
Ejemplo n.º 2
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_FWD_RATES)
    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")
Ejemplo n.º 3
0
# -*- coding: utf-8 -*-
"""
Created on Sun Jan 13 21:52:16 2019

@author: Dominic O'Kane
"""

from financepy.finutils.FinDate import FinDate

# We can creat a FinDate as follows

dt1 = FinDate(2019, 10, 10)

# To see what this is, print it

print("PRINT DATES")
print(dt1)

# To add two days we can do

print("ADD CALENDAR DAYS")
dt2 = dt1.addDays(2)
print(dt2)

# dt has not changed, we just created a new date

# To add business days we do the following - note this does not know
# about regional or religious holidays - just weekends
print("ADD WORKDAYS")
print(dt1, dt1.addWorkDays(2))
Ejemplo n.º 4
0
def test_FinLiborDepositsFuturesSwaps():

    spotDate = FinDate(6, 6, 2018)
    spotDays = 0
    settlementDate = spotDate.addWorkDays(spotDays)
    depoDCCType = FinDayCountTypes.ACT_360
    depos = []
    depositRate = 0.0231381
    depo = FinLiborDeposit(settlementDate, "3M", depositRate, depoDCCType)
    depos.append(depo)

    depositRate = 0.027
    depo = FinLiborDeposit(settlementDate, "3M", depositRate, depoDCCType)
    depos.append(depo)

    depos = []
    depo = FinLiborDeposit(settlementDate, "1M", 0.0230, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "2M", 0.0235, depoDCCType)
    depos.append(depo)
    depo = FinLiborDeposit(settlementDate, "3M", 0.0240, depoDCCType)
    depos.append(depo)

    fras = []

    fraRate = futureToFRARate(97.6675, -0.00005)
    fraSettlementDate = spotDate.nextIMMDate()
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

    fraRate = futureToFRARate(97.5200, -0.00060)
    fraSettlementDate = fraMaturityDate
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

    fraRate = futureToFRARate(97.3550, -0.00146)
    fraSettlementDate = fraMaturityDate
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

    fraRate = futureToFRARate(97.2450, -0.00263)
    fraSettlementDate = fraMaturityDate
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

    fraRate = futureToFRARate(97.1450, -0.00411)
    fraSettlementDate = fraMaturityDate
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

    fraRate = futureToFRARate(97.0750, -0.00589)
    fraSettlementDate = fraSettlementDate.nextIMMDate()
    fraMaturityDate = fraSettlementDate.nextIMMDate()
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, depoDCCType)
    fras.append(fra)

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

    spotDays = 2
    startDate = spotDate.addWorkDays(spotDays)

    swaps = []
    swapType = FinLiborSwapTypes.PAYER
    fixedDCCType = FinDayCountTypes.THIRTY_E_360
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL
    floatFreqType = FinFrequencyTypes.QUARTERLY
    notional = 1000000
    floatSpread = 0.0
    floatDCCType = FinDayCountTypes.ACT_360
    calendarType = FinCalendarTypes.US
    busDayAdjustRule = FinBusDayAdjustTypes.PRECEDING

    swapRate = 0.02776305

    swap = FinLiborSwap(startDate, "2Y", swapType, swapRate, fixedFreqType,
                        fixedDCCType, notional, floatSpread, floatFreqType,
                        floatDCCType, calendarType, busDayAdjustRule)

    swaps.append(swap)

    liborCurve = FinLiborCurve(spotDate, depos, fras, swaps)

    times = np.linspace(0.0, 2.0, 25)
    dates = spotDate.addYears(times)
    zeroRates = liborCurve.zeroRate(dates)
    fwdRates = liborCurve.fwd(dates)

    if PLOT_GRAPHS:
        plt.figure(figsize=(8, 6))
        plt.plot(times, zeroRates * 100, label="zero rates")
        plt.plot(times, fwdRates * 100, label="fwd rates")
        plt.xlabel("Times")
        plt.ylabel("CC forward rates")
        plt.legend()

        print("==============================================================")
        for fra in fras:
            print(fra)
        print("==============================================================")

        endDate = spotDate
        df = liborCurve.df(endDate)
        print(endDate, df)

        endDate = settlementDate
        df = liborCurve.df(endDate)
        print(endDate, df)

        endDate = FinDate(20, 6, 2018)
        df = liborCurve.df(endDate)
        print(endDate, df)

        for depo in depos:
            endDate = depo._maturityDate
            df = liborCurve.df(endDate)
            print(endDate, df)

        for fra in fras:
            endDate = fra._maturityDate
            df = liborCurve.df(endDate)
            print(endDate, df)

        for swap in swaps:
            endDate = swap._maturityDate
            df = liborCurve.df(endDate)
            print(endDate, df)

        swap.printFixedLegPV(spotDate)
        swap.printFloatLegPV(spotDate)
Ejemplo n.º 5
0
def test_bloombergPricingExample():
    ''' This is an example of a replication of a BBG example from
    https://github.com/vilen22/curve-building/blob/master/Bloomberg%20Curve%20Building%20Replication.xlsx

    '''
    valuationDate = FinDate(6, 6, 2018)

    # We do the O/N rate which settles on trade date
    spotDays = 0
    settlementDate = valuationDate.addWorkDays(spotDays)
    depoDCCType = FinDayCountTypes.ACT_360
    depos = []
    depositRate = 0.0231381
    maturityDate = settlementDate.addMonths(3)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate,
                           depoDCCType)
    depos.append(depo)

    futs = []
    fut = FinLiborFuture(valuationDate, 1)
    futs.append(fut)
    fut = FinLiborFuture(valuationDate, 2)
    futs.append(fut)
    fut = FinLiborFuture(valuationDate, 3)
    futs.append(fut)
    fut = FinLiborFuture(valuationDate, 4)
    futs.append(fut)
    fut = FinLiborFuture(valuationDate, 5)
    futs.append(fut)
    fut = FinLiborFuture(valuationDate, 6)
    futs.append(fut)

    fras = [None] * 6
    fras[0] = futs[0].toFRA(97.6675, -0.00005)
    fras[1] = futs[1].toFRA(97.5200, -0.00060)
    fras[2] = futs[2].toFRA(97.3550, -0.00146)
    fras[3] = futs[3].toFRA(97.2450, -0.00263)
    fras[4] = futs[4].toFRA(97.1450, -0.00411)
    fras[5] = futs[5].toFRA(97.0750, -0.00589)

    accrual = FinDayCountTypes.THIRTY_E_360
    freq = FinFrequencyTypes.SEMI_ANNUAL

    spotDays = 2
    settlementDate = valuationDate.addWorkDays(spotDays)
    notional = ONE_MILLION
    swapType = FinLiborSwapTypes.PAYER

    swaps = []
    swap = FinLiborSwap(settlementDate, "2Y", swapType,
                        (2.77417 + 2.77844) / 200, freq, accrual, notional)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "3Y", swapType,
                        (2.86098 + 2.86582) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "4Y", swapType,
                        (2.90240 + 2.90620) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "5Y", swapType,
                        (2.92944 + 2.92906) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "6Y", swapType,
                        (2.94001 + 2.94499) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "7Y", swapType,
                        (2.95352 + 2.95998) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "8Y", swapType,
                        (2.96830 + 2.97400) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "9Y", swapType,
                        (2.98403 + 2.98817) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "10Y", swapType,
                        (2.99716 + 3.00394) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "11Y", swapType,
                        (3.01344 + 3.01596) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "12Y", swapType,
                        (3.02276 + 3.02684) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "15Y", swapType,
                        (3.04092 + 3.04508) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "20Y", swapType,
                        (3.04417 + 3.05183) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "25Y", swapType,
                        (3.03219 + 3.03621) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "30Y", swapType,
                        (3.01030 + 3.01370) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "40Y", swapType,
                        (2.96946 + 2.97354) / 200, freq, accrual)
    swaps.append(swap)
    swap = FinLiborSwap(settlementDate, "50Y", swapType,
                        (2.91552 + 2.93748) / 200, freq, accrual)
    swaps.append(swap)

    liborCurve = FinLiborCurve(valuationDate, depos, fras, swaps)

    # The valuation of 53714.55 is very close to the spreadsheet value 53713.96
    principal = 0.0

    testCases.header("VALUATION TO TODAY DATE", " PV")
    testCases.print(
        "VALUE:", swaps[0].value(valuationDate, liborCurve, liborCurve, None,
                                 principal))
    testCases.print(
        "FIXED:", swaps[0].fixedLegValue(valuationDate, liborCurve, principal))
    testCases.print(
        "FLOAT:", swaps[0].floatLegValue(valuationDate, liborCurve, liborCurve,
                                         None, principal))

    testCases.header("VALUATION TO SWAP SETTLEMENT DATE", " PV")
    testCases.print(
        "VALUE:", swaps[0].value(settlementDate, liborCurve, liborCurve, None,
                                 principal))
    testCases.print(
        "FIXED:", swaps[0].fixedLegValue(settlementDate, liborCurve,
                                         principal))
    testCases.print(
        "FLOAT:", swaps[0].floatLegValue(settlementDate, liborCurve,
                                         liborCurve, None, principal))
Ejemplo n.º 6
0
def test_FinBinomialTree():

    stockPrice = 50.0
    riskFreeRate = 0.06
    dividendYield = 0.04
    volatility = 0.40

    valueDate = FinDate(2016, 1, 1)
    expiryDate = FinDate(2017, 1, 1)

    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, riskFreeRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

    numStepsList = [100, 500, 1000, 2000, 5000]

    strikePrice = 50.0

    testCases.banner("================== EUROPEAN PUT =======================")

    putOption = FinEquityVanillaOption(expiryDate, strikePrice,
                                       FinOptionTypes.EUROPEAN_PUT)
    value = putOption.value(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)
    delta = putOption.delta(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)
    gamma = putOption.gamma(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)
    theta = putOption.theta(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)
    testCases.header("BS Value", "BS Delta", "BS Gamma", "BS Theta")
    testCases.print(value, delta, gamma, theta)

    payoff = FinEquityTreePayoffTypes.VANILLA_OPTION
    exercise = FinEquityTreeExerciseTypes.EUROPEAN
    params = np.array([-1, strikePrice])

    testCases.header("NumSteps", "Results", "TIME")

    for numSteps in numStepsList:
        start = time.time()
        tree = FinEquityBinomialTree()
        results = tree.value(stockPrice, discountCurve, dividendCurve,
                             volatility, numSteps, valueDate, payoff,
                             expiryDate, payoff, exercise, params)
        end = time.time()
        duration = end - start
        testCases.print(numSteps, results, duration)

    testCases.banner("================== AMERICAN PUT =======================")

    payoff = FinEquityTreePayoffTypes.VANILLA_OPTION
    exercise = FinEquityTreeExerciseTypes.AMERICAN
    params = np.array([-1, strikePrice])

    testCases.header("NumSteps", "Results", "TIME")

    for numSteps in numStepsList:
        start = time.time()
        tree = FinEquityBinomialTree()
        results = tree.value(stockPrice, discountCurve, dividendCurve,
                             volatility, numSteps, valueDate, payoff,
                             expiryDate, payoff, exercise, params)
        end = time.time()
        duration = end - start
        testCases.print(numSteps, results, duration)

    testCases.banner(
        "================== EUROPEAN CALL =======================")

    callOption = FinEquityVanillaOption(expiryDate, strikePrice,
                                        FinOptionTypes.EUROPEAN_CALL)
    value = callOption.value(valueDate, stockPrice, discountCurve,
                             dividendCurve, model)
    delta = callOption.delta(valueDate, stockPrice, discountCurve,
                             dividendCurve, model)
    gamma = callOption.gamma(valueDate, stockPrice, discountCurve,
                             dividendCurve, model)
    theta = callOption.theta(valueDate, stockPrice, discountCurve,
                             dividendCurve, model)
    testCases.header("BS Value", "BS Delta", "BS Gamma", "BS Theta")
    testCases.print(value, delta, gamma, theta)

    payoff = FinEquityTreePayoffTypes.VANILLA_OPTION
    exercise = FinEquityTreeExerciseTypes.EUROPEAN
    params = np.array([1.0, strikePrice])

    testCases.header("NumSteps", "Results", "TIME")
    for numSteps in numStepsList:
        start = time.time()
        tree = FinEquityBinomialTree()

        results = tree.value(stockPrice, discountCurve, dividendCurve,
                             volatility, numSteps, valueDate, payoff,
                             expiryDate, payoff, exercise, params)

        end = time.time()
        duration = end - start
        testCases.print(numSteps, results, duration)

    testCases.banner(
        "================== AMERICAN CALL =======================")

    payoff = FinEquityTreePayoffTypes.VANILLA_OPTION
    exercise = FinEquityTreeExerciseTypes.AMERICAN
    params = np.array([1.0, strikePrice])

    testCases.header("NumSteps", "Results", "TIME")
    for numSteps in numStepsList:
        start = time.time()
        tree = FinEquityBinomialTree()

        results = tree.value(stockPrice, discountCurve, dividendCurve,
                             volatility, numSteps, valueDate, payoff,
                             expiryDate, payoff, exercise, params)

        end = time.time()
        duration = end - start
        testCases.print(numSteps, results, duration)
Ejemplo n.º 7
0
###########################################################################

from financepy.finutils.FinFrequency import FinFrequencyTypes
from financepy.finutils.FinDayCount import FinDayCountTypes
from financepy.finutils.FinDate import FinDate
from financepy.products.bonds.FinBond import FinBond, FinYieldConventions
from financepy.market.curves.FinFlatCurve import FinFlatCurve
from financepy.market.curves.FinFlatCurve import FinCompoundingMethods

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

print("BLOOMBERG US TREASURY EXAMPLE")
settlementDate = FinDate(2017, 7, 21)
maturityDate = FinDate(2027, 5, 15)
coupon = 0.02375
freqType = FinFrequencyTypes.SEMI_ANNUAL
accrualType = FinDayCountTypes.ACT_ACT_ICMA

# By setting the face to 100 we expect a price of par to be 100.0
face = 100.0

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

cleanPrice = 99.780842  # if face is 1 then this must be 0.99780842

yld = bond.currentYield(cleanPrice)
print("Current Yield = ", yld)

ytm = bond.yieldToMaturity(settlementDate, cleanPrice,
                           FinYieldConventions.UK_DMO)
print("UK DMO Yield To Maturity = ", ytm)
Ejemplo n.º 8
0
def test_FinBondFRN():

    # https://data.bloomberglp.com/bat/sites/3/2017/07/SF-2017_Paul-Fjeldsted.pdf
    # I have a day out problem on the accrued interest - should be 71 and not 72 days
    # Other than that agreement on the DM is very good.

    ##########################################################################
    # CITIGROUP FRN SCREENSHOT
    ##########################################################################

    testCases.banner("BLOOMBERG CITIGROUP FRN EXAMPLE")
    issueDate = FinDate(10, 11, 2010)
    maturityDate = FinDate(10, 11, 2021)
    quotedMargin = 0.0025
    freqType = FinFrequencyTypes.QUARTERLY
    accrualType = FinDayCountTypes.THIRTY_E_360
    face = 1000000

    bond = FinBondFRN(issueDate, maturityDate, quotedMargin, freqType,
                      accrualType, face)

    testCases.header("FIELD", "VALUE")
    cleanPrice = 96.793
    resetIbor = 0.0143456 - quotedMargin
    currentIbor = 0.0120534
    futureIbors = 0.0130522

    settlementDate = FinDate(21, 7, 2017)

    dm = bond.discountMargin(settlementDate, resetIbor, currentIbor,
                             futureIbors, cleanPrice)

    testCases.print("Discount Margin (bp) = ", dm * 10000)

    fullPrice = bond.fullPriceFromDM(settlementDate, resetIbor, currentIbor,
                                     futureIbors, dm)

    testCases.print("Full Price = ", fullPrice)

    lastCouponDt = bond._pcd
    testCases.print("Last Coupon Date = ", str(lastCouponDt))

    accddays = bond._accruedDays
    testCases.print("Accrued Days = ", accddays)

    accdAmount = bond._accruedInterest
    testCases.print("Accrued Amount = ", accdAmount)

    principal = bond.principal(settlementDate, resetIbor, currentIbor,
                               futureIbors, dm)

    testCases.print("Dollar Principal = ", principal)

    duration = bond.dollarDuration(settlementDate, resetIbor, currentIbor,
                                   futureIbors, dm)

    testCases.print("Dollar Rate Duration = ", duration)

    modifiedDuration = bond.modifiedRateDuration(settlementDate, resetIbor,
                                                 currentIbor, futureIbors, dm)

    testCases.print("Modified Rate Duration = ", modifiedDuration)

    macauleyDuration = bond.macauleyRateDuration(settlementDate, resetIbor,
                                                 currentIbor, futureIbors, dm)

    testCases.print("Macauley Duration = ", macauleyDuration)

    convexity = bond.convexityFromDM(settlementDate, resetIbor, currentIbor,
                                     futureIbors, dm)

    testCases.print("Convexity = ", convexity)

    duration = bond.dollarCreditDuration(settlementDate, resetIbor,
                                         currentIbor, futureIbors, dm)

    testCases.print("Dollar Credit Duration = ", duration)

    modifiedDuration = bond.modifiedCreditDuration(settlementDate, resetIbor,
                                                   currentIbor, futureIbors,
                                                   dm)

    testCases.print("Modified Credit Duration = ", modifiedDuration)

    ##########################################################################
    # EXAMPLE
    # https://ebrary.net/14293/economics/actual_floater
    ##########################################################################

    testCases.banner("BLOOMBERG CITIGROUP FRN EXAMPLE II")
    issueDate = FinDate(28, 3, 2000)
    settlementDate = FinDate(28, 3, 2014)
    maturityDate = FinDate(3, 2, 2021)
    quotedMargin = 0.0020
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.THIRTY_E_360_ISDA
    face = 1000000.0

    bond = FinBondFRN(issueDate, maturityDate, quotedMargin, freqType,
                      accrualType, face)

    testCases.header("FIELD", "VALUE")
    cleanPrice = 93.08
    resetIbor = 0.00537 - quotedMargin
    currentIbor = 0.027558
    futureIbors = 0.03295

    dm = bond.discountMargin(settlementDate, resetIbor, currentIbor,
                             futureIbors, cleanPrice)

    testCases.print("Discount Margin (bp) = ", dm * 10000)

    fullPrice = bond.fullPriceFromDM(settlementDate, resetIbor, currentIbor,
                                     futureIbors, dm)

    testCases.print("Full Price = ", fullPrice)

    lastCouponDt = bond._pcd
    testCases.print("Last Coupon Date = ", str(lastCouponDt))

    accddays = bond._accruedDays
    testCases.print("Accrued Days = ", accddays)

    accdAmount = bond._accruedInterest
    testCases.print("Accrued Amount = ", accdAmount)

    principal = bond.principal(settlementDate, resetIbor, currentIbor,
                               futureIbors, dm)

    testCases.print("Dollar Principal = ", principal)

    duration = bond.dollarDuration(settlementDate, resetIbor, currentIbor,
                                   futureIbors, dm)

    testCases.print("Dollar Rate Duration = ", duration)

    modifiedDuration = bond.modifiedRateDuration(settlementDate, resetIbor,
                                                 currentIbor, futureIbors, dm)

    testCases.print("Modified Rate Duration = ", modifiedDuration)

    macauleyDuration = bond.macauleyRateDuration(settlementDate, resetIbor,
                                                 currentIbor, futureIbors, dm)

    testCases.print("Macauley Duration = ", macauleyDuration)

    convexity = bond.convexityFromDM(settlementDate, resetIbor, currentIbor,
                                     futureIbors, dm)

    testCases.print("Convexity = ", convexity)

    principal = bond.principal(settlementDate, resetIbor, currentIbor,
                               futureIbors, dm)

    testCases.print("Principal = ", principal)

    duration = bond.dollarCreditDuration(settlementDate, resetIbor,
                                         currentIbor, futureIbors, dm)

    testCases.print("Dollar Credit Duration = ", duration)

    modifiedDuration = bond.modifiedCreditDuration(settlementDate, resetIbor,
                                                   currentIbor, futureIbors,
                                                   dm)

    testCases.print("Modified Credit Duration = ", modifiedDuration)
Ejemplo n.º 9
0
def test_FinLiborSwaption():

    import time

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

    swapFixedCoupon = 0.030
    swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL
    swapFixedDayCountType = FinDayCountTypes.ACT_365_ISDA

    liborCurve = test_FinLiborDepositsAndSwaps(valuationDate)

    start = time.time()

    swaptionType = FinLiborSwaptionType.PAYER
    swaption = FinLiborSwaption(exerciseDate, swapMaturityDate, swaptionType,
                                swapFixedCoupon, swapFixedFrequencyType,
                                swapFixedDayCountType)

    model = FinLiborModelBlack(0.25)
    settlementDate = valuationDate.addWorkDays(2)
    value = swaption.value(settlementDate, liborCurve, model)

    #    swaption.print()

    testCases.header("LABEL", "VALUE")
    testCases.print("PAYER Swaption Value", value)

    swaptionType = FinLiborSwaptionType.RECEIVER
    swaption = FinLiborSwaption(exerciseDate, swapMaturityDate, swaptionType,
                                swapFixedCoupon, swapFixedFrequencyType,
                                swapFixedDayCountType)

    model = FinLiborModelBlack(0.25)
    settlementDate = valuationDate.addWorkDays(2)
    value = swaption.value(settlementDate, liborCurve, model)

    #    swaption.print()

    testCases.print("RECEIVER Swaption Value", value)

    end = time.time()

    testCases.header("TIME")
    testCases.print(end - start)

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

    start = time.time()

    swaptionType = FinLiborSwaptionType.PAYER

    testCases.banner(
        "===================================================================")

    swaption = FinLiborSwaption(exerciseDate, swapMaturityDate, swaptionType,
                                swapFixedCoupon, swapFixedFrequencyType,
                                swapFixedDayCountType)

    model = FinLiborModelSABR(0.28, 1.0, -0.09, 0.21)
    value = swaption.value(settlementDate, liborCurve, model)

    #    swaption.print()

    testCases.header("LABEL", "VALUE")
    testCases.print("PAYER Swaption Value", value)

    swaptionType = FinLiborSwaptionType.RECEIVER

    swaption = FinLiborSwaption(exerciseDate, swapMaturityDate, swaptionType,
                                swapFixedCoupon, swapFixedFrequencyType,
                                swapFixedDayCountType)

    model = FinLiborModelSABR(0.28, 1.0, -0.09, 0.21)
    value = swaption.value(settlementDate, liborCurve, model)

    #    swaption.print()

    testCases.print("RECEIVER Swaption Value", value)

    end = time.time()

    testCases.header("TIME")
    testCases.print(end - start)
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
def test_FinCDSCurve():

    curveDate = FinDate(2018, 12, 20)

    swaps = []
    depos = []
    fras = []

    fixedDCC = FinDayCountTypes.ACT_365F
    fixedFreq = FinFrequencyTypes.SEMI_ANNUAL
    fixedCoupon = 0.05

    for i in range(1, 11):

        maturityDate = curveDate.addMonths(12 * i)
        swap = FinIborSwap(curveDate, maturityDate, FinSwapTypes.PAYER,
                           fixedCoupon, fixedFreq, fixedDCC)
        swaps.append(swap)

    libor_curve = FinIborSingleCurve(curveDate, depos, fras, swaps)

    cdsContracts = []

    for i in range(1, 11):
        maturityDate = curveDate.addMonths(12 * i)
        cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1))
        cdsContracts.append(cds)

    issuerCurve = FinCDSCurve(curveDate,
                              cdsContracts,
                              libor_curve,
                              recoveryRate=0.40,
                              useCache=False)

    testCases.header("T", "Q")
    n = len(issuerCurve._times)
    for i in range(0, n):
        testCases.print(issuerCurve._times[i], issuerCurve._values[i])

    testCases.header("CONTRACT", "VALUE")
    for i in range(1, 11):
        maturityDate = curveDate.addMonths(12 * i)
        cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1))
        v = cds.value(curveDate, issuerCurve)
        testCases.print(i, v)

    if 1 == 0:
        x = [0.0, 1.2, 1.6, 1.7, 10.0]
        qs = issuerCurve.survProb(x)
        print("===>", qs)

        x = [0.3, 1.2, 1.6, 1.7, 10.0]
        xx = np.array(x)
        qs = issuerCurve.survProb(xx)
        print("===>", qs)

        x = [0.3, 1.2, 1.6, 1.7, 10.0]
        dfs = issuerCurve.df(x)
        print("===>", dfs)

        x = [0.3, 1.2, 1.6, 1.7, 10.0]
        xx = np.array(x)
        dfs = issuerCurve.df(xx)
        print("===>", dfs)
Ejemplo 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)
Ejemplo n.º 13
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, 100)
    analVector = []
    treeVector = []

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

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

    for 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, period, vTreeCall, vAnal['call'],
                        vTreePut, vAnal['put'], diffC, diffP)
Ejemplo n.º 14
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, 500, 1000]
    tmat = (maturityDate - settlementDate)/gDaysInYear

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

    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, period, v1, v2)
def test_FinNelsonSiegelSvenssonCurve():

    tau1 = 2.0
    tau2 = 0.5
    times = np.linspace(0.0, 10.0, 5)
    startDate = FinDate(1, 1, 2020)
    dates = startDate.addYears(times)

    curve1 = FinDiscountCurveNSS(startDate, 1., 0., 0., 0., tau1, tau2)
    factor1loading = curve1.zeroRate(dates)
    curve2 = FinDiscountCurveNSS(startDate, 0., 1., 0., 0., tau1, tau2)
    factor2loading = curve2.zeroRate(dates)
    curve3 = FinDiscountCurveNSS(startDate, 0., 0., 1., 0., tau1, tau2)
    factor3loading = curve3.zeroRate(dates)
    curve4 = FinDiscountCurveNSS(startDate, 0., 0., 0., 1., tau1, tau2)
    factor4loading = curve4.zeroRate(dates)

    testCases.header("FACTOR LOADING ON ZERO RATES")
    testCases.print(factor1loading)
    testCases.print(factor2loading)
    testCases.print(factor3loading)
    testCases.print(factor4loading)

#    plt.figure(figsize = (6,4))
#    plt.plot(times,scaleVector(factor1loading,1),label='beta1');
#    plt.plot(times,scaleVector(factor2loading,1),label='beta2');
#    plt.plot(times,scaleVector(factor3loading,1),label='beta3');
#    plt.ylim((0,1.05))
#
#    plt.title('Factor Loadings in Nelson-Siegel Model');
#    plt.xlabel('Time (years)');
#    plt.ylabel('Loading');
#    plt.legend(loc='best')

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

    testCases.header("BETA1", "BETA2", "BETA3", "BETA4", "ZEROS")

    beta1 = 0.03
    beta2 = -0.02
    beta3 = -0.02
    beta4 = 0.08
    curve1 = FinDiscountCurveNSS(startDate,
        beta1, beta2, beta3, beta4, tau1, tau2)
    zeroRates1 = curve1.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, beta4, zeroRates1)

    beta1 = 0.04
    beta2 = -0.02
    beta3 = -0.02
    beta4 = 0.08
    curve2 = FinDiscountCurveNSS(startDate,
        beta1, beta2, beta3, beta4, tau1, tau2)
    zeroRates2 = curve2.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, beta4, zeroRates2)

    beta1 = 0.05
    beta2 = -0.02
    beta3 = -0.02
    beta4 = 0.08
    curve3 = FinDiscountCurveNSS(startDate,
        beta1, beta2, beta3, beta4, tau1, tau2)
    zeroRates3 = curve3.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, beta4, zeroRates3)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = -0.02
    beta4 = 0.08
    curve4 = FinDiscountCurveNSS(startDate,
        beta1, beta2, beta3, beta4, tau1, tau2)
    zeroRates4 = curve4.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, beta4, zeroRates4)

    beta1 = 0.07
    beta2 = -0.02
    beta3 = -0.02
    beta4 = 0.08
    curve5 = FinDiscountCurveNSS(startDate,
        beta1, beta2, beta3, beta4, tau1, tau2)
    zeroRates5 = curve5.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, beta4, zeroRates5)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(times, scale(zeroRates1, 100), label='beta1=3%')
        plt.plot(times, scale(zeroRates2, 100), label='beta1=4%')
        plt.plot(times, scale(zeroRates3, 100), label='beta1=5%')
        plt.plot(times, scale(zeroRates4, 100), label='beta1=6%')
        plt.plot(times, scale(zeroRates5, 100), label='beta1=7%')
        plt.ylim((0, 7.5))

        plt.title('Nelson-Siegel Zero Rate Curves')
        plt.xlabel('Time (years)')
        plt.ylabel('Zero Rate (%)')
        plt.legend(loc='lower right', frameon=False)
Ejemplo n.º 16
0
def test_FinBondYieldCurve():

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

    import pandas as pd
    path = os.path.join(os.path.dirname(__file__), './data/giltBondPrices.txt')
    bondDataFrame = pd.read_csv(path, sep='\t')
    bondDataFrame['mid'] = 0.5 * (bondDataFrame['bid'] + bondDataFrame['ask'])

    freqType = FinFrequencyTypes.SEMI_ANNUAL
    accrualType = FinDayCountTypes.ACT_ACT_ICMA
    settlement = FinDate(2012, 9, 19)

    bonds = []
    ylds = []

    for _, bond in bondDataFrame.iterrows():

        dateString = bond['maturity']
        matDatetime = dt.datetime.strptime(dateString, '%d-%b-%y')
        maturityDt = fromDatetime(matDatetime)
        issueDt = FinDate(maturityDt._d, maturityDt._m, 2000)
        coupon = bond['coupon'] / 100.0
        cleanPrice = bond['mid']
        bond = FinBond(issueDt, maturityDt, coupon, freqType, accrualType)
        yld = bond.yieldToMaturity(settlement, cleanPrice)
        bonds.append(bond)
        ylds.append(yld)

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

    curveFitMethod = FinCurveFitPolynomial()
    fittedCurve1 = FinBondYieldCurve(settlement, bonds, ylds, curveFitMethod)
    #    fittedCurve1.display("GBP Yield Curve")

    curveFitMethod = FinCurveFitPolynomial(5)
    fittedCurve2 = FinBondYieldCurve(settlement, bonds, ylds, curveFitMethod)
    #    fittedCurve2.display("GBP Yield Curve")

    curveFitMethod = FinCurveFitNelsonSiegel()
    fittedCurve3 = FinBondYieldCurve(settlement, bonds, ylds, curveFitMethod)
    #    fittedCurve3.display("GBP Yield Curve")

    curveFitMethod = FinCurveFitNelsonSiegelSvensson()
    fittedCurve4 = FinBondYieldCurve(settlement, bonds, ylds, curveFitMethod)
    #    fittedCurve4.display("GBP Yield Curve")

    curveFitMethod = FinCurveFitBSpline()
    fittedCurve5 = FinBondYieldCurve(settlement, bonds, ylds, curveFitMethod)
    #    fittedCurve5.display("GBP Yield Curve")

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

    testCases.header("PARAMETER", "VALUE")
    testCases.print("beta1", fittedCurve3._curveFit._beta1)
    testCases.print("beta2", fittedCurve3._curveFit._beta2)
    testCases.print("beta3", fittedCurve3._curveFit._beta3)
    testCases.print("tau", fittedCurve3._curveFit._tau)

    testCases.header("PARAMETER", "VALUE")
    testCases.print("beta1", fittedCurve4._curveFit._beta1)
    testCases.print("beta2", fittedCurve4._curveFit._beta2)
    testCases.print("beta3", fittedCurve4._curveFit._beta3)
    testCases.print("beta4", fittedCurve4._curveFit._beta4)
    testCases.print("tau1", fittedCurve4._curveFit._tau1)
    testCases.print("tau2", fittedCurve4._curveFit._tau2)

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

    maturityDate = FinDate(2030, 9, 19)
    interpolatedYield = fittedCurve5.interpolatedYield(maturityDate)
    testCases.print(maturityDate, interpolatedYield)
Ejemplo n.º 17
0
def test_FinFXMktVolSurface1(verboseCalibration):

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

    if 1 == 1:

        # Example from Book extract by Iain Clarke using Tables 3.3 and 3.4
        # print("EURUSD EXAMPLE CLARKE")

        valueDate = FinDate(10, 4, 2020)

        forName = "EUR"
        domName = "USD"
        forCCRate = 0.03460  # EUR
        domCCRate = 0.02940  # USD

        domDiscountCurve = FinDiscountCurveFlat(valueDate, domCCRate)
        forDiscountCurve = FinDiscountCurveFlat(valueDate, forCCRate)

        currencyPair = forName + domName
        spotFXRate = 1.3465

        tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
        atmVols = [21.00, 21.00, 20.750, 19.400, 18.250, 17.677]
        marketStrangle25DeltaVols = [0.65, 0.75, 0.85, 0.90, 0.95, 0.85]
        riskReversal25DeltaVols = [-0.20, -0.25, -0.30, -0.50, -0.60, -0.562]
        marketStrangle10DeltaVols = [2.433, 2.83, 3.228, 3.485, 3.806, 3.208]
        riskReversal10DeltaVols = [-1.258, -1.297, -1.332, -1.408, -1.359, -1.208]

        if 1==1:
            tenors = ['1Y']
            atmVols = [18.250]
            marketStrangle25DeltaVols = [0.950]
            riskReversal25DeltaVols = [-0.600]
            marketStrangle10DeltaVols = [3.806]
            riskReversal10DeltaVols = [-1.359]

        notionalCurrency = forName

        atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
        deltaMethod = FinFXDeltaMethod.SPOT_DELTA
        volFunctionType = FinVolFunctionTypes.CLARKE
#        volFunctionType = FinVolFunctionTypes.SABR
        
        fxMarket = FinFXVolSurfacePlus(valueDate,
                                       spotFXRate,
                                       currencyPair,
                                       notionalCurrency,
                                       domDiscountCurve,
                                       forDiscountCurve,
                                       tenors,
                                       atmVols,
                                       marketStrangle25DeltaVols,
                                       riskReversal25DeltaVols,
                                       marketStrangle10DeltaVols,
                                       riskReversal10DeltaVols,
                                       atmMethod,
                                       deltaMethod, 
                                       volFunctionType)

        fxMarket.checkCalibration(False)

        if PLOT_GRAPHS:
            fxMarket.plotVolCurves()

        dbns = fxMarket.impliedDbns(0.00001, 5.0, 10000)

        for i in range(0, len(dbns)):
            plt.plot(dbns[i]._x, dbns[i]._densitydx)
            print("SUM:", dbns[i].sum())

        fxMarket = FinFXVolSurface(valueDate,
                                       spotFXRate,
                                       currencyPair,
                                       notionalCurrency,
                                       domDiscountCurve,
                                       forDiscountCurve,
                                       tenors,
                                       atmVols,
                                       marketStrangle25DeltaVols,
                                       riskReversal25DeltaVols,
                                       atmMethod,
                                       deltaMethod, 
                                       volFunctionType)

        fxMarket.checkCalibration(False)

        if PLOT_GRAPHS:
            fxMarket.plotVolCurves()

        dbns = fxMarket.impliedDbns(0.00001, 5.0, 10000)

        for i in range(0, len(dbns)):
            plt.plot(dbns[i]._x, dbns[i]._densitydx)
            print("SUM:", dbns[i].sum())
Ejemplo n.º 18
0
from financepy.products.bonds.FinBond import FinBond
from financepy.market.curves.FinBondYieldCurve import FinBondYieldCurve
from financepy.market.curves.FinBondYieldCurveModel import *

###############################################################################
# FIRST LOAD UP SOME UK BOND DATA USING PANDAS

bondDataFrame = pd.read_csv('../tests/data/giltbondprices.txt', sep='\t')

# CALCULATE MID MARKET PRICES
bondDataFrame['mid'] = 0.5 * (bondDataFrame['bid'] + bondDataFrame['ask'])

# SPECIFY UK BOND CONVENTIONS
frequencyType = FinFrequencyTypes.SEMI_ANNUAL
accrualType = FinDayCountTypes.ACT_ACT_ICMA
settlement = FinDate(2012, 9, 19)

bonds = []
ylds = []

# LOAD BONDS AND CREATE A VECTOR OF FINBOND AND THEIR CORRESPONDING YIELDS

for index, bond in bondDataFrame.iterrows():

    dateString = bond['maturity']
    matDatetime = dt.datetime.strptime(dateString, '%d-%b-%y')
    maturityDt = FinDate.fromDatetime(matDatetime)
    coupon = bond['coupon'] / 100.0
    cleanPrice = bond['mid']
    bond = FinBond(maturityDt, coupon, frequencyType, accrualType)
    yld = bond.yieldToMaturity(settlement, cleanPrice)
Ejemplo n.º 19
0
def test_fullPriceCDSIndexOption():

    tradeDate = FinDate(2007, 8, 1)
    stepInDate = tradeDate.addDays(1)
    valuationDate = stepInDate

    liborCurve = buildIborCurve(tradeDate)

    maturity3Y = tradeDate.nextCDSDate(36)
    maturity5Y = tradeDate.nextCDSDate(60)
    maturity7Y = tradeDate.nextCDSDate(84)
    maturity10Y = tradeDate.nextCDSDate(120)

    path = os.path.join(os.path.dirname(__file__),
                        './/data//CDX_NA_IG_S7_SPREADS.csv')
    f = open(path, 'r')
    data = f.readlines()
    f.close()
    issuerCurves = []

    for row in data[1:]:

        splitRow = row.split(",")
        creditName = splitRow[0]
        spd3Y = float(splitRow[1]) / 10000.0
        spd5Y = float(splitRow[2]) / 10000.0
        spd7Y = float(splitRow[3]) / 10000.0
        spd10Y = float(splitRow[4]) / 10000.0
        recoveryRate = float(splitRow[5])

        cds3Y = FinCDS(stepInDate, maturity3Y, spd3Y)
        cds5Y = FinCDS(stepInDate, maturity5Y, spd5Y)
        cds7Y = FinCDS(stepInDate, maturity7Y, spd7Y)
        cds10Y = FinCDS(stepInDate, maturity10Y, spd10Y)
        cdsContracts = [cds3Y, cds5Y, cds7Y, cds10Y]

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

        issuerCurves.append(issuerCurve)

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

    indexUpfronts = [0.0, 0.0, 0.0, 0.0]
    indexMaturityDates = [
        FinDate(2009, 12, 20),
        FinDate(2011, 12, 20),
        FinDate(2013, 12, 20),
        FinDate(2016, 12, 20)
    ]
    indexRecovery = 0.40

    testCases.banner(
        "======================= CDS INDEX OPTION ==========================")

    indexCoupon = 0.004
    volatility = 0.50
    expiryDate = FinDate(2008, 2, 1)
    maturityDate = FinDate(2011, 12, 20)
    notional = 10000.0
    tolerance = 1e-6

    testCases.header("TIME", "STRIKE", "INDEX", "PAYER", "RECEIVER", "G(K)",
                     "X", "EXPH", "ABPAY", "ABREC")

    for index in np.linspace(20, 60, 10):

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

        cdsContracts = []
        for dt in indexMaturityDates:
            cds = FinCDS(valuationDate, dt, index / 10000.0)
            cdsContracts.append(cds)

        indexCurve = FinCDSCurve(valuationDate, cdsContracts, liborCurve,
                                 indexRecovery)

        if 1 == 1:

            indexSpreads = [index / 10000.0] * 4

            indexPortfolio = FinCDSIndexPortfolio()
            adjustedIssuerCurves = indexPortfolio.hazardRateAdjustIntrinsic(
                valuationDate, issuerCurves, indexSpreads, indexUpfronts,
                indexMaturityDates, indexRecovery, tolerance)
        else:

            indexSpread = index / 10000.0
            issuerCurve = buildFlatIssuerCurve(tradeDate, liborCurve,
                                               indexSpread, indexRecovery)

            adjustedIssuerCurves = []
            for iCredit in range(0, 125):
                adjustedIssuerCurves.append(issuerCurve)

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

        for strike in np.linspace(20, 60, 20):

            start = time.time()

            option = FinCDSIndexOption(expiryDate, maturityDate, indexCoupon,
                                       strike / 10000.0, notional)

            v_pay_1, v_rec_1, strikeValue, mu, expH = option.valueAnderson(
                valuationDate, adjustedIssuerCurves, indexRecovery, volatility)
            end = time.time()
            elapsed = end - start

            end = time.time()

            v_pay_2, v_rec_2 = option.valueAdjustedBlack(
                valuationDate, indexCurve, indexRecovery, liborCurve,
                volatility)

            elapsed = end - start

            testCases.print(elapsed, strike, index, v_pay_1, v_rec_1,
                            strikeValue, mu, expH, v_pay_2, v_rec_2)
Ejemplo n.º 20
0
def test_FinFXVanillaOptionHullExample():

    #   Example from Hull 4th edition page 284
    valueDate = FinDate(2015, 1, 1)
    expiryDate = valueDate.addMonths(4)
    spotFXRate = 1.60
    volatility = 0.1411
    domInterestRate = 0.08
    forInterestRate = 0.11
    model = FinFXModelBlackScholes(volatility)
    domDiscountCurve = FinDiscountCurveFlat(valueDate, domInterestRate)
    forDiscountCurve = FinDiscountCurveFlat(valueDate, forInterestRate)

    numPathsList = [10000, 20000, 40000, 80000, 160000, 320000]

    testCases.header("NUMPATHS", "VALUE_BS", "VALUE_MC", "TIME")
    strikeFXRate = 1.60

    for numPaths in numPathsList:

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, 1000000,
                                        "USD")

        value = callOption.value(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)

        start = time.time()

        valueMC = callOption.valueMC(valueDate, spotFXRate, domDiscountCurve,
                                     forDiscountCurve, model, numPaths)

        end = time.time()
        duration = end - start
        testCases.print(numPaths, value, valueMC, duration)

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

    spotFXRates = np.arange(100, 200, 10)
    spotFXRates = spotFXRates / 100.0
    numPaths = 100000

    testCases.header("NUMPATHS", "CALL_VALUE_BS", "CALL_VALUE_MC", "TIME")

    for spotFXRate in spotFXRates:

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, 1000000,
                                        "USD")

        value = callOption.value(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)
        start = time.time()
        valueMC = callOption.valueMC(valueDate, spotFXRate, domDiscountCurve,
                                     forDiscountCurve, model, numPaths)
        end = time.time()
        duration = end - start
        testCases.print(numPaths, value, valueMC, duration)

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

    spotFXRates = np.arange(100, 200, 10) / 100.0
    numPaths = 100000

    testCases.header("SPOT FX RATE", "PUT_VALUE_BS", "PUT_VALUE_MC", "TIME")

    for spotFXRate in spotFXRates:

        putOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                       FinOptionTypes.EUROPEAN_PUT, 1000000,
                                       "USD")

        value = putOption.value(valueDate, spotFXRate, domDiscountCurve,
                                forDiscountCurve, model)
        start = time.time()
        valueMC = putOption.valueMC(valueDate, spotFXRate, domDiscountCurve,
                                    forDiscountCurve, model, numPaths)
        end = time.time()
        duration = end - start
        testCases.print(spotFXRate, value, valueMC, duration)

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

    spotFXRates = np.arange(100, 200, 10) / 100.0

    testCases.header("SPOT FX RATE", "CALL_VALUE_BS", "DELTA_BS", "VEGA_BS",
                     "THETA_BS", "RHO_BS")

    for spotFXRate in spotFXRates:
        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, 1000000,
                                        "USD")
        value = callOption.value(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)
        delta = callOption.delta(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)
        vega = callOption.vega(valueDate, spotFXRate, domDiscountCurve,
                               forDiscountCurve, model)
        theta = callOption.theta(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)
        #  callOption.rho(valueDate,stockPrice, interestRate,
        #  dividendYield, modelType, modelParams)
        rho = 999
        testCases.print(spotFXRate, value, delta, vega, theta, rho)

    testCases.header("SPOT FX RATE", "PUT_VALUE_BS", "DELTA_BS", "VEGA_BS",
                     "THETA_BS", "RHO_BS")

    for spotFXRate in spotFXRates:
        putOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                       FinOptionTypes.EUROPEAN_PUT, 1000000,
                                       "USD")

        value = putOption.value(valueDate, spotFXRate, domDiscountCurve,
                                forDiscountCurve, model)
        delta = putOption.delta(valueDate, spotFXRate, domDiscountCurve,
                                forDiscountCurve, model)
        vega = putOption.vega(valueDate, spotFXRate, domDiscountCurve,
                              forDiscountCurve, model)
        theta = putOption.theta(valueDate, spotFXRate, domDiscountCurve,
                                forDiscountCurve, model)
        # putOption.rho(valueDate,stockPrice, interestRate, dividendYield,
        # modelType, modelParams)
        rho = 999
        testCases.print(spotFXRate, value, delta, vega, theta, rho)

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

    testCases.header("SPOT FX RATE", "VALUE_BS", "VOL_IN", "IMPLD_VOL")

    spotFXRates = np.arange(100, 200, 10) / 100.0

    for spotFXRate in spotFXRates:
        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, 1000000,
                                        "USD")

        value = callOption.value(valueDate, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)['v']

        impliedVol = callOption.impliedVolatility(valueDate, spotFXRate,
                                                  domDiscountCurve,
                                                  forDiscountCurve, value)

        testCases.print(spotFXRate, value, volatility, impliedVol)
Ejemplo n.º 21
0
def test_FinLiborDepositsFRAsSwaps():

    valuationDate = FinDate(2019, 9, 18)

    dccType = FinDayCountTypes.THIRTY_E_360_ISDA
    depos = []

    spotDays = 0
    settlementDate = valuationDate.addWorkDays(spotDays)

    depositRate = 0.050
    maturityDate = settlementDate.addMonths(1)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    maturityDate = settlementDate.addMonths(2)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    maturityDate = settlementDate.addMonths(3)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    maturityDate = settlementDate.addMonths(6)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    maturityDate = settlementDate.addMonths(9)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    maturityDate = settlementDate.addMonths(12)
    depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, dccType)
    depos.append(depo)

    fras = []
    # 1 x 4 FRA
    fraRate = 0.04
    fraSettlementDate = settlementDate.addMonths(9)
    fraMaturityDate = settlementDate.addMonths(13)
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, dccType)
    fras.append(fra)

    # 4 x 7 FRA
    fraRate = 0.03
    fraSettlementDate = settlementDate.addMonths(13)
    fraMaturityDate = settlementDate.addMonths(17)
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, dccType)
    fras.append(fra)

    # 4 x 7 FRA
    fraRate = 0.07
    fraSettlementDate = settlementDate.addMonths(17)
    fraMaturityDate = settlementDate.addMonths(21)
    fra = FinLiborFRA(fraSettlementDate, fraMaturityDate, fraRate, dccType)
    fras.append(fra)

    swaps = []
    fixedDCCType = FinDayCountTypes.ACT_365F
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL

    swapRate = 0.05
    #    maturityDate = settlementDate.addMonths(24)
    #    swap = FinLiborSwap(settlementDate, maturityDate, swapRate, fixedFreqType,
    #                        fixedDCCType)
    #    swaps.append(swap)

    swapType = FinLiborSwapTypes.PAYER
    maturityDate = settlementDate.addMonths(36)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(48)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(60)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(72)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(84)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(96)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(108)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(120)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(132)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(144)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(180)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(240)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(300)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    maturityDate = settlementDate.addMonths(360)
    swap = FinLiborSwap(settlementDate, maturityDate, swapType, swapRate,
                        fixedFreqType, fixedDCCType)
    swaps.append(swap)

    liborCurve = FinLiborCurve(valuationDate, depos, fras, swaps)

    df = liborCurve.df(settlementDate)

    testCases.header("SETTLEMENT DATE", "DF")
    testCases.print(str(settlementDate), df)
    testCases.header("DATE", "DF")

    for deposit in depos:
        df = liborCurve.df(deposit._maturityDate)
        testCases.print(str(deposit._maturityDate), df)

    for swap in swaps:
        df = liborCurve.df(swap._maturityDate)
        testCases.print(str(swap._maturityDate), df)
Ejemplo n.º 22
0
def test_FinFXAmericanOption():

    # There is no FXAmericanOption class. It is embedded in the FXVanillaOption
    # class. This test just compares it to the European

    valueDate = FinDate(13, 2, 2018)
    expiryDate = FinDate(13, 2, 2019)

    # In BS the FX rate is the price in domestic of one unit of foreign
    # In case of EURUSD = 1.3 the domestic currency is USD and foreign is EUR
    # DOM = USD , FOR = EUR
    ccy1 = "EUR"
    ccy2 = "USD"
    ccy1CCRate = 0.030  # EUR
    ccy2CCRate = 0.025  # USD

    currencyPair = ccy1 + ccy2  # Always ccy1ccy2
    spotFXRate = 1.20
    strikeFXRate = 1.250
    volatility = 0.10

    domDiscountCurve = FinDiscountCurveFlat(valueDate, ccy2CCRate)
    forDiscountCurve = FinDiscountCurveFlat(valueDate, ccy1CCRate)

    model = FinFXModelBlackScholes(volatility)

    # Two examples to show that changing the notional currency and notional
    # keeps the value unchanged

    testCases.header("SPOT FX RATE", "VALUE_BS", "VOL_IN", "IMPLD_VOL")

    spotFXRates = np.arange(50, 200, 10) / 100.0

    for spotFXRate in spotFXRates:

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, currencyPair,
                                        FinOptionTypes.EUROPEAN_CALL, 1000000,
                                        "USD")

        valueEuropean = callOption.value(valueDate, spotFXRate,
                                         domDiscountCurve, forDiscountCurve,
                                         model)['v']

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.AMERICAN_CALL, 1000000,
                                        "USD")

        valueAmerican = callOption.value(valueDate, spotFXRate,
                                         domDiscountCurve, forDiscountCurve,
                                         model)['v']

        diff = (valueAmerican - valueEuropean)
        testCases.print(spotFXRate, valueEuropean, valueAmerican, diff)

    for spotFXRate in spotFXRates:

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_PUT, 1000000,
                                        "USD")

        valueEuropean = callOption.value(valueDate, spotFXRate,
                                         domDiscountCurve, forDiscountCurve,
                                         model)['v']

        callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.AMERICAN_PUT, 1000000,
                                        "USD")

        valueAmerican = callOption.value(valueDate, spotFXRate,
                                         domDiscountCurve, forDiscountCurve,
                                         model)['v']

        diff = (valueAmerican - valueEuropean)
        testCases.print(spotFXRate, valueEuropean, valueAmerican, diff)
Ejemplo n.º 23
0
def test_derivativePricingExample():

    valuationDate = FinDate(10, 11, 2011)

    dccType = FinDayCountTypes.ACT_360
    depos = []

    # We do the O/N rate which settles on trade date
    spotDays = 0
    settlementDate = valuationDate.addWorkDays(spotDays)

    depositRate = 0.001410
    depo = FinLiborDeposit(settlementDate, "ON", depositRate, dccType)
    depos.append(depo)

    spotDays = 1
    settlementDate = valuationDate.addWorkDays(spotDays)

    depositRate = 0.001410
    depo = FinLiborDeposit(settlementDate, "TN", depositRate, dccType)
    depos.append(depo)

    spotDays = 2
    settlementDate = valuationDate.addWorkDays(spotDays)

    depositRate = 0.001910
    depo = FinLiborDeposit(settlementDate, "1W", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.002090
    depo = FinLiborDeposit(settlementDate, "2W", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.002490
    depo = FinLiborDeposit(settlementDate, "1M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.003450
    depo = FinLiborDeposit(settlementDate, "2M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.004570
    depo = FinLiborDeposit(settlementDate, "3M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.005230
    depo = FinLiborDeposit(settlementDate, "4M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.005860
    depo = FinLiborDeposit(settlementDate, "5M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.006540
    depo = FinLiborDeposit(settlementDate, "6M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.007080
    depo = FinLiborDeposit(settlementDate, "7M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.007540
    depo = FinLiborDeposit(settlementDate, "8M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.008080
    depo = FinLiborDeposit(settlementDate, "9M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.008570
    depo = FinLiborDeposit(settlementDate, "10M", depositRate, dccType)
    depos.append(depo)

    depositRate = 0.009130
    depo = FinLiborDeposit(settlementDate, "11M", depositRate, dccType)
    depos.append(depo)

    fras = []

    swaps = []
    dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA
    #    dayCountType = FinDayCountTypes.ACT_360
    freqType = FinFrequencyTypes.SEMI_ANNUAL
    swapType = FinLiborSwapTypes.PAYER

    swapRate = 0.0058
    swap = FinLiborSwap(settlementDate, "1Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0060
    swap = FinLiborSwap(settlementDate, "2Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0072
    swap = FinLiborSwap(settlementDate, "3Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0096
    swap = FinLiborSwap(settlementDate, "4Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0124
    swap = FinLiborSwap(settlementDate, "5Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0173
    swap = FinLiborSwap(settlementDate, "7Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0219
    swap = FinLiborSwap(settlementDate, "10Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    swapRate = 0.0283
    swap = FinLiborSwap(settlementDate, "30Y", swapType, swapRate, freqType,
                        dayCountType)
    swaps.append(swap)

    numRepeats = 10
    start = time.time()

    for _ in range(0, numRepeats):
        _ = FinLiborCurve(valuationDate, depos, fras, swaps,
                          FinInterpTypes.FLAT_FORWARDS)

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

    start = time.time()

    for _ in range(0, numRepeats):
        _ = FinLiborCurve(valuationDate, depos, fras, swaps,
                          FinInterpTypes.LINEAR_SWAP_RATES)

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

    testCases.header("METHOD", "TIME")
    testCases.print("NON-LINEAR SOLVER BOOTSTRAP", elapsed1 / numRepeats)
    testCases.print("LINEAR SWAP BOOTSTRAP", elapsed2 / numRepeats)
Ejemplo n.º 24
0
def test_FinIborCapFloorVolCurve():
    ''' Aim here is to price cap and caplets using cap and caplet vols and to
    demonstrate they are the same - NOT SURE THAT HULLS BOOKS FORMULA WORKS FOR
    OPTIONS. '''

    todayDate = FinDate(20, 6, 2019)
    valuationDate = todayDate
    maturityDate = valuationDate.addTenor("3Y")
    dayCountType = FinDayCountTypes.THIRTY_E_360
    frequency = FinFrequencyTypes.ANNUAL

    k = 0.04
    capFloorType = FinCapFloorTypes.CAP
    capFloor = FinIborCapFloor(valuationDate, maturityDate, capFloorType, k,
                               None, frequency, dayCountType)

    capVolDates = FinSchedule(valuationDate, valuationDate.addTenor("10Y"),
                              frequency)._generate()

    flatRate = 0.04
    liborCurve = FinDiscountCurveFlat(valuationDate, flatRate, frequency,
                                      dayCountType)

    flat = False
    if flat is True:
        capVolatilities = [20.0] * 11
        capVolatilities[0] = 0.0
    else:
        capVolatilities = [
            0.00, 15.50, 18.25, 17.91, 17.74, 17.27, 16.79, 16.30, 16.01,
            15.76, 15.54
        ]

    capVolatilities = np.array(capVolatilities) / 100.0
    capVolatilities[0] = 0.0

    volCurve = FinIborCapVolCurve(valuationDate, capVolDates, capVolatilities,
                                  dayCountType)

    #    print(volCurve._capletGammas)

    # Value cap using a single flat cap volatility
    tcap = (maturityDate - valuationDate) / gDaysInYear
    vol = volCurve.capVol(maturityDate)
    model = FinModelBlack(vol)
    valueCap = capFloor.value(valuationDate, liborCurve, model)
    #    print("CAP T", tcap, "VOL:", vol, "VALUE OF CAP:", valueCap)

    # Value cap by breaking it down into caplets using caplet vols
    vCaplets = 0.0
    capletStartDate = capFloor._capFloorLetDates[1]
    testCases.header("START", "END", "VOL", "VALUE")

    for capletEndDate in capFloor._capFloorLetDates[2:]:
        vol = volCurve.capletVol(capletEndDate)
        modelCaplet = FinModelBlack(vol)
        vCaplet = capFloor.valueCapletFloorLet(valuationDate, capletStartDate,
                                               capletEndDate, liborCurve,
                                               modelCaplet)

        vCaplets += vCaplet
        testCases.print("%12s" % capletStartDate, "%s" % capletEndDate,
                        "%9.5f" % (vol * 100.0), "%9.5f" % vCaplet)

        capletStartDate = capletEndDate

    testCases.header("LABEL", "VALUE")
    testCases.print("CAPLETS->CAP: ", vCaplets)
Ejemplo n.º 25
0
def test_FinSwaptionVolSurface1(verboseCalibration):

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

    if 1 == 1:

        # https://fr.mathworks.com/help/fininst/pricing-a-swaption-using-the-sabr-model.html

        valueDate = FinDate(12, 6, 2013)

        # These are 3M, 1Y, 2Y, 3Y, 4Y, 5Y, 7Y, 10Y
        exerciseDates = [
            FinDate(12, 9, 2013),
            FinDate(12, 6, 2014),
            FinDate(12, 6, 2015),
            FinDate(12, 6, 2016),
            FinDate(12, 6, 2017),
            FinDate(12, 6, 2018),
            FinDate(12, 6, 2020),
            FinDate(12, 6, 2023)
        ]

        # First dimension is the strike, then the expiry date
        marketVolatilities = [[57.6, 53.7, 49.4, 45.6, 44.1, 41.1, 35.2, 32.0],
                              [46.6, 46.9, 44.8, 41.6, 39.8, 37.4, 33.4, 31.0],
                              [35.9, 39.3, 39.6, 37.9, 37.2, 34.7, 30.5, 28.9],
                              [34.1, 36.5, 37.8, 36.6, 35.0, 31.9, 28.1, 26.6],
                              [41.0, 41.3, 39.5, 37.8, 36.0, 32.6, 29.0, 26.0],
                              [45.8, 43.4, 41.9, 39.2, 36.9, 33.2, 29.6, 26.3],
                              [50.3, 46.9, 44.0, 40.0, 37.5, 33.8, 30.2, 27.3]]

        marketVolatilities = np.array(marketVolatilities) / 100.0

        # First dimension is the strike, then the expiry date
        marketStrikes = [[1.00, 1.25, 1.68, 2.00, 2.26, 2.41, 2.58, 2.62],
                         [1.50, 1.75, 2.18, 2.50, 2.76, 2.91, 3.08, 3.12],
                         [2.00, 2.25, 2.68, 3.00, 3.26, 3.41, 3.58, 3.62],
                         [2.50, 2.75, 3.18, 3.50, 3.76, 3.91, 4.08, 4.12],
                         [3.00, 3.25, 3.68, 4.00, 4.26, 4.41, 4.58, 4.62],
                         [3.50, 3.75, 4.18, 4.50, 4.76, 4.91, 5.08, 5.12],
                         [4.00, 4.25, 4.68, 5.00, 5.26, 5.41, 5.58, 5.62]]

        marketStrikes = np.array(marketStrikes) / 100.0

        fwdSwapRates = marketStrikes[3]
        atmVols = marketVolatilities[3]

        rfrRate = 0.020  # USD
        discountCurve = FinDiscountCurveFlat(valueDate, rfrRate)

        divRate = 0.010  # USD
        dividendCurve = FinDiscountCurveFlat(valueDate, divRate)

        volFunctionType = FinVolFunctionTypes.SABR_BETA_HALF

        swaptionSurface = FinSwaptionVolSurface(valueDate, exerciseDates,
                                                fwdSwapRates, marketStrikes,
                                                marketVolatilities,
                                                volFunctionType)

        tol = 1e-4
        swaptionSurface.checkCalibration(False, tol)

        if 1 == 1:  # PLOT_GRAPHS:

            swaptionSurface.plotVolCurves()
Ejemplo n.º 26
0
def test_FinIborCapFloorQLExample():

    valuationDate = FinDate(14, 6, 2016)

    dates = [
        FinDate(14, 6, 2016),
        FinDate(14, 9, 2016),
        FinDate(14, 12, 2016),
        FinDate(14, 6, 2017),
        FinDate(14, 6, 2019),
        FinDate(14, 6, 2021),
        FinDate(15, 6, 2026),
        FinDate(16, 6, 2031),
        FinDate(16, 6, 2036),
        FinDate(14, 6, 2046)
    ]

    rates = [
        0.000000, 0.006616, 0.007049, 0.007795, 0.009599, 0.011203, 0.015068,
        0.017583, 0.018998, 0.020080
    ]

    freqType = FinFrequencyTypes.ANNUAL
    dayCountType = FinDayCountTypes.ACT_ACT_ISDA

    discountCurve = FinDiscountCurveZeros(valuationDate, dates, rates,
                                          freqType, dayCountType,
                                          FinInterpTypes.LINEAR_ZERO_RATES)

    startDate = FinDate(14, 6, 2016)
    endDate = FinDate(14, 6, 2026)
    calendarType = FinCalendarTypes.US
    busDayAdjustType = FinBusDayAdjustTypes.MODIFIED_FOLLOWING
    freqType = FinFrequencyTypes.QUARTERLY
    dateGenRuleType = FinDateGenRuleTypes.FORWARD
    lastFixing = 0.0065560
    notional = 1000000
    dayCountType = FinDayCountTypes.ACT_360
    optionType = FinCapFloorTypes.CAP
    strikeRate = 0.02

    cap = FinIborCapFloor(startDate, endDate, optionType, strikeRate,
                          lastFixing, freqType, dayCountType, notional,
                          calendarType, busDayAdjustType, dateGenRuleType)

    blackVol = 0.547295
    model = FinModelBlack(blackVol)

    start = time.time()
    numRepeats = 10
    for i in range(0, numRepeats):
        v = cap.value(valuationDate, discountCurve, model)

    end = time.time()
    period = end - start
Ejemplo n.º 27
0
def test_FinNelsonSiegelCurve():

    tau = 2.0
    times = np.linspace(0.0, 10.0, 5)
    curveDate = FinDate(6, 6, 2019)
    dates = curveDate.addYears(times)

    curve1 = FinDiscountCurveNS(curveDate, 1, 0, 0, tau)
    factor1loading = curve1.zeroRate(dates)
    curve2 = FinDiscountCurveNS(curveDate, 0, 1, 0, tau)
    factor2loading = curve2.zeroRate(dates)
    curve3 = FinDiscountCurveNS(curveDate, 0, 0, 1, tau)
    factor3loading = curve3.zeroRate(dates)

    testCases.header("FACTOR LOADING ON ZERO RATES")
    testCases.print(factor1loading)
    testCases.print(factor2loading)
    testCases.print(factor3loading)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(times, scale(factor1loading, 1), label='beta1')
        plt.plot(times, scale(factor2loading, 1), label='beta2')
        plt.plot(times, scale(factor3loading, 1), label='beta3')
        plt.ylim((0, 1.05))

        plt.title('Factor Loadings in Nelson-Siegel Model')
        plt.xlabel('Time (years)')
        plt.ylabel('Loading')
        plt.legend(loc='best')

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

    testCases.header("BETA1", "BETA2", "BETA3", "ZEROS")

    beta1 = 0.03
    beta2 = -0.02
    beta3 = 0.02
    curve1 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates1 = curve1.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates1)

    beta1 = 0.04
    beta2 = -0.02
    beta3 = 0.02
    curve2 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates2 = curve2.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates2)

    beta1 = 0.05
    beta2 = -0.02
    beta3 = 0.02
    curve3 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates3 = curve3.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates3)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.02
    curve4 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates4 = curve4.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates4)

    beta1 = 0.07
    beta2 = -0.02
    beta3 = 0.02
    curve5 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates5 = curve5.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates5)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(times, scale(zeroRates1, 100), label='beta1=3%')
        plt.plot(times, scale(zeroRates2, 100), label='beta1=4%')
        plt.plot(times, scale(zeroRates3, 100), label='beta1=5%')
        plt.plot(times, scale(zeroRates4, 100), label='beta1=6%')
        plt.plot(times, scale(zeroRates5, 100), label='beta1=7%')
        plt.ylim((0, 7.5))

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

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

    beta1 = 0.06
    beta2 = -0.04
    beta3 = 0.02
    curve1 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates1 = curve1.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates1)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.02
    curve2 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates2 = curve2.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates2)

    beta1 = 0.06
    beta2 = 0.00
    beta3 = 0.02
    curve3 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates3 = curve3.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates3)

    beta1 = 0.06
    beta2 = 0.02
    beta3 = 0.02
    curve4 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates4 = curve4.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates4)

    beta1 = 0.06
    beta2 = 0.04
    beta3 = 0.02
    curve5 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates5 = curve5.zeroRate(dates)
    testCases.print(beta1, beta2, beta3, zeroRates5)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(times, scale(zeroRates1, 100), label='beta2=-4%')
        plt.plot(times, scale(zeroRates2, 100), label='beta2=-2%')
        plt.plot(times, scale(zeroRates3, 100), label='beta2=0%')
        plt.plot(times, scale(zeroRates4, 100), label='beta2=2%')
        plt.plot(times, scale(zeroRates5, 100), label='beta2=4%')
        plt.ylim((0, 10))

        plt.title('Nelson-Siegel Zero Rate Curves: Varying beta2')
        plt.xlabel('Time (years)')
        plt.ylabel('Zero Rate (%)')
        plt.legend(loc='lower right', frameon=False)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = -0.02
    curve1 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates1 = curve1.zeroRate(dates)

    testCases.print(beta1, beta2, beta3, zeroRates1)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.00
    curve2 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates2 = curve2.zeroRate(dates)

    testCases.print(beta1, beta2, beta3, zeroRates2)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.02
    curve3 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates3 = curve3.zeroRate(dates)

    testCases.print(beta1, beta2, beta3, zeroRates3)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.04
    curve4 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates4 = curve4.zeroRate(dates)

    testCases.print(beta1, beta2, beta3, zeroRates4)

    beta1 = 0.06
    beta2 = -0.02
    beta3 = 0.06
    curve5 = FinDiscountCurveNS(curveDate, beta1, beta2, beta3, tau)
    zeroRates5 = curve5.zeroRate(dates)

    testCases.print(beta1, beta2, beta3, zeroRates5)

    if PLOT_GRAPHS:
        plt.figure(figsize=(6, 4))
        plt.plot(times, scale(zeroRates1, 100), label='beta3=-2%')
        plt.plot(times, scale(zeroRates2, 100), label='beta3=0%')
        plt.plot(times, scale(zeroRates3, 100), label='beta3=2%')
        plt.plot(times, scale(zeroRates4, 100), label='beta3=4%')
        plt.plot(times, scale(zeroRates5, 100), label='beta3=6%')
        plt.ylim((3.5, 7.5))

        plt.title('Nelson-Siegel Zero Rate Curves: Varying beta3')
        plt.xlabel('Time (years)')
        plt.ylabel('Zero Rate (%)')
        plt.legend(loc='lower right', frameon=False)
Ejemplo n.º 28
0
def test_FinIborCapFloor():

    todayDate = FinDate(20, 6, 2019)
    valuationDate = todayDate
    startDate = todayDate.addWeekDays(2)
    maturityDate = startDate.addTenor("1Y")
    liborCurve = test_FinIborDepositsAndSwaps(todayDate)

    # The capfloor has begun
    # lastFixing = 0.028

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

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

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

    model1 = FinModelBlack(0.20)
    model2 = FinModelBlackShifted(0.25, 0.0)
    model3 = FinModelSABR(0.013, 0.5, 0.5, 0.5)
    model4 = FinModelSABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
    model5 = FinModelRatesHW(0.30, 0.01)
    model6 = FinModelBachelier(0.01)

    for k in strikes:
        capFloorType = FinCapFloorTypes.CAP
        capfloor = FinIborCapFloor(startDate, maturityDate, capFloorType, k)
        cvalue1 = capfloor.value(valuationDate, liborCurve, model1)
        cvalue2 = capfloor.value(valuationDate, liborCurve, model2)
        cvalue3 = capfloor.value(valuationDate, liborCurve, model3)
        cvalue4 = capfloor.value(valuationDate, liborCurve, model4)
        cvalue5 = capfloor.value(valuationDate, liborCurve, model5)
        cvalue6 = capfloor.value(valuationDate, liborCurve, model6)
        testCases.print("CAP", k, cvalue1, cvalue2, cvalue3, cvalue4, cvalue5,
                        cvalue6)

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

    for k in strikes:
        capFloorType = FinCapFloorTypes.FLOOR
        capfloor = FinIborCapFloor(startDate, maturityDate, capFloorType, k)
        fvalue1 = capfloor.value(valuationDate, liborCurve, model1)
        fvalue2 = capfloor.value(valuationDate, liborCurve, model2)
        fvalue3 = capfloor.value(valuationDate, liborCurve, model3)
        fvalue4 = capfloor.value(valuationDate, liborCurve, model4)
        fvalue5 = capfloor.value(valuationDate, liborCurve, model5)
        fvalue6 = capfloor.value(valuationDate, liborCurve, model6)
        testCases.print("FLR", k, fvalue1, fvalue2, fvalue3, fvalue4, fvalue5,
                        fvalue6)

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

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

    for k in strikes:
        capFloorType = FinCapFloorTypes.CAP
        capfloor = FinIborCapFloor(startDate, maturityDate, capFloorType, k)
        cvalue1 = capfloor.value(valuationDate, liborCurve, model1)
        cvalue2 = capfloor.value(valuationDate, liborCurve, model2)
        cvalue3 = capfloor.value(valuationDate, liborCurve, model3)
        cvalue4 = capfloor.value(valuationDate, liborCurve, model4)
        cvalue5 = capfloor.value(valuationDate, liborCurve, model5)
        cvalue6 = capfloor.value(valuationDate, liborCurve, model6)

        capFloorType = FinCapFloorTypes.FLOOR
        capfloor = FinIborCapFloor(startDate, maturityDate, capFloorType, k)
        fvalue1 = capfloor.value(valuationDate, liborCurve, model1)
        fvalue2 = capfloor.value(valuationDate, liborCurve, model2)
        fvalue3 = capfloor.value(valuationDate, liborCurve, model3)
        fvalue4 = capfloor.value(valuationDate, liborCurve, model4)
        fvalue5 = capfloor.value(valuationDate, liborCurve, model5)
        fvalue6 = capfloor.value(valuationDate, liborCurve, model6)

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

        testCases.print("PUT_CALL", k, pcvalue1, pcvalue2, pcvalue3, pcvalue4,
                        pcvalue5, pcvalue6)
def test_FinEquityVanillaOption():

    valueDate = FinDate(2015, 1, 1)
    expiryDate = FinDate(2015, 7, 1)
    stockPrice = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    model = FinEquityModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    numPathsList = [10000, 20000, 40000, 80000, 160000, 320000]

    testCases.header("NUMPATHS", "VALUE_BS", "VALUE_MC", "TIME")

    for numPaths in numPathsList:

        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        start = time.time()
        valueMC = callOption.valueMC(valueDate, stockPrice, discountCurve,
                                     dividendYield, model, numPaths)
        end = time.time()
        duration = end - start
        testCases.print(numPaths, value, valueMC, duration)

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

    stockPrices = range(80, 120, 10)
    numPaths = 100000

    testCases.header("NUMPATHS", "VALUE_BS", "VALUE_MC", "TIME")
    useSobol = True

    for stockPrice in stockPrices:

        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        start = time.time()

        useSobol = False
        valueMC1 = callOption.valueMC(valueDate, stockPrice, discountCurve,
                                      dividendYield, model, numPaths, useSobol)

        useSobol = True
        valueMC2 = callOption.valueMC(valueDate, stockPrice, discountCurve,
                                      dividendYield, model, numPaths, useSobol)

        end = time.time()
        duration = end - start
        testCases.print(numPaths, value, valueMC, duration)

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

    stockPrices = range(80, 120, 10)
    numPaths = 100000

    testCases.header("STOCK PRICE", "VALUE_BS", "VALUE_MC", "TIME")

    for stockPrice in stockPrices:

        putOption = FinEquityVanillaOption(expiryDate, 100.0,
                                           FinOptionTypes.EUROPEAN_PUT)
        value = putOption.value(valueDate, stockPrice, discountCurve,
                                dividendYield, model)
        start = time.time()
        valueMC = putOption.valueMC(valueDate, stockPrice, discountCurve,
                                    dividendYield, model, numPaths)
        end = time.time()
        duration = end - start
        testCases.print(stockPrice, value, valueMC, duration)

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

    stockPrices = range(80, 120, 10)

    testCases.header("STOCK PRICE", "VALUE_BS", "DELTA_BS", "VEGA_BS",
                     "THETA_BS", "RHO_BS")

    for stockPrice in stockPrices:
        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        delta = callOption.delta(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        vega = callOption.vega(valueDate, stockPrice, discountCurve,
                               dividendYield, model)
        theta = callOption.theta(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        # callOption.rho(valueDate,stockPrice, interestRate, dividendYield, modelType, modelParams)
        rho = 999
        testCases.print(stockPrice, value, delta, vega, theta, rho)

    testCases.header("STOCK PRICE", "VALUE_BS", "DELTA_BS", "VEGA_BS",
                     "THETA_BS", "RHO_BS")

    for stockPrice in stockPrices:
        putOption = FinEquityVanillaOption(expiryDate, 100.0,
                                           FinOptionTypes.EUROPEAN_PUT)
        value = putOption.value(valueDate, stockPrice, discountCurve,
                                dividendYield, model)
        delta = putOption.delta(valueDate, stockPrice, discountCurve,
                                dividendYield, model)
        vega = putOption.vega(valueDate, stockPrice, discountCurve,
                              dividendYield, model)
        theta = putOption.theta(valueDate, stockPrice, discountCurve,
                                dividendYield, model)
        # putOption.rho(valueDate,stockPrice, interestRate, dividendYield,
        # modelType, modelParams)
        rho = 999
        testCases.print(stockPrice, value, delta, vega, theta, rho)

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

    testCases.header("STOCK PRICE", "VALUE_BS", "VOL_IN", "IMPLD_VOL")

    stockPrices = range(60, 150, 10)

    for stockPrice in stockPrices:
        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        impliedVol = callOption.impliedVolatility(valueDate, stockPrice,
                                                  discountCurve, dividendYield,
                                                  value)
        testCases.print(stockPrice, value, volatility, impliedVol)
Ejemplo n.º 30
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
    frequencyType = 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, frequencyType,
                               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))