def test_BondOptionAmericanConvergenceONE():

    # Build discount curve
    settlement_date = Date(1, 12, 2019)
    discount_curve = DiscountCurveFlat(settlement_date, 0.05)

    # Bond details
    issue_date = Date(1, 9, 2014)
    maturity_date = Date(1, 9, 2025)
    coupon = 0.05
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    # Option Details
    expiry_date = Date(1, 12, 2020)
    strike_price = 100.0
    face = 100.0

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

    timeSteps = range(100, 500, 100)

    for num_time_steps in timeSteps:

        sigma = 0.05
        a = 0.1

        start = time.time()

        option_type = FinOptionTypes.AMERICAN_PUT
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model1 = HWTree(sigma, a, num_time_steps)
        v1put = bond_option1.value(settlement_date, discount_curve, model1)

        option_type = FinOptionTypes.EUROPEAN_PUT
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_ONLY)
        v2put = bond_option2.value(settlement_date, discount_curve, model2)

        option_type = FinOptionTypes.AMERICAN_CALL
        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model1 = HWTree(sigma, a, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model1)

        option_type = FinOptionTypes.EUROPEAN_CALL
        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_TREE)
        v2call = bond_option2.value(settlement_date, discount_curve, model2)

        end = time.time()

        period = end - start

        testCases.print(period, num_time_steps, v1put, v2put, v1call, v2call)
def test_BondOptionAmericanConvergenceTWO():

    # Build discount curve
    settlement_date = Date(1, 12, 2019)
    discount_curve = DiscountCurveFlat(settlement_date, 0.05,
                                       FrequencyTypes.CONTINUOUS)

    # Bond details
    issue_date = Date(1, 9, 2014)
    maturity_date = Date(1, 9, 2025)
    coupon = 0.05
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)
    expiry_date = settlement_date.add_tenor("18m")
    face = 100.0

    spotValue = bond.full_price_from_discount_curve(settlement_date,
                                                    discount_curve)
    testCases.header("LABEL", "VALUE")
    testCases.print("BOND PRICE", spotValue)

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

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

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

    if 1 == 1:
        K = 100.0
        bkModel = BKTree(sigma, a, 100)
        europeanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.EUROPEAN_CALL)

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

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

    for num_steps in num_stepsVector:

        bkModel = BKTree(sigma, a, num_steps)

        start = time.time()

        europeanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.EUROPEAN_CALL)
        v_ec = europeanCallBondOption.value(settlement_date, discount_curve,
                                            bkModel)

        americanCallBondOption = BondOption(bond, expiry_date, K, face,
                                            FinOptionTypes.AMERICAN_CALL)
        v_ac = americanCallBondOption.value(settlement_date, discount_curve,
                                            bkModel)

        europeanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           FinOptionTypes.EUROPEAN_PUT)
        v_ep = europeanPutBondOption.value(settlement_date, discount_curve,
                                           bkModel)

        americanPutBondOption = BondOption(bond, expiry_date, K, face,
                                           FinOptionTypes.AMERICAN_PUT)
        v_ap = americanPutBondOption.value(settlement_date, discount_curve,
                                           bkModel)

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

        testCases.print(period, num_steps, v_ec, v_ac, v_ep, v_ap)

        vec_ec.append(v_ec)
        vec_ac.append(v_ac)
        vec_ep.append(v_ep)
        vec_ap.append(v_ap)

    if plotGraphs:

        plt.figure()
        plt.plot(num_stepsVector, vec_ec, label="European Call")
        plt.legend()

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

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

        plt.figure()
        plt.plot(num_stepsVector, vec_ap, label="American Put")
        plt.legend()
def test_BondOptionZEROVOLConvergence():

    # Build discount curve
    settlement_date = Date(1, 9, 2019)
    rate = 0.05
    discount_curve = DiscountCurveFlat(settlement_date, rate,
                                       FrequencyTypes.ANNUAL)

    # Bond details
    issue_date = Date(1, 9, 2014)
    maturity_date = Date(1, 9, 2025)
    coupon = 0.06
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    # Option Details
    expiry_date = Date(1, 12, 2021)
    face = 100.0

    dfExpiry = discount_curve.df(expiry_date)
    fwdCleanValue = bond.clean_price_from_discount_curve(
        expiry_date, discount_curve)
    fwdFullValue = bond.full_price_from_discount_curve(expiry_date,
                                                       discount_curve)
    #    print("BOND FwdCleanBondPx", fwdCleanValue)
    #    print("BOND FwdFullBondPx", fwdFullValue)
    #    print("BOND Accrued:", bond._accrued_interest)

    spotCleanValue = bond.clean_price_from_discount_curve(
        settlement_date, discount_curve)

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

    num_time_steps = range(100, 1000, 100)
    strike_prices = [90, 100, 110, 120]

    for strike_price in strike_prices:

        callIntrinsic = max(spotCleanValue - strike_price, 0)
        putIntrinsic = max(strike_price - spotCleanValue, 0)
        callIntrinsicPV = max(fwdCleanValue - strike_price, 0) * dfExpiry
        putIntrinsicPV = max(strike_price - fwdCleanValue, 0) * dfExpiry

        for num_steps in num_time_steps:

            sigma = 0.0000001
            a = 0.1
            model = BKTree(sigma, a, num_steps)

            option_type = FinOptionTypes.EUROPEAN_CALL
            bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v1 = bond_option1.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.AMERICAN_CALL
            bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v2 = bond_option2.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.EUROPEAN_PUT
            bond_option3 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v3 = bond_option3.value(settlement_date, discount_curve, model)

            option_type = FinOptionTypes.AMERICAN_PUT
            bond_option4 = BondOption(bond, expiry_date, strike_price, face,
                                      option_type)
            v4 = bond_option4.value(settlement_date, discount_curve, model)

            testCases.print(strike_price, num_steps, callIntrinsic,
                            callIntrinsicPV, v1, v2, putIntrinsic,
                            putIntrinsicPV, v3, v4)
def test_BondEmbeddedOptionQUANTLIB():

    # Based on example at the nice blog on Quantlib at
    # http://gouthamanbalaraman.com/blog/callable-bond-quantlib-python.html
    # I get a price of 68.97 for 1000 time steps which is higher than the
    # 68.38 found in blog article. But this is for 40 grid points.
    # Note also that a basis point vol of 0.120 is 12% which is VERY HIGH!

    valuation_date = Date(16, 8, 2016)
    settlement_date = valuation_date.addWeekDays(3)

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

    discount_curve = DiscountCurveFlat(valuation_date, 0.035,
                                       FrequencyTypes.SEMI_ANNUAL)

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

    issue_date = Date(15, 9, 2010)
    maturity_date = Date(15, 9, 2022)
    coupon = 0.025
    freq_type = FrequencyTypes.QUARTERLY
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

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

    nextCallDate = Date(15, 9, 2016)
    call_dates = [nextCallDate]
    call_prices = [100.0]

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

    put_dates = []
    put_prices = []

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

    puttableBond = BondEmbeddedOption(issue_date,
                                      maturity_date, coupon,
                                      freq_type, accrual_type,
                                      call_dates, call_prices,
                                      put_dates, put_prices)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.clean_price_from_discount_curve(settlement_date, discount_curve)
    testCases.print("Bond Pure Price:", v)

    testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure")
    timeSteps = range(100, 1000, 100)
    values = []
    for numTimeSteps in timeSteps:
        model = FinModelRatesHW(sigma, a, numTimeSteps)
        start = time.time()
        v = puttableBond.value(settlement_date, discount_curve, model)
        end = time.time()
        period = end - start
        testCases.print(period, numTimeSteps, v['bondwithoption'], v['bondpure'])
        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.title("Puttable Bond Price Convergence")
        plt.plot(timeSteps, values)
