Exemplo n.º 1
0
def test_FinDateAddYears():

    startDate = FinDate(1, 1, 2010)

    testCases.header("Years", "Dates")

    years = [1, 3, 5, 7, 10]
    dates1 = startDate.addYears(years)
    for dt in dates1:
        testCases.print("DATES1", dt)

    years = np.array([1, 3, 5, 7, 10])
    dates2 = startDate.addYears(years)
    for dt in dates2:
        testCases.print("DATES2", dt)

    years = np.array([1.5, 3.25, 5.75, 7.25, 10.0])
    dates3 = startDate.addYears(years)

    for dt in dates3:
        testCases.print("DATES3", dt)

    dt = 1.0 / 365.0
    years = np.array(
        [1.5 + 2.0 * dt, 3.5 - 6 * dt, 5.75 + 3 * dt, 7.25 + dt, 10.0 + dt])
    dates4 = startDate.addYears(years)

    for dt in dates4:
        testCases.print("DATES4", dt)
Exemplo n.º 2
0
def test_FinDiscountCurve():

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

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

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

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

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

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

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

    # Examine dependency of fwd curve on the interpolation scheme

    for interp in FinInterpTypes:

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

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

            plt.title('Forward Curves using ' + str(interp))
            plt.xlabel('Time (years)')
            plt.ylabel('Fwd Rate (%)')
            plt.legend(loc='lower right', frameon=False)
def test_FinDiscountCurveZeros():

    startDate = FinDate(1, 1, 2018)
    times = np.linspace(1.0, 10.0, 10)
    dates = startDate.addYears(times)
    zeroRates = np.linspace(5.0, 6.0, 10) / 100
    freqType = FinFrequencyTypes.ANNUAL
    dayCountType = FinDayCountTypes.ACT_ACT_ISDA

    curve = FinDiscountCurveZeros(startDate, dates, zeroRates, freqType,
                                  dayCountType, FinInterpTypes.FLAT_FWD_RATES)

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

    years = np.linspace(0, 10, 21)
    dates = startDate.addYears(years)
    for dt in dates:
        df = curve.df(dt)
        testCases.print(dt, df)

#    print(curve)

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

    numRepeats = 100

    start = time.time()

    for i in range(0, numRepeats):
        freqType = FinFrequencyTypes.ANNUAL
        dayCountType = FinDayCountTypes.ACT_ACT_ISDA

        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)
        ]

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

        startDate = dates[0]

        curve = FinDiscountCurveZeros(startDate, dates, zeroRates, freqType,
                                      dayCountType,
                                      FinInterpTypes.FLAT_FWD_RATES)

    end = time.time()
    period = end - start
Exemplo n.º 4
0
def test_BDTExampleOne():
    # HULL BOOK NOTES
    # http://www-2.rotman.utoronto.ca/~hull/technicalnotes/TechnicalNote23.pdf

    valuationDate = FinDate(1, 1, 2020)
    years = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
    zeroDates = valuationDate.addYears(years)
    zeroRates = [0.00, 0.10, 0.11, 0.12, 0.125, 0.13]

    testCases.header("DATES")
    testCases.print(zeroDates)

    testCases.header("RATES")
    testCases.print(zeroRates)

    curve = FinDiscountCurveZeros(valuationDate, zeroDates, zeroRates,
                                  FinFrequencyTypes.ANNUAL)

    yieldVol = 0.16

    numTimeSteps = 5
    tmat = years[-1]
    dfs = curve.df(zeroDates)

    testCases.print("DFS")
    testCases.print(dfs)

    years = np.array(years)
    dfs = np.array(dfs)

    model = FinModelRatesBDT(yieldVol, numTimeSteps)
    model.buildTree(tmat, years, dfs)
Exemplo n.º 5
0
def test_IssuerCurveBuild():
    ''' Test issuer curve build with simple libor curve to isolate cds
    curve building time cost. '''

    valuationDate = FinDate(20, 6, 2018)

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

    cdsContracts = []

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

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

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

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

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

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

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

    return cdsContracts, issuerCurve
