Ejemplo n.º 1
0
def test_FinFXVanillaOptionBloombergExample():

    # Example Bloomberg Pricing at
    # https://stackoverflow.com/questions/48778712/fx-vanilla-call-price-in-quantlib-doesnt-match-bloomberg

    valuation_date = Date(13, 2, 2018)
    expiry_date = Date(15, 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
    forName = "EUR"
    domName = "USD"
    forDepoRate = 0.05  # EUR
    domDepoRate = 0.02  # USD

    currencyPair = forName + domName  # Always FORDOM
    spotFXRate = 1.30
    strikeFXRate = 1.3650
    volatility = 0.20

    spotDays = 0
    settlement_date = valuation_date.addWeekDays(spotDays)
    maturity_date = settlement_date.addMonths(12)
    notional = 1000000.0
    notionalCurrency = "EUR"
    calendar_type = CalendarTypes.TARGET

    depos = []
    fras = []
    swaps = []
    depo = FinIborDeposit(settlement_date, maturity_date, domDepoRate,
                          DayCountTypes.ACT_360, notional, calendar_type)
    depos.append(depo)
    domDiscountCurve = IborSingleCurve(valuation_date, depos, fras, swaps)

    depos = []
    fras = []
    swaps = []
    depo = FinIborDeposit(settlement_date, maturity_date, forDepoRate,
                          DayCountTypes.ACT_360, notional, calendar_type)
    depos.append(depo)
    forDiscountCurve = IborSingleCurve(valuation_date, depos, fras, swaps)

    model = FinModelBlackScholes(volatility)

    callOption = FinFXVanillaOption(expiry_date, strikeFXRate, currencyPair,
                                    FinOptionTypes.EUROPEAN_CALL, notional,
                                    notionalCurrency, 2)

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

    delta = callOption.delta(valuation_date, spotFXRate, domDiscountCurve,
                             forDiscountCurve, model)

    testCases.header("value", "delta")
    testCases.print(value, delta)
Ejemplo n.º 2
0
def test_FinFXVanillaOptionWystupExample1():

    # Example from Book extract by Uwe Wystup with results in Table 1.2
    # https://mathfinance.com/wp-content/uploads/2017/06/FXOptionsStructuredProducts2e-Extract.pdf

    # Not exactly T=1.0 but close so don't exact exact agreement
    # (in fact I do not get exact agreement even if I do set T=1.0)
    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
    ccy1 = "EUR"
    ccy2 = "USD"
    ccy1CCRate = 0.030  # EUR
    ccy2CCRate = 0.025  # USD

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

    notional = 1000000.0

    domDiscountCurve = DiscountCurveFlat(valuation_date, ccy2CCRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, ccy1CCRate)

    model = FinModelBlackScholes(volatility)

    # Two examples to show that changing the notional currency and notional
    # keeps the value unchanged
    notional = 1000000.0
    callOption = FinFXVanillaOption(expiry_date, strikeFXRate, currencyPair,
                                    FinOptionTypes.EUROPEAN_CALL, notional,
                                    "EUR", 2)

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

    notional = 1250000.0
    callOption = FinFXVanillaOption(expiry_date, strikeFXRate, currencyPair,
                                    FinOptionTypes.EUROPEAN_CALL, notional,
                                    "USD", 2)

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

    delta = callOption.delta(valuation_date, spotFXRate, domDiscountCurve,
                             forDiscountCurve, model)

    testCases.header("value", "delta")
    testCases.print(value, delta)
Ejemplo n.º 3
0
def test_FinFXVanillaOptionWystupExample2():

    # Example Bloomberg Pricing at
    # https://stackoverflow.com/questions/48778712/fx-vanilla-call-price-in-quantlib-doesnt-match-bloomberg

    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
    ccy1 = "EUR"
    ccy2 = "USD"
    ccy1CCRate = 0.0396  # EUR
    ccy2CCRate = 0.0357  # USD

    currencyPair = ccy1 + ccy2  # Always ccy1ccy2
    spotFXRate = 0.9090
    strikeFXRate = 0.9090
    volatility = 0.12

    notional = 1000000.0

    domDiscountCurve = DiscountCurveFlat(valuation_date, ccy2CCRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, ccy1CCRate)

    model = FinModelBlackScholes(volatility)

    # Two examples to show that changing the notional currency and notional
    # keeps the value unchanged
    notional = 1000000.0
    callOption = FinFXVanillaOption(expiry_date, strikeFXRate, currencyPair,
                                    FinOptionTypes.EUROPEAN_PUT, notional,
                                    "EUR", 2)

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

    delta = callOption.delta(valuation_date, spotFXRate, domDiscountCurve,
                             forDiscountCurve, model)

    testCases.header("value", "delta")
    testCases.print(value, delta)
Ejemplo n.º 4
0
def test_FinEquityChooserOptionMatlab():
    """https://fr.mathworks.com/help/fininst/chooserbybls.html """

    valuation_date = Date(1, 6, 2007)
    chooseDate = Date(31, 8, 2007)
    callExpiryDate = Date(2, 12, 2007)
    putExpiryDate = Date(2, 12, 2007)
    callStrike = 60.0
    putStrike = 60.0
    stock_price = 50.0
    volatility = 0.20
    interestRate = 0.10
    dividendYield = 0.05

    model = FinModelBlackScholes(volatility)

    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    chooserOption = FinEquityChooserOption(chooseDate,
                                           callExpiryDate,
                                           putExpiryDate,
                                           callStrike,
                                           putStrike)

    v = chooserOption.value(valuation_date,
                            stock_price,
                            discount_curve,
                            dividendCurve,
                            model)

    v_mc = chooserOption.valueMC(valuation_date,
                                 stock_price,
                                 discount_curve,
                                 dividendCurve,
                                 model, 20000)

    v_matlab = 8.9308
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "MATLAB", v_matlab, "MC", v_mc)
Ejemplo n.º 5
0
def test_FinEquityChooserOptionDerivicom():
    """http://derivicom.com/support/finoptionsxl/index.html?complex_chooser.htm """

    valuation_date = Date(1, 1, 2007)
    chooseDate = Date(1, 2, 2007)
    callExpiryDate = Date(1, 4, 2007)
    putExpiryDate = Date(1, 5, 2007)
    callStrike = 40.0
    putStrike = 35.0
    stock_price = 38.0
    volatility = 0.20
    interestRate = 0.08
    dividendYield = 0.0625

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    chooserOption = FinEquityChooserOption(chooseDate,
                                           callExpiryDate,
                                           putExpiryDate,
                                           callStrike,
                                           putStrike)

    v = chooserOption.value(valuation_date,
                            stock_price,
                            discount_curve,
                            dividendCurve,
                            model)

    v_mc = chooserOption.valueMC(valuation_date,
                                 stock_price,
                                 discount_curve,
                                 dividendCurve,
                                 model, 20000)

    v_derivicom = 1.0989
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "DERIVICOM", v_derivicom, "MC", v_mc)
Ejemplo n.º 6
0
def test_FinEquityChooserOptionHaug():
    """ Following example in Haug Page 130 """

    valuation_date = Date(1, 1, 2015)
    chooseDate = Date(2, 4, 2015)
    callExpiryDate = Date(1, 7, 2015)
    putExpiryDate = Date(2, 8, 2015)
    callStrike = 55.0
    putStrike = 48.0
    stock_price = 50.0
    volatility = 0.35
    interestRate = 0.10
    dividendYield = 0.05

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    chooserOption = FinEquityChooserOption(chooseDate,
                                           callExpiryDate,
                                           putExpiryDate,
                                           callStrike,
                                           putStrike)

    v = chooserOption.value(valuation_date,
                            stock_price,
                            discount_curve,
                            dividendCurve,
                            model)

    v_mc = chooserOption.valueMC(valuation_date,
                                 stock_price,
                                 discount_curve,
                                 dividendCurve,
                                 model, 20000)

    v_haug = 6.0508
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "HAUG", v_haug, "MC", v_mc)
def test_FinEquityBarrierOption():

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 1, 2016)
    stock_price = 100.0
    volatility = 0.20
    interestRate = 0.05
    dividendYield = 0.02
    optionType = FinEquityBarrierTypes.DOWN_AND_OUT_CALL

    drift = interestRate - dividendYield
    scheme = FinGBMNumericalScheme.NORMAL
    processType = FinProcessTypes.GBM

    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    model = FinModelBlackScholes(volatility)

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

    import time
    start = time.time()
    numObservationsPerYear = 100

    testCases.header(
        "Type",
        "K",
        "B",
        "S:",
        "Value:",
        "ValueMC",
        "Diff",
        "TIME")

    for optionType in FinEquityBarrierTypes:
        for stock_price in range(80, 120, 10):

            B = 110.0
            K = 100.0

            option = FinEquityBarrierOption(
                expiry_date, K, optionType, B, numObservationsPerYear)
            value = option.value(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)
            start = time.time()
            modelParams = (stock_price, drift, volatility, scheme)
            valueMC = option.valueMC(valuation_date,
                                     stock_price,
                                     discount_curve,
                                     dividendCurve,
                                     processType,
                                     modelParams)

            end = time.time()
            timeElapsed = round(end - start, 3)
            diff = valueMC - value

            testCases.print(
                optionType,
                K,
                B,
                stock_price,
                value,
                valueMC,
                diff,
                timeElapsed)

        for stock_price in range(80, 120, 10):

            B = 100.0
            K = 110.0

            option = FinEquityBarrierOption(
                expiry_date, K, optionType, B, numObservationsPerYear)
            value = option.value(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)
            start = time.time()
            modelParams = (stock_price, drift, volatility, scheme)
            valueMC = option.valueMC(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                processType,
                modelParams)
            end = time.time()
            timeElapsed = round(end - start, 3)
            diff = valueMC - value

            testCases.print(
                optionType,
                K,
                B,
                stock_price,
                value,
                valueMC,
                diff,
                timeElapsed)

        end = time.time()

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

    stock_prices = range(50, 150, 50)
    B = 105.0

    testCases.header("Type", "K", "B", "S:", "Value", "Delta", "Vega", "Theta")

    for optionType in FinEquityBarrierTypes:

        for stock_price in stock_prices:

            barrierOption = FinEquityBarrierOption(
                expiry_date, 100.0, optionType, B, numObservationsPerYear)

            value = barrierOption.value(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)
            delta = barrierOption.delta(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)
            vega = barrierOption.vega(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)
            theta = barrierOption.theta(
                valuation_date,
                stock_price,
                discount_curve,
                dividendCurve,
                model)

            testCases.print(
                optionType,
                K,
                B,
                stock_price,
                value,
                delta,
                vega,
                theta)