def test_EquityOneTouchOption():
    # Examples Haug Page 180 Table 4-22
    # Agreement not exact at t is not exactly 0.50

    valuation_date = Date(1, 1, 2016)
    expiry_date = Date(2, 7, 2016)
    interest_rate = 0.10
    volatility = 0.20
    barrier_level = 100.0  # H
    model = BlackScholes(volatility)
    dividend_yield = 0.03
    num_paths = 10000
    num_steps_per_year = 252

    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    stock_price = 105.0
    payment_size = 15.0

    testCases.header("================================= CASH ONLY")

    downTypes = [
        FinTouchOptionPayoffTypes.DOWN_AND_IN_CASH_AT_HIT,
        FinTouchOptionPayoffTypes.DOWN_AND_IN_CASH_AT_EXPIRY,
        FinTouchOptionPayoffTypes.DOWN_AND_OUT_CASH_OR_NOTHING
    ]

    testCases.header("TYPE", "VALUE", "VALUE_MC")

    for downType in downTypes:

        option = EquityOneTouchOption(expiry_date, downType, barrier_level,
                                      payment_size)

        v = option.value(valuation_date, stock_price, discount_curve,
                         dividend_curve, model)

        v_mc = option.value_mc(valuation_date, stock_price, discount_curve,
                               dividend_curve, model, num_steps_per_year,
                               num_paths)

        testCases.print("%60s " % downType, "%9.5f" % v, "%9.5f" % v_mc)

    stock_price = 95.0
    payment_size = 15.0

    upTypes = [
        FinTouchOptionPayoffTypes.UP_AND_IN_CASH_AT_HIT,
        FinTouchOptionPayoffTypes.UP_AND_IN_CASH_AT_EXPIRY,
        FinTouchOptionPayoffTypes.UP_AND_OUT_CASH_OR_NOTHING
    ]

    testCases.header("TYPE", "VALUE", "VALUE_MC")

    for upType in upTypes:

        option = EquityOneTouchOption(expiry_date, upType, barrier_level,
                                      payment_size)

        v = option.value(valuation_date, stock_price, discount_curve,
                         dividend_curve, model)

        v_mc = option.value_mc(valuation_date, stock_price, discount_curve,
                               dividend_curve, model, num_steps_per_year,
                               num_paths)

        testCases.print("%60s " % upType, "%9.5f" % v, "%9.5f" % v_mc)

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

    stock_price = 105.0

    testCases.banner("================= ASSET ONLY")

    downTypes = [
        FinTouchOptionPayoffTypes.DOWN_AND_IN_ASSET_AT_HIT,
        FinTouchOptionPayoffTypes.DOWN_AND_IN_ASSET_AT_EXPIRY,
        FinTouchOptionPayoffTypes.DOWN_AND_OUT_ASSET_OR_NOTHING
    ]

    testCases.header("TYPE", "VALUE", "VALUE_MC")
    for downType in downTypes:

        option = EquityOneTouchOption(expiry_date, downType, barrier_level)

        v = option.value(valuation_date, stock_price, discount_curve,
                         dividend_curve, model)

        v_mc = option.value_mc(valuation_date, stock_price, discount_curve,
                               dividend_curve, model, num_steps_per_year,
                               num_paths)

        testCases.print("%60s " % downType, "%9.5f" % v, "%9.5f" % v_mc)

    stock_price = 95.0

    upTypes = [
        FinTouchOptionPayoffTypes.UP_AND_IN_ASSET_AT_HIT,
        FinTouchOptionPayoffTypes.UP_AND_IN_ASSET_AT_EXPIRY,
        FinTouchOptionPayoffTypes.UP_AND_OUT_ASSET_OR_NOTHING
    ]

    for upType in upTypes:

        option = EquityOneTouchOption(expiry_date, upType, barrier_level)

        v = option.value(valuation_date, stock_price, discount_curve,
                         dividend_curve, model)

        v_mc = option.value_mc(valuation_date, stock_price, discount_curve,
                               dividend_curve, model, num_steps_per_year,
                               num_paths)

        testCases.print("%60s " % upType, "%9.5f" % v, "%9.5f" % v_mc)
Esempio n. 6
0
def test_FinInflationBondStack():

    ##########################################################################
    # https://stackoverflow.com/questions/57676724/failing-to-obtain-correct-accrued-interest-with-quantlib-inflation-bond-pricer-i
    ##########################################################################

    testCases.banner("=============================")
    testCases.banner("QUANT FINANCE US TIPS EXAMPLE")
    testCases.banner("=============================")
    settlement_date = Date(23, 8, 2019)
    issue_date = Date(25, 9, 2013)
    maturity_date = Date(22, 3, 2068)
    coupon = 0.00125
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    face = 100.0
    baseCPIValue = 249.70

    ###########################################################################
    # Discount curve
    discount_curve = DiscountCurveFlat(settlement_date, 0.01033692,
                                       FrequencyTypes.ANNUAL,
                                       DayCountTypes.ACT_ACT_ISDA)

    lag = 3
    fixingCPI = 244.65884
    fixingDate = settlement_date.add_months(-lag)

    ###########################################################################
    # Create Index Curve
    months = range(0, 12, 1)
    fixingDates = Date(31, 8, 2018).add_months(months)
    fixingRates = [
        284.2, 284.1, 284.5, 284.6, 285.6, 283.0, 285.0, 285.1, 288.2, 289.2,
        289.6, 289.5
    ]
    inflationIndex = FinInflationIndexCurve(fixingDates, fixingRates, lag)
    #    print(inflationIndex)
    ###########################################################################

    zciisData = [(Date(31, 7, 2020), 3.1500000000137085),
                 (Date(31, 7, 2021), 3.547500000013759),
                 (Date(31, 7, 2022), 3.675000000013573),
                 (Date(31, 7, 2023), 3.7250000000134342),
                 (Date(31, 7, 2024), 3.750000000013265),
                 (Date(31, 7, 2025), 3.7430000000129526),
                 (Date(31, 7, 2026), 3.741200000012679),
                 (Date(31, 7, 2027), 3.7337000000123632),
                 (Date(31, 7, 2028), 3.725000000011902),
                 (Date(31, 7, 2029), 3.720000000011603),
                 (Date(31, 7, 2030), 3.712517289063011),
                 (Date(31, 7, 2031), 3.7013000000108764),
                 (Date(31, 7, 2032), 3.686986039205209),
                 (Date(31, 7, 2033), 3.671102614032895),
                 (Date(31, 7, 2034), 3.655000000009778),
                 (Date(31, 7, 2035), 3.6394715951305834),
                 (Date(31, 7, 2036), 3.624362044800966),
                 (Date(31, 7, 2037), 3.6093619727979087),
                 (Date(31, 7, 2038), 3.59421438364369),
                 (Date(31, 7, 2039), 3.5787000000081948),
                 (Date(31, 7, 2040), 3.5626192748395624),
                 (Date(31, 7, 2041), 3.545765016376823),
                 (Date(31, 7, 2042), 3.527943521613608),
                 (Date(31, 7, 2043), 3.508977137925462),
                 (Date(31, 7, 2044), 3.48870000000685),
                 (Date(31, 7, 2045), 3.467083068721011),
                 (Date(31, 7, 2046), 3.4445738220594935),
                 (Date(31, 7, 2047), 3.4216470902302065),
                 (Date(31, 7, 2048), 3.3986861494999188),
                 (Date(31, 7, 2049), 3.376000000005752),
                 (Date(31, 7, 2050), 3.3538412080641233),
                 (Date(31, 7, 2051), 3.3324275806807746),
                 (Date(31, 7, 2052), 3.311938788306623),
                 (Date(31, 7, 2053), 3.2925208131865835),
                 (Date(31, 7, 2054), 3.274293040759302),
                 (Date(31, 7, 2055), 3.2573541974782794),
                 (Date(31, 7, 2056), 3.241787355503245),
                 (Date(31, 7, 2057), 3.227664186159851),
                 (Date(31, 7, 2058), 3.2150486140060774),
                 (Date(31, 7, 2059), 3.204000000004159),
                 (Date(31, 7, 2060), 3.1945334946674064),
                 (Date(31, 7, 2061), 3.1865047145143377),
                 (Date(31, 7, 2062), 3.179753073456304),
                 (Date(31, 7, 2063), 3.1741427790361154),
                 (Date(31, 7, 2064), 3.1695593261025223),
                 (Date(31, 7, 2065), 3.1659065919088736),
                 (Date(31, 7, 2066), 3.163104428386987),
                 (Date(31, 7, 2067), 3.1610866681252903),
                 (Date(31, 7, 2068), 3.1597994770515836),
                 (Date(31, 7, 2069), 3.159200000003204),
                 (Date(31, 7, 2070), 3.159242349440139),
                 (Date(31, 7, 2071), 3.1598400898057433),
                 (Date(31, 7, 2072), 3.16090721831932),
                 (Date(31, 7, 2073), 3.162369676612098),
                 (Date(31, 7, 2074), 3.1641636543027207)]

    zcDates = []
    zcRates = []
    for i in range(0, len(zciisData)):
        zcDates.append(zciisData[i][0])
        zcRates.append(zciisData[i][1] / 100.0)

    inflationZeroCurve = DiscountCurveZeros(settlement_date, zcDates, zcRates,
                                            FrequencyTypes.ANNUAL,
                                            DayCountTypes.ACT_ACT_ISDA)

    #    print(inflationZeroCurve)

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

    bond = FinInflationBond(issue_date, maturity_date, coupon, freq_type,
                            accrual_type, face, baseCPIValue)

    testCases.header("FIELD", "VALUE")
    clean_price = 104.03502

    yld = bond.current_yield(clean_price)
    testCases.print("Current Yield = ", yld)

    return

    ###########################################################################
    # Inherited functions that just calculate real yield without CPI adjustments
    ###########################################################################

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.UK_DMO)

    testCases.print("UK DMO REAL Yield To Maturity = ", ytm)

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.US_STREET)

    testCases.print("US STREET REAL Yield To Maturity = ", ytm)

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.US_TREASURY)

    testCases.print("US TREASURY REAL Yield To Maturity = ", ytm)

    full_price = bond.full_price_from_ytm(settlement_date, ytm)
    testCases.print("Full Price from REAL YTM = ", full_price)

    clean_price = bond.clean_price_from_ytm(settlement_date, ytm)
    testCases.print("Clean Price from Real YTM = ", clean_price)

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

    accrued_interest = bond._accrued_interest
    testCases.print("REAL Accrued Interest = ", accrued_interest)

    ###########################################################################
    # Inflation functions that calculate nominal yield with CPI adjustment
    ###########################################################################

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

    clean_price = bond.clean_price_from_ytm(settlement_date, ytm)
    testCases.print("Clean Price from Real YTM = ", clean_price)

    inflationAccd = bond.calc_inflation_accrued_interest(
        settlement_date, refCPIValue)

    testCases.print("Inflation Accrued = ", inflationAccd)

    lastCpnCPIValue = 244.61839

    clean_price = bond.flat_price_from_yield_to_maturity(
        settlement_date, ytm, lastCpnCPIValue, YTMCalcType.US_TREASURY)

    testCases.print("Flat Price from Real YTM = ", clean_price)

    principal = bond.inflation_principal(settlement_date, ytm, refCPIValue,
                                         YTMCalcType.US_TREASURY)

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

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

    duration = bond.dollar_duration(settlement_date, ytm)
    testCases.print("Dollar Duration = ", duration)

    modified_duration = bond.modified_duration(settlement_date, ytm)
    testCases.print("Modified Duration = ", modified_duration)

    macauley_duration = bond.macauley_duration(settlement_date, ytm)
    testCases.print("Macauley Duration = ", macauley_duration)

    conv = bond.convexity_from_ytm(settlement_date, ytm)
    testCases.print("Convexity = ", conv)