Exemplo n.º 6
0
def test_FinInterpolatedForwards():

    import matplotlib.pyplot as plt

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

    curveDate = FinDate(1, 1, 2019)

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

    for interpType in FinInterpTypes:

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

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

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

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

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

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

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

    recoveryRate = 0.40

    contractCoupon = 0.010

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

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

        cdsContracts = []

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

        cdsContracts.append(cdsMkt)

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

        cdsContract = FinCDS(valueDate, maturityDate, contractCoupon)
        v_exact = cdsContract.value(
            valueDate, issuerCurve, recoveryRate)['full_pv']
        v_approx = cdsContract.valueFastApprox(
            valueDate, r, mktCoupon, recoveryRate)[0]
        pctdiff = (v_exact - v_approx) / ONE_MILLION * 100.0
        testCases.print(mktCoupon * 10000, v_exact, v_approx, pctdiff)
Exemplo n.º 8
0
def test_FinDiscountCurvePolynomial():

    times = np.linspace(0.00, 10.0, 21)
    curveDate = FinDate(2019, 2, 2)
    dates = curveDate.addYears(times)
    coeffs = [0.0004, -0.0001, 0.00000010]
    curve1 = FinDiscountCurvePoly(curveDate, coeffs)
    zeros = curve1.zeroRate(dates)
    fwds = curve1.fwd(dates)

    if PLOT_GRAPHS:
        import matplotlib.pyplot as plt
        plt.figure(figsize=(6, 4))
        plt.plot(times, zeros, label="Zeros")
        plt.plot(times, fwds, label="Forwards")
        plt.xlabel('Time (years)')
        plt.ylabel('Zero Rate')
        plt.legend(loc='best')
Exemplo n.º 9
0
def test_FinNelsonSiegelCurve():

    tau = 2.0
    times = np.linspace(0.0, 10.0, 5)
    curveDate = FinDate(2019, 6, 6)
    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)
Exemplo n.º 10
0
def test_FinIborDepositsFuturesSwaps():

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

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

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

    fras = []

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

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

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

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

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

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

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

    spotDays = 2
    startDate = spotDate.addWeekDays(spotDays)

    swaps = []
    fixedLegType = FinSwapTypes.PAY
    fixedDCCType = FinDayCountTypes.THIRTY_E_360
    fixedFreqType = FinFrequencyTypes.SEMI_ANNUAL
    floatFreqType = FinFrequencyTypes.QUARTERLY
    notional = 1000000
    principal = 0.0
    floatSpread = 0.0
    floatDCCType = FinDayCountTypes.ACT_360
    calendarType = FinCalendarTypes.US
    busDayAdjustRule = FinBusDayAdjustTypes.PRECEDING

    swapRate = 0.02776305

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

    swaps.append(swap)

    liborCurve = FinIborSingleCurveOLD(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)
Exemplo n.º 11
0
def test_FinBondOption():

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

    times = np.linspace(0, 10.0, 21)
    dfs = np.exp(-0.05 * times)
    dates = settlementDate.addYears(times)
    discountCurve = FinDiscountCurve(settlementDate, dates, dfs)

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

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

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

    optionType = FinOptionTypes.EUROPEAN_CALL

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

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

    numTimeSteps = 100

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

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

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

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

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

    optionType = FinOptionTypes.AMERICAN_CALL

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

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

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

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

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

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

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

    price = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.01
        a = 0.1

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

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

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

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

    price = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.02
        a = 0.1

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

        model = FinModelRatesHW(sigma, a)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print(strikePrice, v)
Exemplo n.º 12
0
def test_BDTExampleThree():
    # Valuation of a swaption as in Leif Andersen's paper - see Table 1 on
    # SSRN-id155208.pdf

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

    # This is a sanity check
    testBlackModelCheck()

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

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

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

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

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

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

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

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

                expiryDate = settlementDate.addYears(expiryYears)

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

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

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

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

                price = bond.cleanPriceFromDiscountCurve(settlementDate, curve)

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

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

                testCases.print("%s" % exerciseType, "%9.5f" % sigma,
                                "%9.5f" % numTimeSteps, "%9.5f" % expiryYears,
                                "%9.5f" % maturityYears, "%9.5f" % price,
                                "%9.2f" % (v['pay'] * 100.0),
                                "%9.2f" % (v['rec'] * 100.0))