Ejemplo n.º 8
0
def testFinModelBlackScholes():

    valuation_date = Date(8, 5, 2015)
    expiry_date = Date(15, 1, 2016)

    strikePrice = 130.0
    stock_price = 127.62
    volatility = 0.20
    interestRate = 0.001
    dividendYield = 0.0163

    optionType = FinOptionTypes.AMERICAN_CALL
    euOptionType = FinOptionTypes.EUROPEAN_CALL

    amOption = FinEquityAmericanOption(expiry_date, strikePrice, optionType)

    ameuOption = FinEquityAmericanOption(expiry_date, strikePrice,
                                         euOptionType)

    euOption = FinEquityVanillaOption(expiry_date, strikePrice, euOptionType)

    discount_curve = DiscountCurveFlat(valuation_date, interestRate,
                                       FrequencyTypes.CONTINUOUS,
                                       DayCountTypes.ACT_365F)

    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield,
                                      FrequencyTypes.CONTINUOUS,
                                      DayCountTypes.ACT_365F)

    num_steps_per_year = 400

    modelTree = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     num_steps_per_year)

    v = amOption.value(valuation_date, stock_price, discount_curve,
                       dividendCurve, modelTree)
    #    print(v)

    modelApprox = FinModelBlackScholes(volatility,
                                       FinModelBlackScholesTypes.BARONE_ADESI)

    v = amOption.value(valuation_date, stock_price, discount_curve,
                       dividendCurve, modelApprox)

    #    print(v)

    v = ameuOption.value(valuation_date, stock_price, discount_curve,
                         dividendCurve, modelTree)

    #    print(v)

    v = euOption.value(valuation_date, stock_price, discount_curve,
                       dividendCurve, modelTree)

    #    print(v)

    amTreeValue = []
    amBAWValue = []
    euTreeValue = []
    euAnalValue = []
    volatility = 0.20