Esempio n. 7
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

    """
    valuation_date = Date(6, 6, 2018)

    # We do the O/N rate which settles on trade date
    spot_days = 0
    settlement_date = valuation_date.add_weekdays(spot_days)
    depoDCCType = DayCountTypes.ACT_360
    depos = []
    deposit_rate = 0.0231381
    maturity_date = settlement_date.add_months(3)
    depo = IborDeposit(settlement_date, maturity_date, deposit_rate,
                       depoDCCType)
    depos.append(depo)

    futs = []
    fut = IborFuture(valuation_date, 1); futs.append(fut)
    fut = IborFuture(valuation_date, 2); futs.append(fut)
    fut = IborFuture(valuation_date, 3); futs.append(fut)
    fut = IborFuture(valuation_date, 4); futs.append(fut)
    fut = IborFuture(valuation_date, 5); futs.append(fut)
    fut = IborFuture(valuation_date, 6); futs.append(fut)

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

    accrual = DayCountTypes.THIRTY_E_360
    freq = FrequencyTypes.SEMI_ANNUAL

    spot_days = 2
    settlement_date = valuation_date.add_weekdays(spot_days)
    notional = ONE_MILLION
    fixed_leg_type = SwapTypes.PAY
    interp_type = InterpTypes.FLAT_FWD_RATES

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

    libor_curve = FinIborSingleCurveOLD(valuation_date, depos, fras, swaps, interp_type, True)

    principal = 0.0
    testCases.banner("======================================================")
    testCases.banner("SINGLE CURVE VALUATION")
    testCases.header("LABEL", "VALUE")
    testCases.print("VALUE:", swaps[0].value(valuation_date, libor_curve, libor_curve, None))
    testCases.print("FIXED:", swaps[0].fixed_leg_value(valuation_date, libor_curve))
    testCases.print("FLOAT:", swaps[0].float_leg_value(valuation_date, libor_curve, libor_curve, None))

    testCases.banner("======================================================")
    testCases.banner("SINGLE CURVE VALUATION TO SWAP SETTLEMENT DATE")
    testCases.header("LABEL", "VALUE")
    testCases.print("VALUE:", swaps[0].value(settlement_date, libor_curve, libor_curve, None))
    testCases.print("FIXED:", swaps[0].fixed_leg_value(settlement_date, libor_curve))
    testCases.print("FLOAT:", swaps[0].float_leg_value(settlement_date, libor_curve, libor_curve, None))
    testCases.banner("======================================================")

#    swaps[0].print_fixed_leg_pv()
#    swaps[0].print_float_leg_pv()

    oisCurve = buildOIS(valuation_date)
#    print(oisCurve)

    liborDualCurve = FinIborDualCurveOLD(valuation_date, oisCurve, depos, fras, swaps,
                                         InterpTypes.FLAT_FWD_RATES, True)
#    print(liborDualCurve) 
    
    # The valuation of 53714.55 is very close to the spreadsheet value 53713.96

    testCases.header("VALUATION TO TODAY DATE"," PV")
    testCases.print("VALUE:", swaps[0].value(valuation_date, oisCurve, liborDualCurve, None))
    testCases.print("FIXED:", swaps[0].fixed_leg_value(valuation_date, oisCurve))
    testCases.print("FLOAT:", swaps[0].float_leg_value(valuation_date, oisCurve, libor_curve, None))

    testCases.header("VALUATION TO SWAP SETTLEMENT DATE"," PV")
    testCases.print("VALUE:", swaps[0].value(settlement_date, oisCurve, liborDualCurve, None))
    testCases.print("FIXED:", swaps[0].fixed_leg_value(settlement_date, oisCurve))
    testCases.print("FLOAT:", swaps[0].float_leg_value(settlement_date, oisCurve, liborDualCurve, None, ))

#    swaps[0].print_fixed_leg_pv()
#    swaps[0].print_float_leg_pv()

    PLOT = False
    if PLOT is True:

        years = np.linspace(0, 5, 21)
        dates = settlement_date.add_years(years)
    
        singleCurveFwds = libor_curve.fwd(dates)
        plt.plot(years, singleCurveFwds, label="Single Libor Curve")
 
        oisCurveFwds = oisCurve.fwd(dates)    
        plt.plot(years, oisCurveFwds, label="OIS Curve")

        index_curveFwds = liborDualCurve.fwd(dates)
        plt.plot(years, index_curveFwds, label="Libor Index Curve")
        
        plt.legend()
Esempio n. 8
0
def test_FinEquityVanillaOptionFactored():

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 7, 2015)
    stock_price = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)

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

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

    for num_paths in num_pathsList:

        callOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                               FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)
        start = time.time()
        valueMC = callOption.valueMC(valuation_date, stock_price,
                                     discount_curve, dividendYield, model,
                                     num_paths)
        end = time.time()
        duration = end - start
        testCases.print(num_paths, value, valueMC, duration)

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

    stock_prices = range(80, 120, 10)
    num_paths = 100000

    testCases.header("NUMPATHS", "CALL_VALUE_BS", "CALL_VALUE_MC",
                     "CALL_VALUE_MC_SOBOL", "TIME")
    useSobol = True

    for stock_price in stock_prices:

        callOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                               FinOptionTypes.EUROPEAN_CALL)

        value = callOption.value(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)

        start = time.time()

        useSobol = False
        valueMC1 = callOption.valueMC(valuation_date, stock_price,
                                      discount_curve, dividendYield, model,
                                      num_paths, useSobol)

        useSobol = True
        valueMC2 = callOption.valueMC(valuation_date, stock_price,
                                      discount_curve, dividendYield, model,
                                      num_paths, useSobol)

        end = time.time()
        duration = end - start
        testCases.print(num_paths, value, valueMC1, valueMC2, duration)

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

    stock_prices = range(80, 120, 10)
    num_paths = 100000

    testCases.header("NUMPATHS", "PUT_VALUE_BS", "PUT_VALUE_MC",
                     "PUT_VALUE_MC_SOBOL", "TIME")

    for stock_price in stock_prices:

        putOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                              FinOptionTypes.EUROPEAN_PUT)

        value = putOption.value(valuation_date, stock_price, discount_curve,
                                dividendYield, model)

        start = time.time()

        useSobol = False
        valueMC1 = putOption.valueMC(valuation_date, stock_price,
                                     discount_curve, dividendYield, model,
                                     num_paths, useSobol)

        useSobol = True
        valueMC2 = putOption.valueMC(valuation_date, stock_price,
                                     discount_curve, dividendYield, model,
                                     num_paths, useSobol)

        end = time.time()
        duration = end - start
        testCases.print(num_paths, value, valueMC1, valueMC2, duration)

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

    stock_prices = range(80, 120, 10)

    testCases.header("STOCK PRICE", "CALL_VALUE_BS", "CALL_DELTA_BS",
                     "CALL_VEGA_BS", "CALL_THETA_BS", "CALL_RHO_BS")

    for stock_price in stock_prices:

        callOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                               FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)
        delta = callOption.delta(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)
        vega = callOption.vega(valuation_date, stock_price, discount_curve,
                               dividendYield, model)
        theta = callOption.theta(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)
        rho = callOption.rho(valuation_date, stock_price, discount_curve,
                             dividendYield, model)
        testCases.print(stock_price, value, delta, vega, theta, rho)

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

    testCases.header("STOCK PRICE", "PUT_VALUE_BS", "PUT_DELTA_BS",
                     "PUT_VEGA_BS", "PUT_THETA_BS", "PUT_RHO_BS")

    for stock_price in stock_prices:

        putOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                              FinOptionTypes.EUROPEAN_PUT)

        value = putOption.value(valuation_date, stock_price, discount_curve,
                                dividendYield, model)
        delta = putOption.delta(valuation_date, stock_price, discount_curve,
                                dividendYield, model)
        vega = putOption.vega(valuation_date, stock_price, discount_curve,
                              dividendYield, model)
        theta = putOption.theta(valuation_date, stock_price, discount_curve,
                                dividendYield, model)
        rho = putOption.rho(valuation_date, stock_price, discount_curve,
                            dividendYield, model)
        testCases.print(stock_price, value, delta, vega, theta, rho)

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

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

    stock_prices = range(60, 150, 10)

    for stock_price in stock_prices:
        callOption = FinEquityVanillaOptionOLD(expiry_date, 100.0,
                                               FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valuation_date, stock_price, discount_curve,
                                 dividendYield, model)
        impliedVol = callOption.impliedVolatility(valuation_date, stock_price,
                                                  discount_curve,
                                                  dividendYield, value)
        testCases.print(stock_price, value, volatility, impliedVol)
###############################################################################
# Copyright (C) 2018, 2019, 2020 Dominic O'Kane
###############################################################################

from financepy.utils.global_types import OptionTypes
from financepy.products.equity.equity_digital_option import EquityDigitalOption, FinDigitalOptionTypes
from financepy.models.black_scholes import BlackScholes
from financepy.market.curves.discount_curve_flat import DiscountCurveFlat
from financepy.utils.date import Date
import sys
sys.path.append("./..")


underlying_type = FinDigitalOptionTypes.CASH_OR_NOTHING

valuation_date = Date(1, 1, 2015)
expiry_date = Date(1, 1, 2016)
stock_price = 100.0
volatility = 0.30
interest_rate = 0.05
dividend_yield = 0.01
discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

model = BlackScholes(volatility)

num_paths = 40000


def test_value():
Esempio n. 10
0
def test_FinFXOptionSABR():

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

    valuation_date = Date(13, 2, 2018)
    expiry_date = Date(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
    ccy1CCRate = 0.030  # EUR
    ccy2CCRate = 0.025  # USD

    spot_fx_rate = 1.20
    strike_fx_rate = 1.250
    volatility = 0.10

    notional = 1000000.0

    dom_discount_curve = DiscountCurveFlat(valuation_date, ccy2CCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, ccy1CCRate)

    model = BlackScholes(volatility)

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

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

    testCases.header("OPTION", "FX_RATE", "VALUE_BS", "VOL_IN", "DIFF")

    for spot_fx_rate in spot_fx_rates:

        call_option = FXVanillaOption(expiry_date, strike_fx_rate, "EURUSD",
                                      OptionTypes.EUROPEAN_CALL, notional,
                                      "USD")

        valueEuropean = call_option.value(valuation_date, spot_fx_rate,
                                          dom_discount_curve,
                                          for_discount_curve, model)['v']

        call_option = FXVanillaOption(expiry_date, strike_fx_rate, "EURUSD",
                                      OptionTypes.AMERICAN_CALL, 1000000,
                                      "USD")

        valueAmerican = call_option.value(valuation_date, spot_fx_rate,
                                          dom_discount_curve,
                                          for_discount_curve, model)['v']

        diff = (valueAmerican - valueEuropean)

        testCases.print("CALL:", "%9.6f" % spot_fx_rate,
                        "%9.7f" % valueEuropean, "%9.7f" % valueAmerican,
                        "%9.7f" % diff)

    testCases.header("OPTION", "FX_RATE", "VALUE_BS", "VOL_IN", "DIFF")

    for spot_fx_rate in spot_fx_rates:

        call_option = FXVanillaOption(expiry_date, strike_fx_rate, "EURUSD",
                                      OptionTypes.EUROPEAN_PUT, 1000000, "USD")

        valueEuropean = call_option.value(valuation_date, spot_fx_rate,
                                          dom_discount_curve,
                                          for_discount_curve, model)['v']

        call_option = FXVanillaOption(expiry_date, strike_fx_rate, "EURUSD",
                                      OptionTypes.AMERICAN_PUT, 1000000, "USD")

        valueAmerican = call_option.value(valuation_date, spot_fx_rate,
                                          dom_discount_curve,
                                          for_discount_curve, model)['v']

        diff = (valueAmerican - valueEuropean)
        testCases.print("PUT:", "%9.6f" % spot_fx_rate,
                        "%9.7f" % valueEuropean, "%9.7f" % valueAmerican,
                        "%9.7f" % diff)
def testImpliedVolatility_NEW():

    valuation_date = Date(1, 1, 2015)
    stock_price = 100.0
    interestRate = 0.05
    dividendYield = 0.03
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, 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:

            expiry_date = valuation_date.addYears(timeToExpiry)

            for strike in strikes:

                for optionType in optionTypes:

                    option = FinEquityVanillaOption(expiry_date, strike,
                                                    optionType)

                    value = option.value(valuation_date, stock_price,
                                         discount_curve, dividendCurve, model)

                    intrinsic = option.intrinsic(valuation_date, stock_price,
                                                 discount_curve, 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(
                            valuation_date, stock_price, discount_curve,
                            dividendCurve, value)

                    numTests += 1

                    errVol = np.abs(impliedVol - vol)

                    if errVol > tol:

                        testCases.print(optionType, timeToExpiry, stock_price,
                                        strike, intrinsic, value, vol,
                                        impliedVol)

                        # These fails include ones due to the zero time value
                        numFails += 1

                        testCases.print(optionType, timeToExpiry, stock_price,
                                        strike, stock_price, value, vol,
                                        impliedVol)

    assert numFails == 694, "Num Fails has changed."
Esempio n. 12
0
def test_full_priceCDSIndexOption():

    tradeDate = Date(1, 8, 2007)
    step_in_date = tradeDate.addDays(1)
    valuation_date = step_in_date

    libor_curve = 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()
    issuer_curves = []

    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
        recovery_rate = float(splitRow[5])

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

        issuer_curve = FinCDSCurve(valuation_date, cds_contracts, libor_curve,
                                   recovery_rate)

        issuer_curves.append(issuer_curve)

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

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

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

    index_coupon = 0.004
    volatility = 0.50
    expiry_date = Date(1, 2, 2008)
    maturity_date = Date(20, 12, 2011)
    notional = 10000.0
    tolerance = 1e-6

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

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

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

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

        index_curve = FinCDSCurve(valuation_date, cds_contracts, libor_curve,
                                  indexRecovery)

        if 1 == 1:

            indexSpreads = [index / 10000.0] * 4

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

            indexSpread = index / 10000.0
            issuer_curve = buildFlatIssuerCurve(tradeDate, libor_curve,
                                                indexSpread, indexRecovery)

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

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

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

            start = time.time()

            option = FinCDSIndexOption(expiry_date, maturity_date,
                                       index_coupon, strike / 10000.0,
                                       notional)

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

            end = time.time()

            v_pay_2, v_rec_2 = option.valueAdjustedBlack(
                valuation_date, index_curve, indexRecovery, libor_curve,
                volatility)

            elapsed = end - start

            testCases.print(elapsed, strike, index, v_pay_1, v_rec_1,
                            strikeValue, mu, expH, v_pay_2, v_rec_2)
def test_BDTExampleThree():
    # Valuation of a swaption as in Leif Andersen's paper - see Table 1 on
    # SSRN-id155208.pdf

    settlement_date = Date(1, 1, 2020)
    times = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
    dates = settlement_date.add_years(times)
    rate = 0.06
    dfs = 1.0 / (1.0 + rate / 2.0)**(2.0 * times)
    curve = DiscountCurve(settlement_date, dates, dfs)

    coupon = 0.06
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    strike_price = 100.0
    face = 100.0
    # Andersen paper
    num_time_steps = 200

    exercise_type = FinExerciseTypes.EUROPEAN
    years_to_maturity = 4.0
    expiryYears = 2.0

    maturity_date = settlement_date.add_years(years_to_maturity)
    issue_date = Date(maturity_date._d, maturity_date._m, 2000)

    sigma = 0.2012

    expiry_date = settlement_date.add_years(expiryYears)

    tmat = (maturity_date - settlement_date) / gDaysInYear
    texp = (expiry_date - settlement_date) / gDaysInYear

    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    coupon_times = []
    coupon_flows = []
    cpn = bond._coupon / bond._frequency
    for flow_date in bond._coupon_dates:
        if flow_date > expiry_date:
            flow_time = (flow_date - settlement_date) / gDaysInYear
            coupon_times.append(flow_time)
            coupon_flows.append(cpn)

    coupon_times = np.array(coupon_times)
    coupon_flows = np.array(coupon_flows)

    price = bond.clean_price_from_discount_curve(settlement_date, curve)

    model = BDTTree(sigma, num_time_steps)
    model.build_tree(tmat, times, dfs)

    v = model.bermudan_swaption(texp, tmat, strike_price, face, coupon_times,
                                coupon_flows, exercise_type)

    assert round(price, 5) == 100.01832
    assert round(v['pay'] * 100, 2) == 0.00
    assert round(v['rec'] * 100, 2) == 8883.21

    exercise_type = FinExerciseTypes.BERMUDAN
    years_to_maturity = 10.0
    expiryYears = 5.0

    maturity_date = settlement_date.add_years(years_to_maturity)
    issue_date = Date(maturity_date._d, maturity_date._m, 2000)

    sigma = 0.1522

    expiry_date = settlement_date.add_years(expiryYears)

    tmat = (maturity_date - settlement_date) / gDaysInYear
    texp = (expiry_date - settlement_date) / gDaysInYear

    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    coupon_times = []
    coupon_flows = []
    cpn = bond._coupon / bond._frequency
    for flow_date in bond._coupon_dates:
        if flow_date > expiry_date:
            flow_time = (flow_date - settlement_date) / gDaysInYear
            coupon_times.append(flow_time)
            coupon_flows.append(cpn)

    coupon_times = np.array(coupon_times)
    coupon_flows = np.array(coupon_flows)

    price = bond.clean_price_from_discount_curve(settlement_date, curve)

    model = BDTTree(sigma, num_time_steps)
    model.build_tree(tmat, times, dfs)

    v = model.bermudan_swaption(texp, tmat, strike_price, face, coupon_times,
                                coupon_flows, exercise_type)

    assert round(price, 5) == 100.08625
    assert round(v['pay'] * 100, 2) == 263.28
    assert round(v['rec'] * 100, 2) == 7437.00
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

    settlement_date = Date(1, 12, 2019)
    issue_date = Date(1, 12, 2015)
    expiry_date = settlement_date.add_tenor("18m")
    maturity_date = settlement_date.add_tenor("10Y")
    coupon = 0.05
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    coupon_times = []
    coupon_flows = []
    cpn = bond._coupon / bond._frequency
    num_flows = len(bond._coupon_dates)

    for i in range(1, num_flows):
        pcd = bond._coupon_dates[i - 1]
        ncd = bond._coupon_dates[i]
        if pcd < settlement_date and ncd > settlement_date:
            flow_time = (pcd - settlement_date) / gDaysInYear
            coupon_times.append(flow_time)
            coupon_flows.append(cpn)

    for flow_date in bond._coupon_dates:
        if flow_date > settlement_date:
            flow_time = (flow_date - settlement_date) / gDaysInYear
            coupon_times.append(flow_time)
            coupon_flows.append(cpn)

    coupon_times = np.array(coupon_times)
    coupon_flows = np.array(coupon_flows)

    strike_price = 105.0
    face = 100.0

    tmat = (maturity_date - settlement_date) / gDaysInYear
    texp = (expiry_date - settlement_date) / gDaysInYear
    times = np.linspace(0, tmat, 11)
    dates = settlement_date.add_years(times)
    dfs = np.exp(-0.05 * times)

    curve = DiscountCurve(settlement_date, dates, dfs)

    price = bond.clean_price_from_discount_curve(settlement_date, curve)
    assert round(price, 4) == 99.5420

    sigma = 0.20

    # Test convergence
    num_time_steps = 5
    exercise_type = FinExerciseTypes.AMERICAN

    model = BDTTree(sigma, num_time_steps)
    model.build_tree(tmat, times, dfs)
    v = model.bond_option(texp, strike_price, face, coupon_times, coupon_flows,
                          exercise_type)

    assert round(v['call'], 4) == 0.5043
    assert round(v['put'], 4) == 8.2242
Esempio n. 15
0
def test_IborCapFloorQLExample():

    valuation_date = Date(14, 6, 2016)

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

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

    freq_type = FrequencyTypes.ANNUAL
    day_count_type = DayCountTypes.ACT_ACT_ISDA

    discount_curve = DiscountCurveZeros(valuation_date, dates, rates,
                                        freq_type, day_count_type,
                                        InterpTypes.LINEAR_ZERO_RATES)

    start_date = Date(14, 6, 2016)
    end_date = Date(14, 6, 2026)
    calendar_type = CalendarTypes.UNITED_STATES
    bus_day_adjust_type = BusDayAdjustTypes.MODIFIED_FOLLOWING
    freq_type = FrequencyTypes.QUARTERLY
    date_gen_rule_type = DateGenRuleTypes.FORWARD
    lastFixing = 0.0065560
    notional = 1000000
    day_count_type = DayCountTypes.ACT_360
    option_type = FinCapFloorTypes.CAP
    strike_rate = 0.02

    cap = IborCapFloor(start_date, end_date, option_type, strike_rate,
                       lastFixing, freq_type, day_count_type, notional,
                       calendar_type, bus_day_adjust_type, date_gen_rule_type)

    blackVol = 0.547295
    model = Black(blackVol)

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

    end = time.time()
    period = end - start
Esempio n. 16
0
def test_addDays():
    assert Date(1, 1, 2018).addDays(-1).addDays(1) == Date(1, 1, 2018)
Esempio n. 17
0
def test_IborCapFloor():

    todayDate = Date(20, 6, 2019)
    valuation_date = todayDate
    start_date = todayDate.add_weekdays(2)
    maturity_date = start_date.add_tenor("1Y")
    libor_curve = test_ibor_depositsAndSwaps(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 = Black(0.20)
    model2 = BlackShifted(0.25, 0.0)
    model3 = SABR(0.013, 0.5, 0.5, 0.5)
    model4 = SABRShifted(0.013, 0.5, 0.5, 0.5, -0.008)
    model5 = HWTree(0.30, 0.01)
    model6 = Bachelier(0.01)

    for k in strikes:
        capFloorType = FinCapFloorTypes.CAP
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        cvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        cvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        cvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        cvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        cvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        cvalue6 = capfloor.value(valuation_date, libor_curve, 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 = IborCapFloor(start_date, maturity_date, capFloorType, k)
        fvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        fvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        fvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        fvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        fvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        fvalue6 = capfloor.value(valuation_date, libor_curve, 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 = IborCapFloor(start_date, maturity_date, capFloorType, k)
        cvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        cvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        cvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        cvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        cvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        cvalue6 = capfloor.value(valuation_date, libor_curve, model6)

        capFloorType = FinCapFloorTypes.FLOOR
        capfloor = IborCapFloor(start_date, maturity_date, capFloorType, k)
        fvalue1 = capfloor.value(valuation_date, libor_curve, model1)
        fvalue2 = capfloor.value(valuation_date, libor_curve, model2)
        fvalue3 = capfloor.value(valuation_date, libor_curve, model3)
        fvalue4 = capfloor.value(valuation_date, libor_curve, model4)
        fvalue5 = capfloor.value(valuation_date, libor_curve, model5)
        fvalue6 = capfloor.value(valuation_date, libor_curve, 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)
Esempio n. 18
0
def test_DateEOM():

    dt = Date(29, 2, 2000)
    assert dt.isEOM() == True

    dt = Date(28, 2, 2001)
    assert dt.isEOM() == True

    dt = Date(29, 2, 2004)
    assert dt.isEOM() == True

    dt = Date(28, 2, 2005)
    assert dt.isEOM() == True

    dt = Date(31, 3, 2003)
    assert dt.isEOM() == True

    dt = Date(30, 4, 2004)
    assert dt.isEOM() == True

    dt = Date(31, 5, 2004)
    assert dt.isEOM() == True

    dt = Date(31, 12, 2010)
    assert dt.isEOM() == True

    dt = Date(2, 2, 2000)
    assert dt.EOM().isEOM() == True

    dt = Date(24, 2, 2001)
    assert dt.EOM().isEOM() == True

    dt = Date(22, 2, 2004)
    assert dt.EOM().isEOM() == True

    dt = Date(1, 2, 2005)
    assert dt.EOM().isEOM() == True

    dt = Date(1, 3, 2003)
    assert dt.EOM().isEOM() == True

    dt = Date(3, 4, 2004)
    assert dt.EOM().isEOM() == True

    dt = Date(5, 5, 2004)
    assert dt.EOM().isEOM() == True

    dt = Date(7, 12, 2010)
    assert dt.EOM().isEOM() == True
Esempio n. 19
0
def test_FinInflationBondBBG():

    ##########################################################################
    # https://data.bloomberglp.com/bat/sites/3/2017/07/SF-2017_Paul-Fjeldsted.pdf
    # Look for CPI Bond example
    ##########################################################################

    testCases.banner("BLOOMBERG US TIPS EXAMPLE")
    settlement_date = Date(21, 7, 2017)
    issue_date = Date(15, 7, 2010)
    maturity_date = Date(15, 7, 2020)
    coupon = 0.0125
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    face = 100.0
    baseCPIValue = 218.08532

    bond = FinInflationBond(issue_date, maturity_date, coupon, freq_type,
                            accrual_type, face, baseCPIValue)

    testCases.header("FIELD", "VALUE")
    clean_price = 104.03502

    yld = bond.current_yield(clean_price)
    testCases.print("Current Yield = ", yld)

    ###########################################################################
    # Inherited functions that just calculate real yield without CPI adjustments
    ###########################################################################

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.UK_DMO)

    testCases.print("UK DMO REAL Yield To Maturity = ", ytm)

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.US_STREET)

    testCases.print("US STREET REAL Yield To Maturity = ", ytm)

    ytm = bond.yield_to_maturity(settlement_date, clean_price,
                                 YTMCalcType.US_TREASURY)

    testCases.print("US TREASURY REAL Yield To Maturity = ", ytm)

    full_price = bond.full_price_from_ytm(settlement_date, ytm)
    testCases.print("Full Price from REAL YTM = ", full_price)

    clean_price = bond.clean_price_from_ytm(settlement_date, ytm)
    testCases.print("Clean Price from Real YTM = ", clean_price)

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

    accrued_interest = bond._accrued_interest
    testCases.print("REAL Accrued Interest = ", accrued_interest)

    ###########################################################################
    # Inflation functions that calculate nominal yield with CPI adjustment
    ###########################################################################

    refCPIValue = 244.65884

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

    clean_price = bond.clean_price_from_ytm(settlement_date, ytm)
    testCases.print("Clean Price from Real YTM = ", clean_price)

    inflationAccd = bond.calc_inflation_accrued_interest(
        settlement_date, refCPIValue)

    testCases.print("Inflation Accrued = ", inflationAccd)

    lastCpnCPIValue = 244.61839

    clean_price = bond.flat_price_from_yield_to_maturity(
        settlement_date, ytm, lastCpnCPIValue, YTMCalcType.US_TREASURY)

    testCases.print("Flat Price from Real YTM = ", clean_price)

    principal = bond.inflation_principal(settlement_date, ytm, refCPIValue,
                                         YTMCalcType.US_TREASURY)

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

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

    duration = bond.dollar_duration(settlement_date, ytm)
    testCases.print("Dollar Duration = ", duration)

    modified_duration = bond.modified_duration(settlement_date, ytm)
    testCases.print("Modified Duration = ", modified_duration)

    macauley_duration = bond.macauley_duration(settlement_date, ytm)
    testCases.print("Macauley Duration = ", macauley_duration)

    conv = bond.convexity_from_ytm(settlement_date, ytm)
    testCases.print("Convexity = ", conv)
Esempio n. 20
0
def test_from_string():
    assert Date.fromString("1-1-2018", "%d-%m-%Y") == Date(1, 1, 2018)
Esempio n. 21
0
def test_swapValuationExample():
    
    # Example from
    # https://blog.deriscope.com/index.php/en/excel-interest-rate-swap-price-dual-bootstrapping-curve
    
    vBloomberg = 388147

    valuation_date = Date(30, 11, 2018)

    start_date = Date(27, 12, 2017)
    maturity_date = Date(27, 12, 2067)
    notional = 10 * ONE_MILLION
    fixed_leg_type = SwapTypes.RECEIVE
    
    fixedRate = 0.0150
    fixedDCCType = DayCountTypes.THIRTY_360_BOND
    fixedFreqType = FrequencyTypes.ANNUAL
    
    float_spread = 0.0
    floatDCCType = DayCountTypes.ACT_360
    floatFreqType = FrequencyTypes.SEMI_ANNUAL

    offMarketSwap = IborSwapOLD(start_date, maturity_date, fixed_leg_type,
                                fixedRate, fixedFreqType, fixedDCCType,
                                notional,
                                float_spread, floatFreqType, floatDCCType)
    
    interp_type = InterpTypes.LINEAR_ZERO_RATES
    
    depoDCCType = DayCountTypes.ACT_360
    depos = []
    
    ###########################################################################
    # MARKET
    ###########################################################################
    
    spot_days = 0
    settlement_date = valuation_date.add_weekdays(spot_days)
    depo = IborDeposit(settlement_date, "6M", -0.2510 / 100.0, depoDCCType); depos.append(depo)
    
    fras = []
    fraDCCType = DayCountTypes.ACT_360
    
    fra = IborFRA(settlement_date.add_tenor("1M"), "6M", -0.2450 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("2M"), "6M", -0.2435 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("3M"), "6M", -0.2400 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("4M"), "6M", -0.2360 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("5M"), "6M", -0.2285 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("6M"), "6M", -0.2230 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("7M"), "6M", -0.2110 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("8M"), "6M", -0.1990 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("9M"), "6M", -0.1850 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("10M"), "6M", -0.1680 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("11M"), "6M", -0.1510 / 100.0, fraDCCType); fras.append(fra)
    fra = IborFRA(settlement_date.add_tenor("12M"), "6M", -0.1360 / 100.0, fraDCCType); fras.append(fra)
    
    swaps = []
    fixed_leg_type = SwapTypes.PAY
    fixedDCCType = DayCountTypes.THIRTY_360_BOND
    fixedFreqType = FrequencyTypes.ANNUAL
    
    swap = IborSwapOLD(settlement_date, "2Y", fixed_leg_type, -0.1525/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "3Y", fixed_leg_type, -0.0185/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "4Y", fixed_leg_type, 0.1315/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "5Y", fixed_leg_type, 0.2745/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "6Y", fixed_leg_type, 0.4135/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "7Y", fixed_leg_type, 0.5439/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "8Y", fixed_leg_type, 0.6652/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "9Y", fixed_leg_type, 0.7784/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "10Y", fixed_leg_type, 0.8799/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "11Y", fixed_leg_type, 0.9715/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "12Y", fixed_leg_type, 1.0517/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "15Y", fixed_leg_type, 1.2369/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "20Y", fixed_leg_type, 1.3965/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "25Y", fixed_leg_type, 1.4472/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "30Y", fixed_leg_type, 1.4585/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "35Y", fixed_leg_type, 1.4595/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "40Y", fixed_leg_type, 1.4535/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "45Y", fixed_leg_type, 1.4410/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = IborSwapOLD(settlement_date, "50Y", fixed_leg_type, 1.4335/100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    
    iborDepos = depos.copy()
    iborFras = fras.copy()
    ibor_swaps = swaps.copy()
    
    iborCurve = FinIborSingleCurve(valuation_date, iborDepos, iborFras, ibor_swaps, interp_type)
    v1 = offMarketSwap.value(valuation_date, iborCurve, iborCurve, -0.268/100.0)    

    testCases.banner("DERISCOPE EXAMPLE REPLICATION")    
    testCases.header("LABEL", "VALUE")
    testCases.print("BBG VALUE", vBloomberg)
    testCases.print("FP ONE CURVE VALUE", v1)
    
    ###############################################################################
    
    depoDCCType = DayCountTypes.ACT_360
    depos = []
    
    spot_days = 0
    settlement_date = valuation_date.add_weekdays(spot_days)
    depo = IborDeposit(settlement_date, "1D", -0.3490 / 100.0, depoDCCType); depos.append(depo)
    
    fras = []
    
    swaps = []
    fixed_leg_type = SwapTypes.PAY
    fixedDCCType = DayCountTypes.ACT_365F
    fixedFreqType = FrequencyTypes.ANNUAL
    
    # Standard OIS with standard annual terms
    swap = OIS(settlement_date, "2W", fixed_leg_type, -0.3600 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "1M", fixed_leg_type, -0.3560 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "2M", fixed_leg_type, -0.3570 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "3M", fixed_leg_type, -0.3580 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "4M", fixed_leg_type, -0.3575 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "5M", fixed_leg_type, -0.3578 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "6M", fixed_leg_type, -0.3580 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "7M", fixed_leg_type, -0.3600 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "8M", fixed_leg_type, -0.3575 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "9M", fixed_leg_type, -0.3569 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "10M", fixed_leg_type, -0.3553 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "11M", fixed_leg_type, -0.3534 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "12M", fixed_leg_type, -0.3496 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "18M", fixed_leg_type, -0.3173 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    
    swap = OIS(settlement_date, "2Y", fixed_leg_type, -0.2671 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "30M", fixed_leg_type, -0.2070 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "3Y", fixed_leg_type, -0.1410 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "4Y", fixed_leg_type, -0.0060 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "5Y", fixed_leg_type, 0.1285 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "6Y", fixed_leg_type, 0.2590 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "7Y", fixed_leg_type, 0.3830 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "8Y", fixed_leg_type, 0.5020 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "9Y", fixed_leg_type, 0.6140 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "10Y", fixed_leg_type, 0.7160 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "11Y", fixed_leg_type, 0.8070 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "12Y", fixed_leg_type, 0.8890 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "15Y", fixed_leg_type, 1.0790 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "20Y", fixed_leg_type, 1.2460 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "25Y", fixed_leg_type, 1.3055 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "30Y", fixed_leg_type, 1.3270 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "35Y", fixed_leg_type, 1.3315 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "40Y", fixed_leg_type, 1.3300 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    swap = OIS(settlement_date, "50Y", fixed_leg_type, 1.3270 / 100.0, fixedFreqType, fixedDCCType); swaps.append(swap)
    
    oisDepos = depos.copy()
    oisFras = fras.copy()
    oisSwaps = swaps.copy()
    
#    oisCurveFF = FinOISCurve(valuation_date, oisDepos, oisFras, oisSwaps, interp_type)
    
    iborDualCurve = FinIborDualCurve(valuation_date, oisCurveFF, iborDepos, iborFras, ibor_swaps, interp_type)
Esempio n. 22
0
def test_weekday():
    assert Date(3, 3, 2021)._weekday == Date.WED
def test_BondEmbeddedOptionMATLAB():

    # https://fr.mathworks.com/help/fininst/optembndbyhw.html
    # I FIND THAT THE PRICE CONVERGES TO 102.88 WHICH IS CLOSE TO 102.9127
    # FOUND BY MATLAB ALTHOUGH THEY DO NOT EXAMINE THE ASYMPTOTIC PRICE
    # WHICH MIGHT BE A BETTER MATCH

    settlement_date = Date(1, 1, 2007)
    valuation_date = settlement_date
    
    ###########################################################################

    dcType = DayCountTypes.THIRTY_E_360
    fixedFreq = FrequencyTypes.ANNUAL
    fixed_legType = FinSwapTypes.PAY
    swap1 = FinIborSwap(settlement_date, "1Y", fixed_legType, 0.0350, fixedFreq, dcType)
    swap2 = FinIborSwap(settlement_date, "2Y", fixed_legType, 0.0400, fixedFreq, dcType)
    swap3 = FinIborSwap(settlement_date, "3Y", fixed_legType, 0.0450, fixedFreq, dcType)
    swaps = [swap1, swap2, swap3]
    discount_curve = IborSingleCurve(valuation_date, [], [], swaps)

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

    issue_date = Date(1, 1, 2004)
    maturity_date = Date(1, 1, 2010)
    
    coupon = 0.0525
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    call_dates = []
    call_prices = []
    put_dates = []
    put_prices = []

    putDate = Date(1, 1, 2008)
    for _ in range(0, 24):
        put_dates.append(putDate)
        put_prices.append(100)
        putDate = putDate.addMonths(1)

    testCases.header("BOND PRICE", "PRICE")
    v = bond.clean_price_from_discount_curve(settlement_date, discount_curve)
    testCases.print("Bond Pure Price:", v)

    sigma = 0.01  # basis point volatility
    a = 0.1

    puttableBond = BondEmbeddedOption(issue_date,
                                      maturity_date, coupon,
                                      freq_type, accrual_type,
                                      call_dates, call_prices,
                                      put_dates, put_prices)

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

    timeSteps = range(50, 1000, 10)
    values = []
    for numTimeSteps in timeSteps:
        model = FinModelRatesHW(sigma, a, numTimeSteps)
        start = time.time()
        v = puttableBond.value(settlement_date, discount_curve, model)
        end = time.time()
        period = end - start
        testCases.print(period, numTimeSteps, v['bondwithoption'],
                        v['bondpure'])
        values.append(v['bondwithoption'])

    if plotGraphs:
        plt.figure()
        plt.plot(timeSteps, values)
Esempio n. 24
0
def test_excel_representation():
    assert Date(5, 1, 1900)._excelDate == 5
    assert Date(1, 3, 2020)._excelDate == 43891
def test_CDSIndexPortfolio():

    tradeDate = Date(1, 8, 2007)
    step_in_date = tradeDate.addDays(1)
    valuation_date = step_in_date

    libor_curve = 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()
    issuer_curves = []

    for row in data[1:]:

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

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

        issuer_curve = FinCDSCurve(valuation_date, cds_contracts, libor_curve,
                                   recovery_rate)

        issuer_curves.append(issuer_curve)

    ##########################################################################
    # Now determine the average spread of the index
    ##########################################################################

    cdsIndex = FinCDSIndexPortfolio()

    averageSpd3Y = cdsIndex.averageSpread(valuation_date, step_in_date,
                                          maturity3Y, issuer_curves) * 10000.0

    averageSpd5Y = cdsIndex.averageSpread(valuation_date, step_in_date,
                                          maturity5Y, issuer_curves) * 10000.0

    averageSpd7Y = cdsIndex.averageSpread(valuation_date, step_in_date,
                                          maturity7Y, issuer_curves) * 10000.0

    averageSpd10Y = cdsIndex.averageSpread(
        valuation_date, step_in_date, maturity10Y, issuer_curves) * 10000.0

    testCases.header("LABEL", "VALUE")
    testCases.print("AVERAGE SPD 3Y", averageSpd3Y)
    testCases.print("AVERAGE SPD 5Y", averageSpd5Y)
    testCases.print("AVERAGE SPD 7Y", averageSpd7Y)
    testCases.print("AVERAGE SPD 10Y", averageSpd10Y)

    ##########################################################################
    # Now determine the intrinsic spread of the index to the same maturity
    # dates. As the single name CDS contracts
    ##########################################################################

    cdsIndex = FinCDSIndexPortfolio()

    intrinsicSpd3Y = cdsIndex.intrinsicSpread(
        valuation_date, step_in_date, maturity3Y, issuer_curves) * 10000.0

    intrinsicSpd5Y = cdsIndex.intrinsicSpread(
        valuation_date, step_in_date, maturity5Y, issuer_curves) * 10000.0

    intrinsicSpd7Y = cdsIndex.intrinsicSpread(
        valuation_date, step_in_date, maturity7Y, issuer_curves) * 10000.0

    intrinsicSpd10Y = cdsIndex.intrinsicSpread(
        valuation_date, step_in_date, maturity10Y, issuer_curves) * 10000.0

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

    testCases.header("LABEL", "VALUE")
    testCases.print("INTRINSIC SPD 3Y", intrinsicSpd3Y)
    testCases.print("INTRINSIC SPD 5Y", intrinsicSpd5Y)
    testCases.print("INTRINSIC SPD 7Y", intrinsicSpd7Y)
    testCases.print("INTRINSIC SPD 10Y", intrinsicSpd10Y)
def test_EquityDigitalOption():

    underlying_type = FinDigitalOptionTypes.CASH_OR_NOTHING

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 1, 2016)
    stock_price = 100.0
    volatility = 0.30
    interest_rate = 0.05
    dividend_yield = 0.01
    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    model = BlackScholes(volatility)
    import time

    call_option_values = []
    call_option_valuesMC = []
    num_paths_list = [
        10000,
        20000,
        40000,
        80000]

    '''        160000,
        320000,
        640000,
        1280000,
        2560000]
    '''

    testCases.header("NumLoops", "ValueBS", "ValueMC", "TIME")

    for num_paths in num_paths_list:

        call_option = EquityDigitalOption(
            expiry_date, 100.0, OptionTypes.EUROPEAN_CALL, underlying_type)
        value = call_option.value(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        start = time.time()
        value_mc = call_option.value_mc(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model,
            num_paths)
        end = time.time()
        duration = end - start
        testCases.print(num_paths, value, value_mc, duration)

        call_option_values.append(value)
        call_option_valuesMC.append(value_mc)

#    plt.figure(figsize=(10,8))
#    plt.plot(num_paths_list, call_option_values, color = 'b', label="Call Option")
#    plt.plot(num_paths_list, call_option_valuesMC, color = 'r', label = "Call Option MC")
#    plt.xlabel("Num Loops")
#    plt.legend(loc='best')

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

    stock_prices = range(50, 150, 50)
    call_option_values = []
    call_optionDeltas = []
    call_optionVegas = []
    call_optionThetas = []

    for stock_price in stock_prices:
        call_option = EquityDigitalOption(
            expiry_date, 100.0, OptionTypes.EUROPEAN_CALL, underlying_type)
        value = call_option.value(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        delta = call_option.delta(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        vega = call_option.vega(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        theta = call_option.theta(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        call_option_values.append(value)
        call_optionDeltas.append(delta)
        call_optionVegas.append(vega)
        call_optionThetas.append(theta)

    put_option_values = []
    put_optionDeltas = []
    put_optionVegas = []
    put_optionThetas = []

    for stock_price in stock_prices:
        put_option = EquityDigitalOption(
            expiry_date, 100.0, OptionTypes.EUROPEAN_PUT, underlying_type)
        value = put_option.value(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        delta = put_option.delta(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        vega = put_option.vega(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        theta = put_option.theta(
            valuation_date,
            stock_price,
            discount_curve,
            dividend_curve,
            model)
        put_option_values.append(value)
        put_optionDeltas.append(delta)
        put_optionVegas.append(vega)
        put_optionThetas.append(theta)
def test_BondOption():

    settlement_date = Date(1, 12, 2019)
    issue_date = Date(1, 12, 2018)
    maturity_date = settlement_date.add_tenor("10Y")
    coupon = 0.05
    freq_type = FrequencyTypes.SEMI_ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    tmat = (maturity_date - settlement_date) / gDaysInYear
    times = np.linspace(0, tmat, 20)
    dates = settlement_date.add_years(times)
    dfs = np.exp(-0.05 * times)
    discount_curve = DiscountCurve(settlement_date, dates, dfs)

    expiry_date = settlement_date.add_tenor("18m")
    strike_price = 105.0
    face = 100.0

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

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

    option_type = FinOptionTypes.EUROPEAN_CALL

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

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)
    testCases.print("Fixed Income Price:", price)

    num_time_steps = 20

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

    for strike_price in strikes:

        sigma = 0.20
        a = 0.1

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN CALL - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20
        a = 0.05

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a, num_time_steps)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN CALL - BK", strike_price, v)

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

    option_type = FinOptionTypes.AMERICAN_CALL

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)
    testCases.header("LABEL", "VALUE")
    testCases.print("Fixed Income Price:", price)

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

    for strike_price in strikes:

        sigma = 0.01
        a = 0.1

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN CALL - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20
        a = 0.05

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN CALL - BK", strike_price, v)

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

    option_type = FinOptionTypes.EUROPEAN_PUT

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)

    for strike_price in strikes:

        sigma = 0.01
        a = 0.1

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN PUT - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20
        a = 0.05

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("EUROPEAN PUT - BK", strike_price, v)

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

    option_type = FinOptionTypes.AMERICAN_PUT

    price = bond.full_price_from_discount_curve(settlement_date,
                                                discount_curve)

    for strike_price in strikes:

        sigma = 0.02
        a = 0.1

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN PUT - BK", strike_price, v)

    for strike_price in strikes:

        sigma = 0.20
        a = 0.05

        bond_option = BondOption(bond, expiry_date, strike_price, face,
                                 option_type)
        model = BKTree(sigma, a)
        v = bond_option.value(settlement_date, discount_curve, model)
        testCases.print("AMERICAN PUT - BK", strike_price, v)
Esempio n. 28
0
def test_IborCapFloorVolCurve():
    """ 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 = Date(20, 6, 2019)
    valuation_date = todayDate
    maturity_date = valuation_date.add_tenor("3Y")
    day_count_type = DayCountTypes.THIRTY_E_360
    frequency = FrequencyTypes.ANNUAL

    k = 0.04
    capFloorType = FinCapFloorTypes.CAP
    capFloor = IborCapFloor(valuation_date, maturity_date, capFloorType, k,
                            None, frequency, day_count_type)

    capVolDates = Schedule(valuation_date, valuation_date.add_tenor("10Y"),
                           frequency)._generate()

    flat_rate = 0.04
    libor_curve = DiscountCurveFlat(valuation_date, flat_rate, frequency,
                                    day_count_type)

    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 = IborCapVolCurve(valuation_date, capVolDates, capVolatilities,
                               day_count_type)

    #    print(volCurve._capletGammas)

    # Value cap using a single flat cap volatility
    tcap = (maturity_date - valuation_date) / gDaysInYear
    vol = volCurve.cap_vol(maturity_date)
    model = Black(vol)
    valueCap = capFloor.value(valuation_date, libor_curve, 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.caplet_vol(capletEndDate)
        modelCaplet = Black(vol)
        vCaplet = capFloor.value_caplet_floor_let(valuation_date,
                                                  capletStartDate,
                                                  capletEndDate, libor_curve,
                                                  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)
Esempio n. 29
0
def buildFullIssuerCurve1(mktSpreadBump, irBump):

    # https://www.markit.com/markit.jsp?jsppage=pv.jsp
    # YIELD CURVE 8-AUG-2019 SNAP AT 1600

    tradeDate = Date(9, 8, 2019)
    valuation_date = tradeDate.add_days(1)

    m = 1.0  # 0.00000000000

    dcType = DayCountTypes.ACT_360
    depos = []
    depo1 = IborDeposit(valuation_date, "1D", m * 0.0220, dcType)
    depos.append(depo1)

    spot_days = 2
    settlement_date = valuation_date.add_days(spot_days)

    maturity_date = settlement_date.add_months(1)
    depo1 = IborDeposit(settlement_date, maturity_date, m * 0.022009, dcType)

    maturity_date = settlement_date.add_months(2)
    depo2 = IborDeposit(settlement_date, maturity_date, m * 0.022138, dcType)

    maturity_date = settlement_date.add_months(3)
    depo3 = IborDeposit(settlement_date, maturity_date, m * 0.021810, dcType)

    maturity_date = settlement_date.add_months(6)
    depo4 = IborDeposit(settlement_date, maturity_date, m * 0.020503, dcType)

    maturity_date = settlement_date.add_months(12)
    depo5 = IborDeposit(settlement_date, maturity_date, m * 0.019930, dcType)

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

    fras = []

    swaps = []
    dcType = DayCountTypes.THIRTY_E_360_ISDA
    fixedFreq = FrequencyTypes.SEMI_ANNUAL

    maturity_date = settlement_date.add_months(24)
    swap1 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.015910 + irBump, fixedFreq, dcType)
    swaps.append(swap1)

    maturity_date = settlement_date.add_months(36)
    swap2 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.014990 + irBump, fixedFreq, dcType)
    swaps.append(swap2)

    maturity_date = settlement_date.add_months(48)
    swap3 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.014725 + irBump, fixedFreq, dcType)
    swaps.append(swap3)

    maturity_date = settlement_date.add_months(60)
    swap4 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.014640 + irBump, fixedFreq, dcType)
    swaps.append(swap4)

    maturity_date = settlement_date.add_months(72)
    swap5 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.014800 + irBump, fixedFreq, dcType)
    swaps.append(swap5)

    maturity_date = settlement_date.add_months(84)
    swap6 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.014995 + irBump, fixedFreq, dcType)
    swaps.append(swap6)

    maturity_date = settlement_date.add_months(96)
    swap7 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.015180 + irBump, fixedFreq, dcType)
    swaps.append(swap7)

    maturity_date = settlement_date.add_months(108)
    swap8 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.015610 + irBump, fixedFreq, dcType)
    swaps.append(swap8)

    maturity_date = settlement_date.add_months(120)
    swap9 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                     m * 0.015880 + irBump, fixedFreq, dcType)
    swaps.append(swap9)

    maturity_date = settlement_date.add_months(144)
    swap10 = IborSwap(settlement_date, maturity_date, SwapTypes.PAY,
                      m * 0.016430 + irBump, fixedFreq, dcType)
    swaps.append(swap10)

    libor_curve = IborSingleCurve(valuation_date, depos, fras, swaps)

    cdsMarketContracts = []

    cdsCoupon = 0.04 + mktSpreadBump

    maturity_date = valuation_date.next_cds_date(6)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(12)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(24)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(36)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(48)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(60)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(84)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(120)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    maturity_date = valuation_date.next_cds_date(180)
    cds = CDS(valuation_date, maturity_date, cdsCoupon)
    cdsMarketContracts.append(cds)

    recovery_rate = 0.40

    issuer_curve = CDSCurve(valuation_date, cdsMarketContracts, libor_curve,
                            recovery_rate)

    return libor_curve, issuer_curve