Exemplo n.º 13
0
def test_FinBondOption():

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

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

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

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

    strikes = [80, 90, 100, 110, 120]

    optionType = FinOptionTypes.EUROPEAN_CALL

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

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

    numTimeSteps = 100

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

    for strikePrice in strikes:

        sigma = 0.20

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

    for strikePrice in strikes:

        sigma = 0.20

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

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

    optionType = FinOptionTypes.AMERICAN_CALL

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

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

    for strikePrice in strikes:

        sigma = 0.20

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

    for strikePrice in strikes:

        sigma = 0.20

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

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

    optionType = FinOptionTypes.EUROPEAN_PUT

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.01

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

    for strikePrice in strikes:

        sigma = 0.20

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

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

    optionType = FinOptionTypes.AMERICAN_PUT

    price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve)

    for strikePrice in strikes:

        sigma = 0.02

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

    for strikePrice in strikes:

        sigma = 0.20

        bondOption = FinBondOption(bond, expiryDate, strikePrice, face,
                                   optionType)
        model = FinModelRatesBDT(sigma, numTimeSteps)
        v = bondOption.value(settlementDate, discountCurve, model)
        testCases.print("AMERICAN PUT - BK", strikePrice, v)
Exemplo n.º 14
0
def test_FinFXMktVolSurface3(verboseCalibration):

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

    if 1 == 1:

        # Example from Book extract by Iain Clark using Tables 4.4 and 4.5
        # where we examine the calibration to a full surface in Chapter 4

        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 = ['1Y', '2Y']
        atmVols = [18.250, 17.677]
        marketStrangle25DeltaVols = [0.95, 0.85]
        riskReversal25DeltaVols = [-0.60, -0.562]
        marketStrangle10DeltaVols = [3.806, 3.208]
        riskReversal10DeltaVols = [-1.359, -1.208]

        notionalCurrency = forName

        # I HAVE NO YET MADE DELTA METHOD A VECTOR FOR EACH TERM AS I WOULD
        # NEED TO DO AS DESCRIBED IN CLARK PAGE 70
        
        atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
        deltaMethod = FinFXDeltaMethod.FORWARD_DELTA # THIS IS DIFFERENT
        volFunctionType = FinVolFunctionTypes.CLARK5
        alpha = 0.5 # FIT WINGS AT 10D if ALPHA = 1.0

        fxMarketPlus = FinFXVolSurfacePlus(valueDate,
                                       spotFXRate,
                                       currencyPair,
                                       notionalCurrency,
                                       domDiscountCurve,
                                       forDiscountCurve,
                                       tenors,
                                       atmVols,
                                       marketStrangle25DeltaVols,
                                       riskReversal25DeltaVols,
                                       marketStrangle10DeltaVols,
                                       riskReversal10DeltaVols,
                                       alpha,
                                       atmMethod,
                                       deltaMethod, 
                                       volFunctionType)

        fxMarketPlus.checkCalibration(False)

        if 1==0: # PLOT_GRAPHS:

            fxMarketPlus.plotVolCurves()

            plt.figure()

            dbns = fxMarketPlus.impliedDbns(0.5, 2.0, 1000)

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

        # Test interpolation
        
        years = [1.0, 1.5, 2.0]
        dates = valueDate.addYears(years)

        strikes = np.linspace(1.0, 2.0, 20)

        if 1==0:
            volSurface = []        
            for k in strikes:
                volSmile = []
                for dt in dates:
                    vol = fxMarketPlus.volatilityFromStrikeDate(k, dt)
                    volSmile.append(vol*100.0)
                    
                    print(k, dt, vol*100.0)
                volSurface.append(volSmile)
    
            fig = plt.figure()
            ax = fig.add_subplot(111, projection='3d')
            X, Y = np.meshgrid(years, strikes)
            zs = np.array(volSurface)
            Z = zs.reshape(X.shape)
            
            ax.plot_surface(X, Y, Z)
            
            ax.set_xlabel('Years')
            ax.set_ylabel('Strikes')
            ax.set_zlabel('Volatility')
            
            plt.show()

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

        deltas = np.linspace(0.10, 0.90, 17)

        if 1==0:
            volSurface = []        
            for delta in deltas:
                volSmile = []
                for dt in dates:
                    (vol, k) = fxMarketPlus.volatilityFromDeltaDate(delta, dt)
                    volSmile.append(vol*100.0)
                    print(delta, k, dt, vol*100.0)

                volSurface.append(volSmile)
    
            fig = plt.figure()
            ax = fig.add_subplot(111, projection='3d')
            X, Y = np.meshgrid(years, deltas)
            zs = np.array(volSurface)
            Z = zs.reshape(X.shape)
            
            ax.plot_surface(X, Y, Z)
            
            ax.set_xlabel('Years')
            ax.set_ylabel('Delta')
            ax.set_zlabel('Volatility')
            
            plt.show()