def test_FinNumbaNumbaParallel(useSobol):

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 7, 2015)
    stock_price = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    seed = 2021

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)

    useSobolInt = int(useSobol)

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

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

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

    num_points = 20
    v_exact = [value] * num_points

    num_pathsList = np.arange(1, num_points + 1, 1) * 1000000

    NUMBA_ONLY_v = []
    NUMBA_ONLY_t = []

    print("NUMBA ONLY")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_ONLY(valuation_date, stock_price,
                                                discount_curve, dividendYield,
                                                model, num_paths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMBA_ONLY_v.append(valueMC)
        NUMBA_ONLY_t.append(duration)

    NUMBA_PARALLEL_v = []
    NUMBA_PARALLEL_t = []

    print("NUMBA PARALLEL")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_PARALLEL(
            valuation_date, stock_price, discount_curve, dividendYield, model,
            num_paths, seed, useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMBA_PARALLEL_v.append(valueMC)
        NUMBA_PARALLEL_t.append(duration)

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

    import matplotlib.pyplot as plt

    if useSobol:
        title = "SOBOL: NUMBA VS NUMBA + PARALLEL"
    else:
        title = "PSEUDORANDOM: NUMBA VS NUMBA + PARALLEL"

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, NUMBA_ONLY_t, 'o-', label="NUMBA ONLY")
    plt.plot(num_pathsList, NUMBA_PARALLEL_t, 'o-', label="NUMBA PARALLEL")
    plt.xlabel("Number of Paths")
    plt.ylabel("Wall Time (s)")
    plt.legend()
    plt.title(title)

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, v_exact, label="EXACT")
    plt.plot(num_pathsList, NUMBA_ONLY_v, 'o-', label="NUMBA ONLY")
    plt.plot(num_pathsList, NUMBA_PARALLEL_v, 'o-', label="NUMBA PARALLEL")
    plt.xlabel("Number of Paths")
    plt.ylabel("Option Value")
    plt.legend()
    plt.title(title)
