def testImpliedVolatility_NEW():


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

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

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

        model = FinModelBlackScholes(vol)

        for timeToExpiry in timesToExpiry:     

            expiryDate = valueDate.addYears(timeToExpiry)

            for strike in strikes:

                for optionType in optionTypes:

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

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

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

                    if value - intrinsic > 1e-10:

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

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

    assert numFails == 694, "Num Fails has changed."
Beispiel #2
0
def test_FinEquityVanillaOption():

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

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

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

    for numPaths in numPathsList:

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

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

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

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

    for stockPrice in stockPrices:

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

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

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

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

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

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

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

    for stockPrice in stockPrices:

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

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

    stockPrices = range(80, 120, 2)

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

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

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

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

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

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

    stockPrices = range(60, 150, 2)

    for stockPrice in stockPrices:
        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        impliedVol = callOption.impliedVolatility(valueDate, stockPrice,
                                                  discountCurve, dividendYield,
                                                  value)
        testCases.print(stockPrice, value, volatility, impliedVol)
def testImpliedVolatility():

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

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

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

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

    for vol in sigmas:

        model = FinModelBlackScholes(vol)

        for expiryDate in expiryDates:

            for strike in strikes:

                for optionType in optionTypes:

                    option = FinEquityVanillaOption(expiryDate, 100.0,
                                                    optionType)

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

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

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

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

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

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

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

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

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