Exemplo n.º 15
0
def testImpliedVolatility_NEW():


    valueDate = FinDate(1, 1, 2015)
    stockPrice = 100.0
    interestRate = 0.05
    dividendYield = 0.03
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

    strikes = np.linspace(50, 150, 11)
    timesToExpiry = [0.003, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0]    
    sigmas = np.arange(1, 100, 5) / 100.0
    optionTypes = [FinOptionTypes.EUROPEAN_CALL, FinOptionTypes.EUROPEAN_PUT]

    testCases.header("OPT_TYPE", "TEXP", "STOCK_PRICE", "STRIKE", "INTRINSIC",
                     "VALUE", "INPUT_VOL", "IMPLIED_VOL")
    
    tol = 1e-5
    numTests = 0
    numFails = 0
    
    for vol in sigmas:

        model = FinModelBlackScholes(vol)

        for timeToExpiry in timesToExpiry:     

            expiryDate = valueDate.addYears(timeToExpiry)

            for strike in strikes:

                for optionType in optionTypes:

                    option = FinEquityVanillaOption(expiryDate, strike, 
                                                    optionType)
                
                    value = option.value(valueDate, stockPrice, discountCurve, 
                                         dividendCurve, model)

                    intrinsic = option.intrinsic(valueDate, stockPrice,
                                             discountCurve, dividendCurve)

                    # I remove the cases where the time value is zero
                    # This is arbitrary but 1e-10 seems good enough to me
                    
                    impliedVol = -999

                    if value - intrinsic > 1e-10:

                        impliedVol = option.impliedVolatility(valueDate, 
                                                              stockPrice, 
                                                              discountCurve, 
                                                              dividendCurve, 
                                                              value)
    
                    numTests += 1    
                        
                    errVol = np.abs(impliedVol - vol)
    
                    if errVol > tol:
    
                        testCases.print(optionType, 
                                  timeToExpiry, 
                                  stockPrice,
                                  strike, 
                                  intrinsic,
                                  value, 
                                  vol, 
                                  impliedVol)

                        # These fails include ones due to the zero time value    
                        numFails += 1
                            
                        testCases.print(optionType, timeToExpiry, stockPrice,
                                        strike,
                                        stockPrice, value, vol, impliedVol)

    assert numFails == 694, "Num Fails has changed."
Exemplo n.º 16
0
def test_FinFXMktVolSurface4(verboseCalibration):

    ###########################################################################
    # Here I remove the 25D Vols
    ###########################################################################

    if 1 == 1:

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

        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
        ]

        marketStrangle25DeltaVols = None
        riskReversal25DeltaVols = None

        notionalCurrency = forName

        atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
        deltaMethod = FinFXDeltaMethod.SPOT_DELTA
        volFunctionType = FinVolFunctionTypes.CLARK
        alpha = 0.50  # FIT WINGS AT 10D if ALPHA = 1.0

        fxMarketPlus = FinFXVolSurfacePlus(
            valueDate, spotFXRate, currencyPair, notionalCurrency,
            domDiscountCurve, forDiscountCurve, tenors, atmVols,
            marketStrangle25DeltaVols, riskReversal25DeltaVols,
            marketStrangle10DeltaVols, riskReversal10DeltaVols, alpha,
            atmMethod, deltaMethod, volFunctionType)

        fxMarketPlus.checkCalibration(False)

        years = [1.0 / 12.0, 2. / 12., 0.25, 0.5, 1.0, 2.0]

        dates = valueDate.addYears(years)

        deltas = np.linspace(0.10, 0.90, 17)

        if 1 == 1:
            volSurface = []
            for delta in deltas:
                volSmile = []
                for dt in dates:
                    (vol, k) = fxMarketPlus.volatilityFromDeltaDate(delta, dt)
                    volSmile.append(vol * 100.0)
                    print(delta, k, dt, vol * 100.0)

                volSurface.append(volSmile)

            fig = plt.figure()
            ax = fig.add_subplot(111, projection='3d')
            X, Y = np.meshgrid(years, deltas)
            zs = np.array(volSurface)
            Z = zs.reshape(X.shape)

            ax.plot_surface(X, Y, Z)

            ax.set_xlabel('Years')
            ax.set_ylabel('Delta')
            ax.set_zlabel('Volatility')
            plt.title("EURUSD Volatility Surface")
            plt.show()