def test_FinNumbaNumpySpeed(useSobol):

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 7, 2015)
    stock_price = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    seed = 1999

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)

    useSobolInt = int(useSobol)

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

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

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

    num_points = 20
    v_exact = [value] * num_points

    ###########################################################################
    # DO UP TO 100K AS IT IS SLOW
    ###########################################################################

    num_pathsList = np.arange(1, num_points + 1, 1) * 100000

    NONUMBA_NONUMPY_v = []
    NONUMBA_NONUMPY_t = []

    print("PURE PYTHON")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NONUMBA_NONUMPY(
            valuation_date, stock_price, discount_curve, dividendYield, model,
            num_paths, seed, useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NONUMBA_NONUMPY_v.append(valueMC)
        NONUMBA_NONUMPY_t.append(duration + 1e-10)

    NUMPY_ONLY_v = []
    NUMPY_ONLY_t = []

    print("NUMPY ONLY")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_ONLY(valuation_date, stock_price,
                                                discount_curve, dividendYield,
                                                model, num_paths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMPY_ONLY_v.append(valueMC)
        NUMPY_ONLY_t.append(duration + 1e-10)

#    speedUp = np.array(NONUMBA_NONUMPY_t)/np.array(NUMPY_ONLY_t)
#    print(NUMPY_ONLY_t)
#    print(NONUMBA_NONUMPY_t)
#    print(speedUp)

    if useSobol:
        title = "SOBOL: PURE PYTHON VS NUMPY"
    else:
        title = "PSEUDORANDOM: PURE PYTHON VS NUMPY"

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, NONUMBA_NONUMPY_t, 'o-', label="PURE PYTHON")
    plt.plot(num_pathsList, NUMPY_ONLY_t, 'o-', label="NUMPY ONLY")
    plt.xlabel("Number of Paths")
    plt.ylabel("Wall Time (s)")
    plt.legend()
    plt.title(title)

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, v_exact, label="EXACT")
    plt.plot(num_pathsList, NONUMBA_NONUMPY_v, 'o-', label="PURE PYTHON")
    plt.plot(num_pathsList, NUMPY_ONLY_v, 'o-', label="NUMPY ONLY")

    plt.xlabel("Number of Paths")
    plt.ylabel("Option Value")
    plt.legend()
    plt.title(title)

    ###########################################################################
    # DO UP TO 10 MILLION NOW THAT WE HAVE NUMPY
    ###########################################################################

    num_pathsList = np.arange(1, num_points + 1, 1) * 1000000

    NUMPY_ONLY_v = []
    NUMPY_ONLY_t = []

    print("NUMPY ONLY")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_ONLY(valuation_date, stock_price,
                                                discount_curve, dividendYield,
                                                model, num_paths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMPY_ONLY_v.append(valueMC)
        NUMPY_ONLY_t.append(duration)

    NUMBA_NUMPY_v = []
    NUMBA_NUMPY_t = []

    print("NUMBA+NUMPY")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_NUMBA(valuation_date, stock_price,
                                                 discount_curve, dividendYield,
                                                 model, num_paths, seed,
                                                 useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMBA_NUMPY_v.append(valueMC)
        NUMBA_NUMPY_t.append(duration)

    NUMBA_ONLY_v = []
    NUMBA_ONLY_t = []

    print("NUMBA ONLY")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_ONLY(valuation_date, stock_price,
                                                discount_curve, dividendYield,
                                                model, num_paths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMBA_ONLY_v.append(valueMC)
        NUMBA_ONLY_t.append(duration)

    NUMBA_PARALLEL_v = []
    NUMBA_PARALLEL_t = []

    print("NUMBA PARALLEL")
    for num_paths in num_pathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_PARALLEL(
            valuation_date, stock_price, discount_curve, dividendYield, model,
            num_paths, seed, useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (num_paths, value, valueMC, duration))

        NUMBA_PARALLEL_v.append(valueMC)
        NUMBA_PARALLEL_t.append(duration)

#    speedUp = np.array(NUMBA_ONLY_t)/np.array(NUMBA_PARALLEL_t)
#    print("PARALLEL:", speedUp)

###########################################################################
# COMPUTED USING NUMSTEPS FROM 1M to 10M
###########################################################################

    CPP_t = np.array([
        0.075, 0.155, 0.223, 0.313, 0.359, 0.421, 0.495, 0.556, 0.64, 0.702,
        0.765, 0.841, 0.923, 0.982, 1.05, 1.125, 1.195, 1.261, 1.333, 1.408
    ])

    CPP_v = np.array([
        9.30872, 9.29576, 9.29422, 9.29832, 9.29863, 9.30153, 9.2994, 9.3025,
        9.29653, 9.29875, 9.29897, 9.29996, 9.29931, 9.29796, 9.29784, 9.2992,
        9.3001, 9.30093, 9.29876, 9.29921
    ])

    if useSobol:
        title = "SOBOL: COMPARING OPTIMISATIONS"
    else:
        title = "PSEUDORANDOM: COMPARING OPTIMISATIONS"

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, NUMPY_ONLY_t, 'o-', label="NUMPY ONLY")
    plt.plot(num_pathsList, NUMBA_NUMPY_t, 'o-', label="NUMBA + NUMPY")

    plt.xlabel("Number of Paths")
    plt.ylabel("Wall Time (s)")
    plt.legend()
    plt.title(title)

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

    if useSobol:
        title = "SOBOL: COMPARING OPTIMISATIONS"
    else:
        title = "PSEUDORANDOM: COMPARING OPTIMISATIONS"

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, NUMPY_ONLY_t, 'o-', label="NUMPY ONLY")
    plt.plot(num_pathsList, NUMBA_NUMPY_t, 'o-', label="NUMBA + NUMPY")
    plt.plot(num_pathsList, NUMBA_ONLY_t, 'o-', label="NUMBA ONLY")
    plt.plot(num_pathsList, NUMBA_PARALLEL_t, 'o-', label="NUMBA PARALLEL")

    if useSobol == False:
        plt.plot(num_pathsList, CPP_t, 'o-', label="C++")

    plt.xlabel("Number of Paths")
    plt.ylabel("Wall Time (s)")
    plt.legend()
    plt.title(title)

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

    plt.figure(figsize=(8, 6))
    plt.plot(num_pathsList, v_exact, label="EXACT")
    plt.plot(num_pathsList, NUMBA_ONLY_v, 'o-', label="NUMBA ONLY")
    plt.plot(num_pathsList, CPP_v, 'o-', label="C++")

    plt.xlabel("Number of Paths")
    plt.ylabel("Option Value")
    plt.legend()
    plt.title(title)
def test_FinEquityDigitalOption():

    underlyingType = FinDigitalOptionTypes.CASH_OR_NOTHING

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 1, 2016)
    stock_price = 100.0
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    model = FinModelBlackScholes(volatility)
    import time

    callOptionValues = []
    callOptionValuesMC = []
    num_pathsList = [
        10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000
    ]

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

    for num_paths in num_pathsList:

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

        callOptionValues.append(value)
        callOptionValuesMC.append(valueMC)

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

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

    stock_prices = range(50, 150, 50)
    callOptionValues = []
    callOptionDeltas = []
    callOptionVegas = []
    callOptionThetas = []

    for stock_price in stock_prices:
        callOption = FinEquityDigitalOption(expiry_date, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL,
                                            underlyingType)
        value = callOption.value(valuation_date, stock_price, discount_curve,
                                 dividendCurve, model)
        delta = callOption.delta(valuation_date, stock_price, discount_curve,
                                 dividendCurve, model)
        vega = callOption.vega(valuation_date, stock_price, discount_curve,
                               dividendCurve, model)
        theta = callOption.theta(valuation_date, stock_price, discount_curve,
                                 dividendCurve, model)
        callOptionValues.append(value)
        callOptionDeltas.append(delta)
        callOptionVegas.append(vega)
        callOptionThetas.append(theta)

    putOptionValues = []
    putOptionDeltas = []
    putOptionVegas = []
    putOptionThetas = []

    for stock_price in stock_prices:
        putOption = FinEquityDigitalOption(expiry_date, 100.0,
                                           FinOptionTypes.EUROPEAN_PUT,
                                           underlyingType)
        value = putOption.value(valuation_date, stock_price, discount_curve,
                                dividendCurve, model)
        delta = putOption.delta(valuation_date, stock_price, discount_curve,
                                dividendCurve, model)
        vega = putOption.vega(valuation_date, stock_price, discount_curve,
                              dividendCurve, model)
        theta = putOption.theta(valuation_date, stock_price, discount_curve,
                                dividendCurve, model)
        putOptionValues.append(value)
        putOptionDeltas.append(delta)
        putOptionVegas.append(vega)
        putOptionThetas.append(theta)