def test_BondOptionEuropeanConvergence():

    # CONVERGENCE TESTS
    # COMPARE AMERICAN TREE VERSUS JAMSHIDIAN IN EUROPEAN LIMIT TO CHECK THAT
    # TREE HAS BEEN CORRECTLY CONSTRUCTED. FIND VERY GOOD AGREEMENT.

    # Build discount curve
    settlement_date = Date(1, 12, 2019)
    discount_curve = DiscountCurveFlat(settlement_date, 0.05,
                                       FrequencyTypes.CONTINUOUS)

    # Bond details
    issue_date = Date(1, 12, 2015)
    maturity_date = Date(1, 12, 2020)
    coupon = 0.05
    freq_type = FrequencyTypes.ANNUAL
    accrual_type = DayCountTypes.ACT_ACT_ICMA
    bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type)

    # Option Details - put expiry in the middle of a coupon period
    expiry_date = Date(1, 3, 2020)
    strike_price = 100.0
    face = 100.0

    timeSteps = range(100, 400, 100)
    strike_price = 100.0

    testCases.header("TIME", "N", "PUT_JAM", "PUT_TREE", "CALL_JAM",
                     "CALL_TREE")

    for num_time_steps in timeSteps:

        sigma = 0.05
        a = 0.1

        start = time.time()
        option_type = FinOptionTypes.EUROPEAN_PUT

        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)
        model1 = HWTree(sigma, a, num_time_steps)
        v1put = bond_option1.value(settlement_date, discount_curve, model1)

        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_ONLY)
        v2put = bond_option2.value(settlement_date, discount_curve, model2)

        option_type = FinOptionTypes.EUROPEAN_CALL

        bond_option1 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model1 = HWTree(sigma, a, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model1)

        bond_option2 = BondOption(bond, expiry_date, strike_price, face,
                                  option_type)

        model2 = HWTree(sigma, a, num_time_steps,
                        FinHWEuropeanCalcType.EXPIRY_TREE)
        v2call = bond_option2.value(settlement_date, discount_curve, model2)

        end = time.time()
        period = end - start
        testCases.print(period, num_time_steps, v1put, v2put, v1call, v2call)