Exemplo n.º 17
0
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)
Exemplo n.º 18
0
def test_BDTExampleTwo():
    # Valuation of a European option on a coupon bearing bond
    # This follows example in Fig 28.11 of John Hull's book (6th Edition)
    # but does not have the exact same dt so there are some differences

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

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

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

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

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

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

    strikePrice = 105.0
    face = 100.0

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

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

    curve = FinDiscountCurve(settlementDate, dates, dfs)

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

    sigma = 0.20

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

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

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

    if PLOT_GRAPHS:
        plt.plot(numStepsList, treeVector)

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

    if 1 == 0:
        print("RT")
        printTree(model._rt, 5)
        print("Q")
        printTree(model._Q, 5)
Exemplo n.º 19
0
def buildFullIssuerCurve2(mktSpreadBump, irBump):

    # https://www.markit.com/markit.jsp?jsppage=pv.jsp
    # YIELD CURVE 20 August 2020 SNAP AT 1600

    m = 1.0

    settlementDate = FinDate(24, 8, 2020)
    dcType = FinDayCountTypes.ACT_360
    depos = []

    maturityDate = settlementDate.addMonths(1)
    depo1 = FinLiborDeposit(settlementDate, maturityDate, m * 0.001709, dcType)

    maturityDate = settlementDate.addMonths(2)
    depo2 = FinLiborDeposit(settlementDate, maturityDate, m * 0.002123, dcType)

    maturityDate = settlementDate.addMonths(3)
    depo3 = FinLiborDeposit(settlementDate, maturityDate, m * 0.002469, dcType)

    maturityDate = settlementDate.addMonths(6)
    depo4 = FinLiborDeposit(settlementDate, maturityDate, m * 0.003045, dcType)

    maturityDate = settlementDate.addMonths(12)
    depo5 = FinLiborDeposit(settlementDate, maturityDate, m * 0.004449, dcType)

    depos.append(depo1)
    depos.append(depo2)
    depos.append(depo3)
    depos.append(depo4)
    depos.append(depo5)

    swaps = []
    dcType = FinDayCountTypes.THIRTY_E_360_ISDA
    fixedFreq = FinFrequencyTypes.SEMI_ANNUAL

    maturityDate = settlementDate.addMonths(24)
    swap1 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER,
                         m * 0.002155 + irBump, fixedFreq, dcType)
    swaps.append(swap1)

    maturityDate = settlementDate.addMonths(36)
    swap2 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER,
                         m * 0.002305 + irBump, fixedFreq, dcType)
    swaps.append(swap2)

    maturityDate = settlementDate.addMonths(48)
    swap3 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER,
                         m * 0.002665 + irBump, fixedFreq, dcType)
    swaps.append(swap3)

    maturityDate = settlementDate.addMonths(60)
    swap4 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER,
                         m * 0.003290 + irBump, fixedFreq, dcType)
    swaps.append(swap4)

    liborCurve = FinLiborCurve(settlementDate, depos, [], swaps)

    cdsCoupon = 0.01 + mktSpreadBump

    cdsMarketContracts = []
    effectiveDate = FinDate(21, 8, 2020)
    cds = FinCDS(effectiveDate, "6M", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "1Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "2Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "3Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "4Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "5Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "7Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    cds = FinCDS(effectiveDate, "10Y", cdsCoupon)
    cdsMarketContracts.append(cds)

    recoveryRate = 0.40

    issuerCurve = FinCDSCurve(settlementDate, cdsMarketContracts, liborCurve,
                              recoveryRate)

    testCases.header("DATE", "DISCOUNT_FACTOR", "SURV_PROB")
    years = np.linspace(0.0, 10.0, 20)
    dates = settlementDate.addYears(years)
    for dt in dates:
        df = liborCurve.df(dt)
        q = issuerCurve.survProb(dt)
        testCases.print("%16s" % dt, "%12.8f" % df, "%12.8f" % q)

    return liborCurve, issuerCurve
Exemplo n.º 20
0
def test_FinDiscountCurves():

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if PLOT_GRAPHS:

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

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

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

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

        plt.figure()
        for name, curve in zip(curveNames, curvesList):
            dfs = curve.df(fwdDates)
            plt.plot(years, dfs, label=name)
        plt.legend()
        plt.title("Discount Factors")
def testImpliedVolatility():

    valueDate = FinDate(1, 1, 2015)
    stockPrice = 100
    interestRate = 0.05
    dividendYield = 0.01
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    strikes = [10, 20, 50, 100, 150, 200]
    timesToExpiry = [0.003, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0]
    expiryDates = valueDate.addYears(timesToExpiry)
    sigmas = [0.01, 0.10, 0.50, 1.0]
    optionTypes = [FinOptionTypes.EUROPEAN_CALL, FinOptionTypes.EUROPEAN_PUT]

    testCases.header("OPT_TYPE", "EXP_DATE", "STRIKE", "STOCK_PRICE", "VALUE",
                     "INPUT_VOL", "IMPLIED_VOL")

    tol = 1e-6
    numTests = 0
    numFails = 0

    for vol in sigmas:

        model = FinModelBlackScholes(vol)

        for expiryDate in expiryDates:

            for strike in strikes:

                for optionType in optionTypes:

                    option = FinEquityVanillaOption(expiryDate, 100.0,
                                                    optionType)

                    value = option.value(valueDate, stockPrice, discountCurve,
                                         dividendYield, model)

                    impliedVol = option.impliedVolatility(
                        valueDate, stockPrice, discountCurve, dividendYield,
                        value)

                    numTests += 1
                    if np.abs(impliedVol - vol) > tol:
                        numFails += 1

#                    print(optionType, expiryDate, strike,
#                          stockPrice, value, vol, impliedVol)

                    testCases.print(optionType, expiryDate, strike, stockPrice,
                                    value, vol, impliedVol)

    print("Num Tests", numTests, "numFails", numFails)

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

    K = [10, 20, 50, 100, 150, 200]
    T = [0.003, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0]
    sigma = [0.01, 0.10, 0.50, 1.0]
    optionTypes = [FinOptionTypes.EUROPEAN_CALL, FinOptionTypes.EUROPEAN_PUT]
    stockPrice = 100
    HOURS_PER_YEAR = 365.25 * 24
    convergenceFailure = 0
    assertionFailure = 0
    noResult = 0
    successful = 0
    numberTests = 0
    totalElapsedTime = 0.
    for t in T:
        expDate = valueDate.addHours(t * HOURS_PER_YEAR)
        for k in K:
            for vol in sigma:
                bs_model = FinModelBlackScholes(vol)
                for type_ in optionTypes:
                    option = FinEquityVanillaOption(expDate, k, type_)
                    value = option.value(valueDate, stockPrice, discountCurve,
                                         dividendYield, bs_model)
                    if value < 1e-10:
                        continue
                    try:
                        start_time = time.time()
                        impliedVol = option.impliedVolatility_v2(
                            valueDate, stockPrice, discountCurve,
                            dividendYield, value)
                        assert abs(impliedVol - vol) < 0.10
                    except FinError:
                        noResult += 1
                    except AssertionError:
                        assertionFailure += 1
                        print("-----------------")
                        print(
                            f"Did not converge to expected value: {round(impliedVol, 2)} vs {vol}"
                        )
                        print("INPUTS\n", "Type:", type_.name, "ttm:", t,
                              "strike:", k, "Expected IV:", vol, "BS Price:",
                              value)
                    except RuntimeError:
                        import traceback
                        traceback.print_exc()
                        convergenceFailure += 1
                        print("INPUTS\n", "Type:", type_.name, "ttm:", t,
                              "strike:", k, "Expected IV:", vol)
                    except Exception:
                        import traceback
                        traceback.print_exc()
                        noResult += 1
                    else:
                        successful += 1
                        totalElapsedTime += time.time() - start_time
                    finally:
                        numberTests += 1

    print("\nSuccessful:", successful)
    print("Convergence failure:", convergenceFailure)
    print("Inaccurate result:", assertionFailure)
    print("No result (price too low)", noResult)
    print("TOTAL:", numberTests)
    print("Mean time:", 1e6 * totalElapsedTime / successful, "us")