Ejemplo n.º 12
0
def test_FinFXAmericanOption():

    # 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
    ccy1 = "EUR"
    ccy2 = "USD"
    ccy1CCRate = 0.030  # EUR
    ccy2CCRate = 0.025  # USD

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

    domDiscountCurve = DiscountCurveFlat(valuation_date, ccy2CCRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, ccy1CCRate)

    model = FinModelBlackScholes(volatility)

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

    valuation_date = Date(1, 1, 2014)
    startAveragingDate = Date(1, 6, 2014)
    expiry_date = Date(1, 1, 2015)
    stock_price = 100.0
    volatility = 0.20
    interestRate = 0.30
    dividendYield = 0.10
    numObservations = 120  # daily as we have a half year
    accruedAverage = None
    K = 100
    seed = 1976

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    asianOption = FinEquityAsianOption(startAveragingDate, expiry_date, K,
                                       FinOptionTypes.EUROPEAN_CALL,
                                       numObservations)

    testCases.header("K", "Geometric", "Turnbull_Wakeman", "Curran", "FastMC",
                     "FastMC_CV")

    valuesTurnbull = []
    valuesCurran = []
    valuesGeometric = []
    valuesMC_fast = []
    valuesMC_CV = []

    num_pathsList = [5000]

    for num_paths in num_pathsList:

        accruedAverage = stock_price * 1.1

        valueMC_fast = asianOption._valueMC_fast(valuation_date, stock_price,
                                                 discount_curve, dividendCurve,
                                                 model, num_paths, seed,
                                                 accruedAverage)

        valueMC_CV = asianOption.valueMC(valuation_date, stock_price,
                                         discount_curve, dividendCurve, model,
                                         num_paths, seed, accruedAverage)

        valueGeometric = asianOption.value(
            valuation_date, stock_price, discount_curve, dividendCurve, model,
            FinAsianOptionValuationMethods.GEOMETRIC, accruedAverage)

        valueTurnbullWakeman = asianOption.value(
            valuation_date, stock_price, discount_curve, dividendCurve, model,
            FinAsianOptionValuationMethods.TURNBULL_WAKEMAN, accruedAverage)

        valueCurran = asianOption.value(valuation_date, stock_price,
                                        discount_curve, dividendCurve, model,
                                        FinAsianOptionValuationMethods.CURRAN,
                                        accruedAverage)

        valuesGeometric.append(valueGeometric)
        valuesTurnbull.append(valueTurnbullWakeman)
        valuesCurran.append(valueCurran)
        valuesMC_fast.append(valueMC_fast)
        valuesMC_CV.append(valueMC_CV)

        testCases.print(num_paths, valueGeometric, valueTurnbullWakeman,
                        valueCurran, valueMC_fast, valueMC_CV)
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
def testTimeEvolution():

    startAveragingDate = Date(1, 1, 2015)
    expiry_date = Date(1, 1, 2016)
    stock_price = 100.0
    volatility = 0.20
    interestRate = 0.30
    dividendYield = 0.10
    numObservations = 100  # weekly as we have a year
    accruedAverage = None
    K = 100
    seed = 1976

    model = FinModelBlackScholes(volatility)

    asianOption = FinEquityAsianOption(startAveragingDate, expiry_date, K,
                                       FinOptionTypes.EUROPEAN_CALL,
                                       numObservations)

    testCases.header("Date", "Geometric", "Turnbull_Wakeman", "Curran",
                     "FastMC", "FastMC_CV")

    valuesTurnbull = []
    valuesCurran = []
    valuesGeometric = []
    valuesMC_fast = []
    valuesMC_CV = []

    valuation_dates = []
    valuation_dates.append(Date(1, 4, 2014))
    valuation_dates.append(Date(1, 6, 2014))
    valuation_dates.append(Date(1, 8, 2014))
    valuation_dates.append(Date(1, 2, 2015))
    valuation_dates.append(Date(1, 4, 2015))
    valuation_dates.append(Date(1, 6, 2015))
    valuation_dates.append(Date(1, 8, 2015))

    num_paths = 10000

    for valuation_date in valuation_dates:

        accruedAverage = stock_price * 0.9

        discount_curve = DiscountCurveFlat(valuation_date, interestRate)
        dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

        valueMC_fast = asianOption._valueMC_fast(valuation_date, stock_price,
                                                 discount_curve, dividendCurve,
                                                 model, num_paths, seed,
                                                 accruedAverage)

        valueMC_CV = asianOption.valueMC(valuation_date, stock_price,
                                         discount_curve, dividendCurve, model,
                                         num_paths, seed, accruedAverage)

        valueGeometric = asianOption.value(
            valuation_date, stock_price, discount_curve, dividendCurve, model,
            FinAsianOptionValuationMethods.GEOMETRIC, accruedAverage)

        valueTurnbullWakeman = asianOption.value(
            valuation_date, stock_price, discount_curve, dividendCurve, model,
            FinAsianOptionValuationMethods.TURNBULL_WAKEMAN, accruedAverage)

        valueCurran = asianOption.value(valuation_date, stock_price,
                                        discount_curve, dividendCurve, model,
                                        FinAsianOptionValuationMethods.CURRAN,
                                        accruedAverage)

        valuesGeometric.append(valueGeometric)
        valuesTurnbull.append(valueTurnbullWakeman)
        valuesCurran.append(valueCurran)
        valuesMC_fast.append(valueMC_fast)
        valuesMC_CV.append(valueMC_CV)

        testCases.print(str(valuation_date), valueGeometric,
                        valueTurnbullWakeman, valueCurran, valueMC_fast,
                        valueMC_CV)
Ejemplo n.º 16
0
def test_FinFXBarrierOption():

    valuation_date = Date(1, 1, 2015)
    expiry_date = Date(1, 1, 2016)
    spotFXRate = 100.0
    currencyPair = "USDJPY"
    volatility = 0.20
    domInterestRate = 0.05
    forInterestRate = 0.02
    optionType = FinFXBarrierTypes.DOWN_AND_OUT_CALL
    notional = 100.0
    notionalCurrency = "USD"

    drift = domInterestRate - forInterestRate
    scheme = FinGBMNumericalScheme.ANTITHETIC
    processType = FinProcessTypes.GBM
    domDiscountCurve = DiscountCurveFlat(valuation_date, domInterestRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, forInterestRate)
    model = FinModelBlackScholes(volatility)

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

    import time
    start = time.time()
    numObservationsPerYear = 100

    for optionType in FinFXBarrierTypes:

        testCases.header("Type", "K", "B", "S", "Value", "ValueMC", "TIME",
                         "Diff")

        for spotFXRate in range(60, 140, 10):
            B = 110.0
            K = 100.0

            option = FinFXBarrierOption(expiry_date, K, currencyPair,
                                        optionType, B, numObservationsPerYear,
                                        notional, notionalCurrency)

            value = option.value(valuation_date, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)

            start = time.time()
            modelParams = (spotFXRate, drift, volatility, scheme)
            valueMC = option.valueMC(valuation_date, spotFXRate,
                                     domInterestRate, processType, modelParams)

            end = time.time()
            timeElapsed = round(end - start, 3)
            diff = valueMC - value

            testCases.print(optionType, K, B, spotFXRate, value, valueMC,
                            timeElapsed, diff)

        for spotFXRate in range(60, 140, 10):
            B = 100.0
            K = 110.0

            option = FinFXBarrierOption(expiry_date, K, currencyPair,
                                        optionType, B, numObservationsPerYear,
                                        notional, notionalCurrency)

            value = option.value(valuation_date, spotFXRate, domDiscountCurve,
                                 forDiscountCurve, model)

            start = time.time()
            modelParams = (spotFXRate, drift, volatility, scheme)
            valueMC = option.valueMC(valuation_date, spotFXRate,
                                     domInterestRate, processType, modelParams)

            end = time.time()
            timeElapsed = round(end - start, 3)
            diff = valueMC - value

            testCases.print(optionType, K, B, spotFXRate, value, valueMC,
                            timeElapsed, diff)

    end = time.time()

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

    spotFXRates = range(50, 150, 50)
    B = 105.0

    testCases.header("Type", "K", "B", "S:", "Value", "Delta", "Vega", "Theta")

    for optionType in FinFXBarrierTypes:
        for spotFXRate in spotFXRates:
            barrierOption = FinFXBarrierOption(expiry_date, 100.0,
                                               currencyPair, optionType, B,
                                               numObservationsPerYear,
                                               notional, notionalCurrency)

            value = barrierOption.value(valuation_date, spotFXRate,
                                        domDiscountCurve, forDiscountCurve,
                                        model)

            delta = barrierOption.delta(valuation_date, spotFXRate,
                                        domDiscountCurve, forDiscountCurve,
                                        model)

            vega = barrierOption.vega(valuation_date, spotFXRate,
                                      domDiscountCurve, forDiscountCurve,
                                      model)

            theta = barrierOption.theta(valuation_date, spotFXRate,
                                        domDiscountCurve, forDiscountCurve,
                                        model)

            testCases.print(optionType, K, B, spotFXRate, value, delta, vega,
                            theta)
Ejemplo n.º 17
0
from financepy.models.black_scholes import FinModelBlackScholes
from financepy.utils.date import Date
from financepy.utils.FinError import FinError

expiryDate = Date(1, 7, 2015)
call_option = FinEquityVanillaOption(expiryDate, 100.0,
                                     FinOptionTypes.EUROPEAN_CALL)
put_option = FinEquityVanillaOption(expiryDate, 100.0,
                                    FinOptionTypes.EUROPEAN_PUT)

valueDate = Date(1, 1, 2015)
stockPrice = 100
volatility = 0.30
interestRate = 0.05
dividendYield = 0.01
model = FinModelBlackScholes(volatility)
discountCurve = DiscountCurveFlat(valueDate, interestRate)
dividendCurve = DiscountCurveFlat(valueDate, dividendYield)


def test_call_option():
    v = call_option.value(valueDate, stockPrice, discountCurve, dividendCurve,
                          model)
    assert v.round(4) == 9.3021


def test_greeks():
    delta = call_option.delta(valueDate, stockPrice, discountCurve,
                              dividendCurve, model)
    vega = call_option.vega(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)
Ejemplo n.º 18
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

    spotFXRate = 1.20
    strikeFXRate = 1.250
    volatility = 0.10

    notional = 1000000.0

    domDiscountCurve = DiscountCurveFlat(valuation_date, ccy2CCRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, ccy1CCRate)

    model = FinModelBlackScholes(volatility)

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

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

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

    for spotFXRate in spotFXRates:

        callOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, notional,
                                        "USD")

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

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

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

        diff = (valueAmerican - valueEuropean)

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

        diff = (valueAmerican - valueEuropean)
        testCases.print("PUT:", "%9.6f" % spotFXRate, "%9.7f" % valueEuropean,
                        "%9.7f" % valueAmerican, "%9.7f" % diff)
def test_FinFXOneTouchOption():
    # 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)
    volatility = 0.20
    barrierLevel = 1.0  # H
    model = FinModelBlackScholes(volatility)

    domesticRate = 0.10
    foreignRate = 0.03

    num_paths = 20000
    num_steps_per_year = 252

    domCurve = DiscountCurveFlat(valuation_date, domesticRate)
    forCurve = DiscountCurveFlat(valuation_date, foreignRate)

    spotFXRate = 1.050
    paymentSize = 1.5

    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 = FinEquityOneTouchOption(expiry_date, downType, barrierLevel,
                                         paymentSize)

        v = option.value(valuation_date, spotFXRate, domCurve, forCurve, model)

        v_mc = option.valueMC(valuation_date, spotFXRate, domCurve, forCurve,
                              model, num_steps_per_year, num_paths)

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

    spotFXRate = 0.950
    paymentSize = 1.5

    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 = FinEquityOneTouchOption(expiry_date, upType, barrierLevel,
                                         paymentSize)

        v = option.value(valuation_date, spotFXRate, domCurve, forCurve, model)

        v_mc = option.valueMC(valuation_date, spotFXRate, domCurve, forCurve,
                              model, num_steps_per_year, num_paths)

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

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

    spotFXRate = 1.050

    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 = FinEquityOneTouchOption(expiry_date, downType, barrierLevel)

        v = option.value(valuation_date, spotFXRate, domCurve, forCurve, model)

        v_mc = option.valueMC(valuation_date, spotFXRate, domCurve, forCurve,
                              model, num_steps_per_year, num_paths)

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

    spotFXRate = 0.950

    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 = FinEquityOneTouchOption(expiry_date, upType, barrierLevel)

        v = option.value(valuation_date, spotFXRate, domCurve, forCurve, model)

        v_mc = option.valueMC(valuation_date, spotFXRate, domCurve, forCurve,
                              model, num_steps_per_year, num_paths)

        testCases.print("%60s " % upType, "%9.5f" % v, "%9.5f" % v_mc)
Ejemplo n.º 20
0
def test_FinFXVanillaOptionHullExample():

    #   Example from Hull 4th edition page 284
    valuation_date = Date(1, 1, 2015)
    expiry_date = valuation_date.addMonths(4)
    spotFXRate = 1.60
    volatility = 0.1411
    domInterestRate = 0.08
    forInterestRate = 0.11
    model = FinModelBlackScholes(volatility)
    domDiscountCurve = DiscountCurveFlat(valuation_date, domInterestRate)
    forDiscountCurve = DiscountCurveFlat(valuation_date, forInterestRate)

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

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

    for num_paths in num_pathsList:

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

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

        start = time.time()

        valueMC = callOption.valueMC(valuation_date, spotFXRate,
                                     domDiscountCurve, forDiscountCurve, model,
                                     num_paths)

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        testCases.print(spotFXRate, value, volatility, impliedVol)
def test_FinEquityCompoundOption():

    valuation_date = Date(1, 1, 2015)
    expiry_date1 = Date(1, 1, 2017)
    expiry_date2 = Date(1, 1, 2018)
    k1 = 5.0
    k2 = 95.0
    stock_price = 85.0
    volatility = 0.15
    interestRate = 0.035
    dividendYield = 0.01

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    num_stepsList = [100, 200, 500, 1000, 2000, 5000]

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

    stock_price = 85.0

    testCases.header("TYPE1", "TYPE2", "K1", "K2", "S", "TreeSteps", "Exact", "TreeValue")

    for optionType1 in [
            FinOptionTypes.EUROPEAN_CALL,
            FinOptionTypes.EUROPEAN_PUT]:
        for optionType2 in [
                FinOptionTypes.EUROPEAN_CALL,
                FinOptionTypes.EUROPEAN_PUT]:

            cmpdOption = FinEquityCompoundOption(expiry_date1, optionType1, k1,
                                                 expiry_date2, optionType2, k2)

            for num_steps in num_stepsList:
        
                value = cmpdOption.value(valuation_date, stock_price, discount_curve,
                                         dividendCurve, model)

                values = cmpdOption._valueTree(valuation_date, stock_price, discount_curve,
                                               dividendCurve, model, num_steps)
        
                testCases.print(optionType1, optionType2, k1, k2, stock_price,
                                num_steps, value, values[0])

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

    stock_price = 85.0

    testCases.header("TYPE1", "TYPE2", "K1", "K2", "S", "TreeSteps", "Exact", "TreeValue")

    for optionType1 in [
            FinOptionTypes.AMERICAN_CALL,
            FinOptionTypes.AMERICAN_PUT]:
        for optionType2 in [
                FinOptionTypes.AMERICAN_CALL,
                FinOptionTypes.AMERICAN_PUT]:

            cmpdOption = FinEquityCompoundOption(expiry_date1, optionType1, k1,
                                                 expiry_date2, optionType2, k2)

            for num_steps in num_stepsList:
        
                value = cmpdOption.value(valuation_date, stock_price, discount_curve,
                                         dividendCurve, model, num_steps)

                values = cmpdOption._valueTree(valuation_date, stock_price, discount_curve,
                                               dividendCurve, model, num_steps)
        
                testCases.print(optionType1, optionType2, k1, k2, stock_price,
                                num_steps, value, values[0])

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

    testCases.header("TYPE1", "TYPE2", "K1", "K2", "S", "Exact", "TreeSteps",
                     "TreeValue", "Diff", "DELTA", "GAMMA", "THETA")

    for optionType1 in [
            FinOptionTypes.EUROPEAN_CALL,
            FinOptionTypes.EUROPEAN_PUT]:
        for optionType2 in [
                FinOptionTypes.EUROPEAN_CALL,
                FinOptionTypes.EUROPEAN_PUT]:

            cmpdOption = FinEquityCompoundOption(
                expiry_date1, optionType1, k1,
                expiry_date2, optionType2, k2)
            stock_prices = range(70, 100, 10)

            for stock_price in stock_prices:
                value = cmpdOption.value(
                    valuation_date,
                    stock_price,
                    discount_curve,
                    dividendCurve,
                    model)
                delta = cmpdOption.delta(
                    valuation_date,
                    stock_price,
                    discount_curve,
                    dividendCurve,
                    model)
                vega = cmpdOption.vega(
                    valuation_date,
                    stock_price,
                    discount_curve,
                    dividendCurve,
                    model)
                theta = cmpdOption.theta(
                    valuation_date,
                    stock_price,
                    discount_curve,
                    dividendCurve,
                    model)

                values = cmpdOption._valueTree(valuation_date, stock_price,
                                               discount_curve, dividendCurve,
                                               model)

                diff = value - values[0]

                testCases.print(
                    optionType1,
                    optionType2,
                    k1,
                    k2,
                    stock_price,
                    value,
                    num_steps,
                    values[0],
                    diff,
                    delta,
                    vega,
                    theta)
Ejemplo n.º 22
0
def testMCTimings():

    valuation_date = Date(1, 1, 2014)
    startAveragingDate = Date(1, 6, 2014)
    expiry_date = Date(1, 1, 2015)
    stock_price = 100.0
    volatility = 0.20
    interestRate = 0.30
    dividendYield = 0.10
    numObservations = 120  # daily as we have a half year
    accruedAverage = None
    K = 100
    seed = 1976

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interestRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

    asianOption = FinEquityAsianOption(startAveragingDate, expiry_date, K,
                                       FinOptionTypes.EUROPEAN_CALL,
                                       numObservations)

    testCases.header("NUMPATHS", "VALUE", "TIME", "VALUE_MC", "TIME",
                     "VALUE_MC_CV", "TIME")

    valuesMC = []
    valuesMC_fast = []
    valuesMC_fast_CV = []

    tvaluesMC = []
    tvaluesMC_fast = []
    tvaluesMC_fast_CV = []

    num_pathsList = [5000]

    for num_paths in num_pathsList:

        accruedAverage = stock_price * 1.1

        start = time.time()
        valueMC = asianOption.valueMC(valuation_date, stock_price,
                                      discount_curve, dividendCurve, model,
                                      num_paths, seed, accruedAverage)

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

        start = time.time()
        valueMC_fast = asianOption._valueMC_fast(valuation_date, stock_price,
                                                 discount_curve, dividendCurve,
                                                 model, num_paths, seed,
                                                 accruedAverage)

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

        start = time.time()
        valueMC_fast_CV = asianOption.valueMC(valuation_date, stock_price,
                                              discount_curve, dividendCurve,
                                              model, num_paths, seed,
                                              accruedAverage)

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

        valuesMC.append(valueMC)
        valuesMC_fast.append(valueMC_fast)
        valuesMC_fast_CV.append(valueMC_fast_CV)

        tvaluesMC.append(t_MC)
        tvaluesMC_fast.append(t_MC_fast)
        tvaluesMC_fast_CV.append(t_MC_fast_CV)

        testCases.print(num_paths, valueMC, t_MC, valueMC_fast, t_MC_fast,
                        valueMC_fast_CV, t_MC_fast_CV)
def test_FinBinomialTree():

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

    valuation_date = Date(1, 1, 2016)
    expiry_date = Date(1, 1, 2017)

    model = FinModelBlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, riskFreeRate)
    dividendCurve = DiscountCurveFlat(valuation_date, dividendYield)

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

    strikePrice = 50.0

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

    putOption = FinEquityVanillaOption(expiry_date, strikePrice,
                                       FinOptionTypes.EUROPEAN_PUT)
    value = putOption.value(valuation_date, stock_price, discount_curve,
                            dividendCurve, model)
    delta = putOption.delta(valuation_date, stock_price, discount_curve,
                            dividendCurve, model)
    gamma = putOption.gamma(valuation_date, stock_price, discount_curve,
                            dividendCurve, model)
    theta = putOption.theta(valuation_date, stock_price, discount_curve,
                            dividendCurve, model)
    testCases.header("BS Value", "BS Delta", "BS Gamma", "BS Theta")
    testCases.print(value, delta, gamma, theta)

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

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

    for num_steps in num_stepsList:
        start = time.time()
        tree = FinEquityBinomialTree()
        results = tree.value(stock_price, discount_curve, dividendCurve,
                             volatility, num_steps, valuation_date, payoff,
                             expiry_date, payoff, exercise, params)
        end = time.time()
        duration = end - start
        testCases.print(num_steps, results, duration)

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

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

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

    for num_steps in num_stepsList:
        start = time.time()
        tree = FinEquityBinomialTree()
        results = tree.value(stock_price, discount_curve, dividendCurve,
                             volatility, num_steps, valuation_date, payoff,
                             expiry_date, payoff, exercise, params)
        end = time.time()
        duration = end - start
        testCases.print(num_steps, results, duration)

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

    callOption = FinEquityVanillaOption(expiry_date, strikePrice,
                                        FinOptionTypes.EUROPEAN_CALL)
    value = callOption.value(valuation_date, stock_price, discount_curve,
                             dividendCurve, model)
    delta = callOption.delta(valuation_date, stock_price, discount_curve,
                             dividendCurve, model)
    gamma = callOption.gamma(valuation_date, stock_price, discount_curve,
                             dividendCurve, model)
    theta = callOption.theta(valuation_date, stock_price, discount_curve,
                             dividendCurve, model)
    testCases.header("BS Value", "BS Delta", "BS Gamma", "BS Theta")
    testCases.print(value, delta, gamma, theta)

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

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

        results = tree.value(stock_price, discount_curve, dividendCurve,
                             volatility, num_steps, valuation_date, payoff,
                             expiry_date, payoff, exercise, params)

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

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

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

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

        results = tree.value(stock_price, discount_curve, dividendCurve,
                             volatility, num_steps, valuation_date, payoff,
                             expiry_date, payoff, exercise, params)

        end = time.time()
        duration = end - start
        testCases.print(num_steps, results, duration)
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."