def testFinModelBlackScholes():

    valueDate = FinDate(8, 5, 2015)
    expiryDate = FinDate(15, 1, 2016)

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

    optionType = FinOptionTypes.AMERICAN_CALL
    euOptionType = FinOptionTypes.EUROPEAN_CALL

    amOption = FinEquityAmericanOption(expiryDate, strikePrice, optionType)

    ameuOption = FinEquityAmericanOption(expiryDate, strikePrice, euOptionType)

    euOption = FinEquityVanillaOption(expiryDate, strikePrice, euOptionType)

    discountCurve = FinDiscountCurveFlat(valueDate, interestRate,
                                         FinFrequencyTypes.CONTINUOUS,
                                         FinDayCountTypes.ACT_365F)

    numStepsPerYear = 400

    modelTree = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     {'numStepsPerYear': numStepsPerYear})

    v = amOption.value(valueDate, stockPrice, discountCurve, dividendYield,
                       modelTree)
    #    print(v)

    modelApprox = FinModelBlackScholes(volatility,
                                       FinModelBlackScholesTypes.BARONE_ADESI,
                                       None)

    v = amOption.value(valueDate, stockPrice, discountCurve, dividendYield,
                       modelApprox)

    #    print(v)

    v = ameuOption.value(valueDate, stockPrice, discountCurve, dividendYield,
                         modelTree)

    #    print(v)

    v = euOption.value(valueDate, stockPrice, discountCurve, dividendYield,
                       modelTree)

    #    print(v)

    amTreeValue = []
    amBAWValue = []
    euTreeValue = []
    euAnalValue = []
    volatility = 0.20
def test_FinEquityCliquetOptionHaug():
    ''' Following example in Haug Page 130 '''

    startDate = FinDate(1, 1, 2015)
    finalExpiryDate = FinDate(1, 1, 2017)
    freqType = FinFrequencyTypes.QUARTERLY
    optionType = FinOptionTypes.EUROPEAN_CALL

    cliquetOption = FinEquityCliquetOption(startDate,
                                           finalExpiryDate,
                                           optionType,
                                           freqType)

    valueDate = FinDate(1, 8, 2016)
    stockPrice = 50.0
    volatility = 0.35
    interestRate = 0.10
    dividendYield = 0.05
    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    v = cliquetOption.value(valueDate,
                            stockPrice,
                            discountCurve,
                            dividendYield,
                            model)

    testCases.header("LABEL", "VALUE")
    testCases.print("FINANCEPY", v)
Пример #3
0
def test_FinEquityChooserOptionHaug():
    ''' Following example in Haug Page 130 '''

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

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

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

    v = chooserOption.value(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)

    v_mc = chooserOption.valueMC(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model, 20000)

    v_haug = 6.0508
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "HAUG", v_haug, "MC", v_mc)
Пример #4
0
def test_FinEquityChooserOptionMatlab():
    '''https://fr.mathworks.com/help/fininst/chooserbybls.html '''

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

    model = FinModelBlackScholes(volatility)

    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

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

    v = chooserOption.value(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)

    v_mc = chooserOption.valueMC(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model, 20000)

    v_matlab = 8.9308
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "MATLAB", v_matlab, "MC", v_mc)
Пример #5
0
def test_FinEquityChooserOptionDerivicom():
    '''http://derivicom.com/support/finoptionsxl/index.html?complex_chooser.htm '''

    valueDate = FinDate(1, 1, 2007)
    chooseDate = FinDate(1, 2, 2007)
    callExpiryDate = FinDate(1, 4, 2007)
    putExpiryDate = FinDate(1, 5, 2007)
    callStrike = 40.0
    putStrike = 35.0
    stockPrice = 38.0
    volatility = 0.20
    interestRate = 0.08
    dividendYield = 0.0625

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

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

    v = chooserOption.value(valueDate, stockPrice, discountCurve,
                            dividendCurve, model)

    v_mc = chooserOption.valueMC(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model, 20000)

    v_derivicom = 1.0989
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "DERIVICOM", v_derivicom, "MC", v_mc)
Пример #6
0
def test_FinEquityCliquetOption():

    startDate = FinDate(1, 1, 2014)
    finalExpiryDate = FinDate(1, 1, 2017)
    freqType = FinFrequencyTypes.QUARTERLY
    optionType = FinOptionTypes.EUROPEAN_CALL

    cliquetOption = FinEquityCliquetOption(startDate,
                                           finalExpiryDate,
                                           optionType,
                                           freqType)

    valueDate = FinDate(1, 1, 2015)
    stockPrice = 100.0
    volatility = 0.20
    interestRate = 0.05
    dividendYield = 0.02
    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

    v = cliquetOption.value(valueDate,
                            stockPrice,
                            discountCurve,
                            dividendCurve,
                            model)

    testCases.header("LABEL", "VALUE")
    testCases.print("FINANCEPY", v)
Пример #7
0
def test_FinFXVanillaOptionBloombergExample():

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

    valuationDate = FinDate(13, 2, 2018)
    expiryDate = FinDate(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
    settlementDate = valuationDate.addWeekDays(spotDays)
    maturityDate = settlementDate.addMonths(12)
    notional = 1000000.0
    notionalCurrency = "EUR"
    calendarType = FinCalendarTypes.TARGET

    depos = []
    fras = []
    swaps = []
    depo = FinIborDeposit(settlementDate, maturityDate, domDepoRate,
                          FinDayCountTypes.ACT_360, notional, calendarType)
    depos.append(depo)
    domDiscountCurve = FinIborSingleCurve(valuationDate, depos, fras, swaps)

    depos = []
    fras = []
    swaps = []
    depo = FinIborDeposit(settlementDate, maturityDate, forDepoRate,
                          FinDayCountTypes.ACT_360, notional, calendarType)
    depos.append(depo)
    forDiscountCurve = FinIborSingleCurve(valuationDate, depos, fras, swaps)

    model = FinModelBlackScholes(volatility)

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

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

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

    testCases.header("value", "delta")
    testCases.print(value, delta)
Пример #8
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)
    valueDate = FinDate(13, 2, 2018)
    expiryDate = FinDate(13, 2, 2019)

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

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

    notional = 1000000.0

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

    model = FinModelBlackScholes(volatility)

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

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

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

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

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

    testCases.header("value", "delta")
    testCases.print(value, delta)
Пример #9
0
def test_FinFXVanillaOptionWystupExample2():

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

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

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

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

    notional = 1000000.0

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

    model = FinModelBlackScholes(volatility)

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

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

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

    testCases.header("value", "delta")
    testCases.print(value, delta)
Пример #10
0
def testTimeEvolution():

    startAveragingDate = FinDate(2015, 1, 1)
    expiryDate = FinDate(2016, 1, 1)
    stockPrice = 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, expiryDate, K,
                                       FinOptionTypes.EUROPEAN_CALL,
                                       numObservations)

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

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

    valueDates = []
    valueDates.append(FinDate(2014, 4, 1))
    valueDates.append(FinDate(2014, 6, 1))
    valueDates.append(FinDate(2014, 8, 1))
    valueDates.append(FinDate(2015, 2, 1))
    valueDates.append(FinDate(2015, 4, 1))
    valueDates.append(FinDate(2015, 6, 1))
    valueDates.append(FinDate(2015, 8, 1))

    numPaths = 10000

    for valueDate in valueDates:

        accruedAverage = stockPrice * 0.9

        discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

        valueMC_fast = asianOption._valueMC_fast(valueDate, stockPrice,
                                                 discountCurve, dividendYield,
                                                 model, numPaths, seed,
                                                 accruedAverage)

        valueMC_CV = asianOption.valueMC(valueDate, stockPrice, discountCurve,
                                         dividendYield, model, numPaths, seed,
                                         accruedAverage)

        valueGeometric = asianOption.value(
            valueDate, stockPrice, discountCurve, dividendYield, model,
            FinAsianOptionValuationMethods.GEOMETRIC, accruedAverage)

        valueTurnbullWakeman = asianOption.value(
            valueDate, stockPrice, discountCurve, dividendYield, model,
            FinAsianOptionValuationMethods.TURNBULL_WAKEMAN, accruedAverage)

        valueCurran = asianOption.value(valueDate, stockPrice, discountCurve,
                                        dividendYield, 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(valueDate), valueGeometric, valueTurnbullWakeman,
                        valueCurran, valueMC_fast, valueMC_CV)
Пример #11
0
def test_FinNumbaNumbaParallel(useSobol):

    valueDate = FinDate(1, 1, 2015)
    expiryDate = FinDate(1, 7, 2015)
    stockPrice = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    seed = 2021

    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    useSobolInt = int(useSobol)

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

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

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

    numPoints = 20
    v_exact = [value] * numPoints

    numPathsList = np.arange(1, numPoints + 1, 1) * 1000000

    NUMBA_ONLY_v = []
    NUMBA_ONLY_t = []

    print("NUMBA ONLY")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_ONLY(valueDate, stockPrice,
                                                discountCurve, dividendYield,
                                                model, numPaths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

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

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

    NUMBA_PARALLEL_v = []
    NUMBA_PARALLEL_t = []

    print("NUMBA PARALLEL")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_PARALLEL(valueDate, stockPrice,
                                                    discountCurve,
                                                    dividendYield, model,
                                                    numPaths, seed,
                                                    useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (numPaths, 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(numPathsList, NUMBA_ONLY_t, 'o-', label="NUMBA ONLY")
    plt.plot(numPathsList, 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(numPathsList, v_exact, label="EXACT")
    plt.plot(numPathsList, NUMBA_ONLY_v, 'o-', label="NUMBA ONLY")
    plt.plot(numPathsList, NUMBA_PARALLEL_v, 'o-', label="NUMBA PARALLEL")
    plt.xlabel("Number of Paths")
    plt.ylabel("Option Value")
    plt.legend()
    plt.title(title)
Пример #12
0
def test_FinNumbaNumpySpeed(useSobol):

    valueDate = FinDate(1, 1, 2015)
    expiryDate = FinDate(1, 7, 2015)
    stockPrice = 100
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    seed = 1999

    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    useSobolInt = int(useSobol)

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

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

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

    numPoints = 20
    v_exact = [value] * numPoints

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

    numPathsList = np.arange(1, numPoints + 1, 1) * 100000

    NONUMBA_NONUMPY_v = []
    NONUMBA_NONUMPY_t = []

    print("PURE PYTHON")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NONUMBA_NONUMPY(valueDate, stockPrice,
                                                     discountCurve,
                                                     dividendYield, model,
                                                     numPaths, seed,
                                                     useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (numPaths, 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 numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_ONLY(valueDate, stockPrice,
                                                discountCurve, dividendYield,
                                                model, numPaths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (numPaths, 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(numPathsList, NONUMBA_NONUMPY_t, 'o-', label="PURE PYTHON")
    plt.plot(numPathsList, 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(numPathsList, v_exact, label="EXACT")
    plt.plot(numPathsList, NONUMBA_NONUMPY_v, 'o-', label="PURE PYTHON")
    plt.plot(numPathsList, 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
    ###########################################################################

    numPathsList = np.arange(1, numPoints + 1, 1) * 1000000

    NUMPY_ONLY_v = []
    NUMPY_ONLY_t = []

    print("NUMPY ONLY")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_ONLY(valueDate, stockPrice,
                                                discountCurve, dividendYield,
                                                model, numPaths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

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

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

    NUMBA_NUMPY_v = []
    NUMBA_NUMPY_t = []

    print("NUMBA+NUMPY")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMPY_NUMBA(valueDate, stockPrice,
                                                 discountCurve, dividendYield,
                                                 model, numPaths, seed,
                                                 useSobolInt)
        end = time.time()
        duration = end - start

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

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

    NUMBA_ONLY_v = []
    NUMBA_ONLY_t = []

    print("NUMBA ONLY")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_ONLY(valueDate, stockPrice,
                                                discountCurve, dividendYield,
                                                model, numPaths, seed,
                                                useSobolInt)
        end = time.time()
        duration = end - start

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

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

    NUMBA_PARALLEL_v = []
    NUMBA_PARALLEL_t = []

    print("NUMBA PARALLEL")
    for numPaths in numPathsList:

        start = time.time()
        valueMC = callOption.valueMC_NUMBA_PARALLEL(valueDate, stockPrice,
                                                    discountCurve,
                                                    dividendYield, model,
                                                    numPaths, seed,
                                                    useSobolInt)
        end = time.time()
        duration = end - start

        print("%10d %9.5f %9.5f %9.6f" % (numPaths, 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(numPathsList, NUMPY_ONLY_t, 'o-', label="NUMPY ONLY")
    plt.plot(numPathsList, 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(numPathsList, NUMPY_ONLY_t, 'o-', label="NUMPY ONLY")
    plt.plot(numPathsList, NUMBA_NUMPY_t, 'o-', label="NUMBA + NUMPY")
    plt.plot(numPathsList, NUMBA_ONLY_t, 'o-', label="NUMBA ONLY")
    plt.plot(numPathsList, NUMBA_PARALLEL_t, 'o-', label="NUMBA PARALLEL")

    if useSobol == False:
        plt.plot(numPathsList, 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(numPathsList, v_exact, label="EXACT")
    plt.plot(numPathsList, NUMBA_ONLY_v, 'o-', label="NUMBA ONLY")
    plt.plot(numPathsList, CPP_v, 'o-', label="C++")

    plt.xlabel("Number of Paths")
    plt.ylabel("Option Value")
    plt.legend()
    plt.title(title)
Пример #13
0
        def _price_option(contract_type_, contract_type_fin_):
            for i in range(len(expiry_date)):
                built_vol_surface = False

                # If we have a "key strike" need to fit the vol surface
                if isinstance(strike[i], str):
                    if not (built_vol_surface):

                        fx_vol_surface.build_vol_surface(horizon_date[i])
                        fx_vol_surface.extract_vol_surface(
                            num_strike_intervals=None)

                        built_vol_surface = True

                    # Delta neutral strike/or whatever strike is quoted as ATM
                    # usually this is ATM delta neutral strike, but can sometimes be ATMF for some Latam
                    # Take the vol directly quoted, rather than getting it from building vol surface
                    if strike[i] == 'atm':
                        strike[i] = fx_vol_surface.get_atm_strike(tenor)
                        vol[i] = fx_vol_surface.get_atm_quoted_vol(
                            tenor) / 100.0
                        # vol[i] = fx_vol_surface.get_atm_vol(tenor) / 100.0 # interpolated
                    elif strike[i] == 'atms':
                        strike[i] = fx_vol_surface.get_spot(
                        )  # Interpolate vol later
                    elif strike[i] == 'atmf':
                        # Quoted tenor, no need to interpolate
                        strike[i] = float(fx_vol_surface.get_all_market_data()[cross + ".close"][horizon_date[i]]) \
                                          + (float(fx_vol_surface.get_all_market_data()[cross + tenor + ".close"][horizon_date[i]]) \
                                    / self._fx_forwards_pricer.get_forwards_divisor(cross[3:6]))

                        # Interpolate vol later
                    elif strike[i] == '25d-otm':
                        if 'call' in contract_type_:
                            strike[i] = fx_vol_surface.get_25d_call_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_25d_call_vol(
                                tenor) / 100.0
                        elif 'put' in contract_type_:
                            strike[i] = fx_vol_surface.get_25d_put_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_25d_put_vol(
                                tenor) / 100.0
                    elif strike[i] == '10d-otm':
                        if 'call' in contract_type_:
                            strike[i] = fx_vol_surface.get_10d_call_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_10d_call_vol(
                                tenor) / 100.0
                        elif 'put' in contract_type_:
                            strike[i] = fx_vol_surface.get_10d_put_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_10d_put_vol(
                                tenor) / 100.0

                if not (built_vol_surface):
                    try:
                        fx_vol_surface.build_vol_surface(horizon_date[i])
                    except:
                        logger.warn("Failed to build vol surface for " +
                                    str(horizon_date) +
                                    ", won't be able to interpolate vol")
                    # fx_vol_surface.extract_vol_surface(num_strike_intervals=None)

                # If an implied vol hasn't been provided, interpolate that one, fit the vol surface (if hasn't already been
                # done)
                if np.isnan(vol[i]):

                    if tenor is None:
                        vol[i] = fx_vol_surface.calculate_vol_for_strike_expiry(
                            strike[i], expiry_date=expiry_date[i], tenor=None)
                    else:
                        vol[i] = fx_vol_surface.calculate_vol_for_strike_expiry(
                            strike[i], expiry_date=None, tenor=tenor)

                model = FinModelBlackScholes(float(vol[i]))

                logger.info("Pricing " + contract_type_ +
                            " option, horizon date = " + str(horizon_date[i]) +
                            ", expiry date = " + str(expiry_date[i]))

                option = FinFXVanillaOption(self._findate(expiry_date[i]),
                                            strike[i], cross,
                                            contract_type_fin_, notional,
                                            cross[0:3])

                spot[i] = fx_vol_surface.get_spot()
                """ FinancePy will return the value in the following dictionary for values
                    {'v': vdf,
                    "cash_dom": cash_dom,
                    "cash_for": cash_for,
                    "pips_dom": pips_dom,
                    "pips_for": pips_for,
                    "pct_dom": pct_dom,
                    "pct_for": pct_for,
                    "not_dom": notional_dom,
                    "not_for": notional_for,
                    "ccy_dom": self._domName,
                    "ccy_for": self._forName}
                """

                option_values[i] = option_values[i] + option.value(
                    self._findate(horizon_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[premium_output.replace('-', '_')]

                intrinsic_values[i] = intrinsic_values[i] + option.value(
                    self._findate(expiry_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[premium_output.replace('-', '_')]
                """FinancePy returns this dictionary for deltas
                    {"pips_spot_delta": pips_spot_delta,
                    "pips_fwd_delta": pips_fwd_delta,
                    "pct_spot_delta_prem_adj": pct_spot_delta_prem_adj,
                    "pct_fwd_delta_prem_adj": pct_fwd_delta_prem_adj}
                """

                delta[i] = delta[i] + option.delta(
                    self._findate(horizon_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[delta_output.replace('-', '_')]
Пример #14
0
        def _price_option(contract_type_, contract_type_fin_):
            for i in range(len(expiry_date)):
                built_vol_surface = False

                # If we have a "key strike" need to fit the vol surface
                if isinstance(strike[i], str):
                    if not (built_vol_surface):

                        fx_vol_surface.build_vol_surface(horizon_date[i])
                        fx_vol_surface.extract_vol_surface(
                            num_strike_intervals=None)

                        built_vol_surface = True

                    if strike[i] == 'atm':
                        strike[i] = fx_vol_surface.get_atm_strike(tenor)
                        vol[i] = fx_vol_surface.get_atm_vol(tenor) / 100.0
                    elif strike[i] == 'atms':
                        strike[i] = fx_vol_surface.get_spot()
                    elif strike[i] == 'atmf':

                        delivery_date = self._calendar.get_delivery_date_from_horizon_date(
                            horizon_date[i], cal=cross)

                        strike[i] = self._fx_forwards_price.price_instrument(
                            cross,
                            delivery_date,
                            market_df=fx_vol_surface.get_all_market_data())
                    elif strike[i] == '25d-otm':
                        if 'call' in contract_type_:
                            strike[i] = fx_vol_surface.get_25d_call_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_25d_call_strike(
                                tenor) / 100.0
                        elif 'put' in contract_type_:
                            strike[i] = fx_vol_surface.get_25d_put_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_25d_put_strike(
                                tenor) / 100.0
                    elif strike[i] == '10d-otm':
                        if 'call' in contract_type_:
                            strike[i] = fx_vol_surface.get_10d_call_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_10d_call_strike(
                                tenor) / 100.0
                        elif 'put' in contract_type_:
                            strike[i] = fx_vol_surface.get_10d_put_strike(
                                tenor)
                            vol[i] = fx_vol_surface.get_10d_put_strike(
                                tenor) / 100.0

                if not (built_vol_surface):
                    fx_vol_surface.build_vol_surface(horizon_date[i])
                    # fx_vol_surface.extract_vol_surface(num_strike_intervals=None)

                # If an implied vol hasn't been provided, interpolate that one, fit the vol surface (if hasn't already been
                # done)
                if np.isnan(vol[i]):

                    if tenor is None:
                        vol[i] = fx_vol_surface.calculate_vol_for_strike_expiry(
                            strike[i], expiry_date=expiry_date[i], tenor=None)
                    else:
                        vol[i] = fx_vol_surface.calculate_vol_for_strike_expiry(
                            strike[i], expiry_date=None, tenor=tenor)

                model = FinModelBlackScholes(float(vol[i]))

                logger.info("Pricing " + contract_type_ +
                            " option, horizon date = " + str(horizon_date[i]) +
                            ", expiry date = " + str(expiry_date[i]))

                option = FinFXVanillaOption(self._findate(expiry_date[i]),
                                            strike[i], cross,
                                            contract_type_fin_, notional,
                                            cross[0:3])

                spot[i] = fx_vol_surface.get_spot()
                """ FinancePy will return the value in the following dictionary for values
                    {'v': vdf,
                    "cash_dom": cash_dom,
                    "cash_for": cash_for,
                    "pips_dom": pips_dom,
                    "pips_for": pips_for,
                    "pct_dom": pct_dom,
                    "pct_for": pct_for,
                    "not_dom": notional_dom,
                    "not_for": notional_for,
                    "ccy_dom": self._domName,
                    "ccy_for": self._forName}
                """

                option_values[i] = option_values[i] + option.value(
                    self._findate(horizon_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[premium_output.replace('-', '_')]

                intrinsic_values[i] = intrinsic_values[i] + option.value(
                    self._findate(expiry_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[premium_output.replace('-', '_')]
                """FinancePy returns this dictionary for deltas
                    {"pips_spot_delta": pips_spot_delta,
                    "pips_fwd_delta": pips_fwd_delta,
                    "pct_spot_delta_prem_adj": pct_spot_delta_prem_adj,
                    "pct_fwd_delta_prem_adj": pct_fwd_delta_prem_adj}
                """

                delta[i] = delta[i] + option.delta(
                    self._findate(horizon_date[i]), spot[i],
                    fx_vol_surface.get_dom_discount_curve(),
                    fx_vol_surface.get_for_discount_curve(),
                    model)[delta_output.replace('-', '_')]
Пример #15
0
def test_FinEquityDigitalOption():

    underlyingType = FinDigitalOptionTypes.CASH_OR_NOTHING

    valueDate = FinDate(2015, 1, 1)
    expiryDate = FinDate(2016, 1, 1)
    stockPrice = 100.0
    volatility = 0.30
    interestRate = 0.05
    dividendYield = 0.01
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

    model = FinModelBlackScholes(volatility)
    import time

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

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

    for numPaths in numPathsList:

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

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

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

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

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

    for stockPrice in stockPrices:
        callOption = FinEquityDigitalOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL,
                                            underlyingType)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model)
        delta = callOption.delta(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model)
        vega = callOption.vega(valueDate, stockPrice, discountCurve,
                               dividendCurve, model)
        theta = callOption.theta(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model)
        callOptionValues.append(value)
        callOptionDeltas.append(delta)
        callOptionVegas.append(vega)
        callOptionThetas.append(theta)

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

    for stockPrice in stockPrices:
        putOption = FinEquityDigitalOption(expiryDate, 100.0,
                                           FinOptionTypes.EUROPEAN_PUT,
                                           underlyingType)
        value = putOption.value(valueDate, stockPrice, discountCurve,
                                dividendCurve, model)
        delta = putOption.delta(valueDate, stockPrice, discountCurve,
                                dividendCurve, model)
        vega = putOption.vega(valueDate, stockPrice, discountCurve,
                              dividendCurve, model)
        theta = putOption.theta(valueDate, stockPrice, discountCurve,
                                dividendCurve, model)
        putOptionValues.append(value)
        putOptionDeltas.append(delta)
        putOptionVegas.append(vega)
        putOptionThetas.append(theta)
Пример #16
0
def test_FinFXAmericanOption():

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

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

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

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

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

    model = 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(expiryDate,
                                        strikeFXRate,
                                        currencyPair,
                                        FinOptionTypes.EUROPEAN_CALL,
                                        1000000,
                                        "USD")

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

        diff = (valueAmerican - valueEuropean)
        testCases.print(spotFXRate, valueEuropean, valueAmerican, diff)
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 = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

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

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

    for numPaths in numPathsList:

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

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

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

    testCases.header("NUMPATHS", "CALL_VALUE_BS", "CALL_VALUE_MC",
                     "CALL_VALUE_MC_SOBOL", "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, valueMC1, valueMC2, duration)

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

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

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

    for stockPrice in stockPrices:

        putOption = FinEquityVanillaOption(expiryDate, 100.0,
                                           FinOptionTypes.EUROPEAN_PUT)

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

        start = time.time()

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

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

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

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

    stockPrices = range(80, 120, 10)

    testCases.header("STOCK PRICE", "CALL_VALUE_BS", "CALL_DELTA_BS",
                     "CALL_VEGA_BS", "CALL_THETA_BS", "CALL_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)
        rho = callOption.rho(valueDate, stockPrice, discountCurve,
                             dividendYield, model)
        testCases.print(stockPrice, 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 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)
        rho = putOption.rho(valueDate, stockPrice, discountCurve,
                            dividendYield, model)
        testCases.print(stockPrice, value, delta, vega, theta, rho)

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

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

    stockPrices = range(60, 150, 10)

    for stockPrice in stockPrices:
        callOption = FinEquityVanillaOption(expiryDate, 100.0,
                                            FinOptionTypes.EUROPEAN_CALL)
        value = callOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        impliedVol = callOption.impliedVolatility(valueDate, stockPrice,
                                                  discountCurve, dividendYield,
                                                  value)
        testCases.print(stockPrice, value, volatility, impliedVol)
Пример #18
0
def test_FinEquityCompoundOption():

    valueDate = FinDate(2015, 1, 1)
    expiryDate1 = FinDate(2017, 1, 1)
    expiryDate2 = FinDate(2018, 1, 1)
    k1 = 5.0
    k2 = 95.0
    stockPrice = 85.0
    volatility = 0.15
    interestRate = 0.035
    dividendYield = 0.01

    model = FinModelBlackScholes(volatility)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    optionType1 = FinOptionTypes.EUROPEAN_CALL
    optionType2 = FinOptionTypes.EUROPEAN_PUT

    numStepsList = [
        200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000
    ]

    cmpdOption = FinEquityCompoundOption(expiryDate1, optionType1, k1,
                                         expiryDate2, optionType2, k2)
    stockPrice = 85.0

    testCases.header("TYPE1", "TYPE2", "K1", "K2", "S", "Exact", "TreeSteps",
                     "TreeValue")
    for numSteps in numStepsList:

        value = cmpdOption.value(valueDate, stockPrice, discountCurve,
                                 dividendYield, model)
        values = cmpdOption._valueTree(valueDate, stockPrice, discountCurve,
                                       dividendYield, model, numSteps)
        testCases.print(optionType1, optionType2, k1, k2, stockPrice, value,
                        numSteps, 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(expiryDate1, optionType1, k1,
                                                 expiryDate2, optionType2, k2)
            stockPrices = range(70, 100, 5)

            for stockPrice in stockPrices:
                value = cmpdOption.value(valueDate, stockPrice, discountCurve,
                                         dividendYield, model)
                delta = cmpdOption.delta(valueDate, stockPrice, discountCurve,
                                         dividendYield, model)
                vega = cmpdOption.vega(valueDate, stockPrice, discountCurve,
                                       dividendYield, model)
                theta = cmpdOption.theta(valueDate, stockPrice, discountCurve,
                                         dividendYield, model)

                values = cmpdOption._valueTree(valueDate, stockPrice,
                                               discountCurve, dividendYield,
                                               model)

                diff = value - values[0]

                testCases.print(optionType1, optionType2, k1, k2, stockPrice,
                                value, numSteps, values[0], diff, delta, vega,
                                theta)
def test_FinBinomialTree():

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

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

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

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

    strikePrice = 50.0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        end = time.time()
        duration = end - start
        testCases.print(numSteps, results, duration)
Пример #20
0
def test_FinFXVanillaOptionHullExample():

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

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

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

    for numPaths in numPathsList:

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

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

        start = time.time()

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

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

    for spotFXRate in spotFXRates:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        testCases.print(spotFXRate, value, volatility, impliedVol)
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."
Пример #22
0
def test_FinEquityOneTouchOption():
    # Examples Haug Page 180 Table 4-22
    # Agreement not exact at t is not exactly 0.50

    valueDate = FinDate(1, 1, 2016)
    expiryDate = FinDate(2, 7, 2016)
    interestRate = 0.10
    volatility = 0.20
    barrierLevel = 100.0  # H
    model = FinModelBlackScholes(volatility)
    dividendYield = 0.03
    numPaths = 10000
    numStepsPerYear = 252

    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, dividendYield)

    stockPrice = 105.0
    paymentSize = 15.0

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

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

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

    for downType in downTypes:

        option = FinEquityOneTouchOption(expiryDate, downType, barrierLevel,
                                         paymentSize)

        v = option.value(valueDate, stockPrice, discountCurve, dividendCurve,
                         model)

        v_mc = option.valueMC(valueDate, stockPrice, discountCurve,
                              dividendCurve, model, numStepsPerYear, numPaths)

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

    stockPrice = 95.0
    paymentSize = 15.0

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

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

    for upType in upTypes:

        option = FinEquityOneTouchOption(expiryDate, upType, barrierLevel,
                                         paymentSize)

        v = option.value(valueDate, stockPrice, discountCurve, dividendCurve,
                         model)

        v_mc = option.valueMC(valueDate, stockPrice, discountCurve,
                              dividendCurve, model, numStepsPerYear, numPaths)

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

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

    stockPrice = 105.0

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

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

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

        option = FinEquityOneTouchOption(expiryDate, downType, barrierLevel)

        v = option.value(valueDate, stockPrice, discountCurve, dividendCurve,
                         model)

        v_mc = option.valueMC(valueDate, stockPrice, discountCurve,
                              dividendCurve, model, numStepsPerYear, numPaths)

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

    stockPrice = 95.0

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

    for upType in upTypes:

        option = FinEquityOneTouchOption(expiryDate, upType, barrierLevel)

        v = option.value(valueDate, stockPrice, discountCurve, dividendCurve,
                         model)

        v_mc = option.valueMC(valueDate, stockPrice, discountCurve,
                              dividendCurve, model, numStepsPerYear, numPaths)

        testCases.print("%60s " % upType, "%9.5f" % v, "%9.5f" % v_mc)
Пример #23
0
def test_FinFXBarrierOption():

    valueDate = FinDate(1, 1, 2015)
    expiryDate = FinDate(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 = FinDiscountCurveFlat(valueDate, domInterestRate)
    forDiscountCurve = FinDiscountCurveFlat(valueDate, 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(expiryDate, K, currencyPair,
                                        optionType, B, numObservationsPerYear,
                                        notional, notionalCurrency)

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

            start = time.time()
            modelParams = (spotFXRate, drift, volatility, scheme)
            valueMC = option.valueMC(valueDate, 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(expiryDate, K, currencyPair,
                                        optionType, B, numObservationsPerYear,
                                        notional, notionalCurrency)

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

            start = time.time()
            modelParams = (spotFXRate, drift, volatility, scheme)
            valueMC = option.valueMC(valueDate, 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(expiryDate, 100.0, currencyPair,
                                               optionType, B,
                                               numObservationsPerYear,
                                               notional, notionalCurrency)

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

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

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

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

            testCases.print(optionType, K, B, spotFXRate, value, delta, vega,
                            theta)
Пример #24
0
def testMCTimings():

    valueDate = FinDate(2014, 1, 1)
    startAveragingDate = FinDate(2014, 6, 1)
    expiryDate = FinDate(2015, 1, 1)
    stockPrice = 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)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

    asianOption = FinEquityAsianOption(startAveragingDate, expiryDate, 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 = []

    numPathsList = [5000]

    for numPaths in numPathsList:

        accruedAverage = stockPrice * 1.1

        start = time.time()
        valueMC = asianOption.valueMC(valueDate, stockPrice, discountCurve,
                                      dividendYield, model, numPaths, seed,
                                      accruedAverage)

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

        start = time.time()
        valueMC_fast = asianOption._valueMC_fast(valueDate, stockPrice,
                                                 discountCurve, dividendYield,
                                                 model, numPaths, seed,
                                                 accruedAverage)

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

        start = time.time()
        valueMC_fast_CV = asianOption.valueMC(valueDate, stockPrice,
                                              discountCurve, dividendYield,
                                              model, numPaths, 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(numPaths, valueMC, t_MC, valueMC_fast, t_MC_fast,
                        valueMC_fast_CV, t_MC_fast_CV)
Пример #25
0
def testConvergence():

    valueDate = FinDate(2014, 1, 1)
    startAveragingDate = FinDate(2014, 6, 1)
    expiryDate = FinDate(2015, 1, 1)
    stockPrice = 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)
    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

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

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

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

    numPathsList = [5000]

    for numPaths in numPathsList:

        accruedAverage = stockPrice * 1.1

        valueMC_fast = asianOption._valueMC_fast(valueDate, stockPrice,
                                                 discountCurve, dividendYield,
                                                 model, numPaths, seed,
                                                 accruedAverage)

        valueMC_CV = asianOption.valueMC(valueDate, stockPrice, discountCurve,
                                         dividendYield, model, numPaths, seed,
                                         accruedAverage)

        valueGeometric = asianOption.value(
            valueDate, stockPrice, discountCurve, dividendYield, model,
            FinAsianOptionValuationMethods.GEOMETRIC, accruedAverage)

        valueTurnbullWakeman = asianOption.value(
            valueDate, stockPrice, discountCurve, dividendYield, model,
            FinAsianOptionValuationMethods.TURNBULL_WAKEMAN, accruedAverage)

        valueCurran = asianOption.value(valueDate, stockPrice, discountCurve,
                                        dividendYield, 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(numPaths, valueGeometric, valueTurnbullWakeman,
                        valueCurran, valueMC_fast, valueMC_CV)
def test_FinEquityBarrierOption():

    valueDate = FinDate(2015, 1, 1)
    expiryDate = FinDate(2016, 1, 1)
    stockPrice = 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

    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)
    dividendCurve = FinDiscountCurveFlat(valueDate, 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 stockPrice in range(80, 120, 10):

            B = 110.0
            K = 100.0

            option = FinEquityBarrierOption(expiryDate, K, optionType, B,
                                            numObservationsPerYear)
            value = option.value(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model)
            start = time.time()
            modelParams = (stockPrice, drift, volatility, scheme)
            valueMC = option.valueMC(valueDate, stockPrice, discountCurve,
                                     dividendCurve, processType, modelParams)

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

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

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

            B = 100.0
            K = 110.0

            option = FinEquityBarrierOption(expiryDate, K, optionType, B,
                                            numObservationsPerYear)
            value = option.value(valueDate, stockPrice, discountCurve,
                                 dividendCurve, model)
            start = time.time()
            modelParams = (stockPrice, drift, volatility, scheme)
            valueMC = option.valueMC(valueDate, stockPrice, discountCurve,
                                     dividendCurve, processType, modelParams)
            end = time.time()
            timeElapsed = round(end - start, 3)
            diff = valueMC - value

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

        end = time.time()

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

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

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

    for optionType in FinEquityBarrierTypes:

        for stockPrice in stockPrices:

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

            value = barrierOption.value(valueDate, stockPrice, discountCurve,
                                        dividendCurve, model)
            delta = barrierOption.delta(valueDate, stockPrice, discountCurve,
                                        dividendCurve, model)
            vega = barrierOption.vega(valueDate, stockPrice, discountCurve,
                                      dividendCurve, model)
            theta = barrierOption.theta(valueDate, stockPrice, discountCurve,
                                        dividendCurve, model)

            testCases.print(optionType, K, B, stockPrice, value, delta, vega,
                            theta)
Пример #27
0
def testFinEquityAmericanOption():

    valueDate = FinDate(2016, 1, 1)
    expiryDate = FinDate(2017, 1, 1)
    stockPrice = 50.0
    interestRate = 0.06
    dividendYield = 0.04
    volatility = 0.40
    strikePrice = 50.0

    discountCurve = FinDiscountCurveFlat(valueDate, interestRate)

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

    putOption = FinEquityAmericanOption(expiryDate, strikePrice,
                                        FinOptionTypes.EUROPEAN_PUT)

    model = FinModelBlackScholes(volatility,
                                 FinModelBlackScholesTypes.CRR_TREE,
                                 {'numStepsPerYear': 100})

    value = putOption.value(valueDate, stockPrice, discountCurve,
                            dividendYield, model)
    delta = putOption.delta(valueDate, stockPrice, discountCurve,
                            dividendYield, model)
    gamma = putOption.gamma(valueDate, stockPrice, discountCurve,
                            dividendYield, model)
    theta = putOption.theta(valueDate, stockPrice, discountCurve,
                            dividendYield, model)

    testCases.header("OPTION_TYPE", "VALUE", "DELTA", "GAMMA", "THETA")
    testCases.print("EUROPEAN_PUT_BS", value, delta, gamma, theta)

    option = FinEquityAmericanOption(expiryDate, strikePrice,
                                     FinOptionTypes.EUROPEAN_PUT)

    testCases.header("OPTION_TYPE", "NUMSTEPS", "VALUE DELTA GAMMA THETA",
                     "TIME")

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

    for numSteps in numStepsList:

        model = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     {'numStepsPerYear': numSteps})

        start = time.time()
        results = option.value(valueDate, stockPrice, discountCurve,
                               dividendYield, model)
        end = time.time()
        duration = end - start
        testCases.print("EUROPEAN_PUT_TREE", numSteps, results, duration)

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

    option = FinEquityAmericanOption(expiryDate, strikePrice,
                                     FinOptionTypes.AMERICAN_PUT)

    testCases.header("OPTION_TYPE", "NUMSTEPS", "VALUE DELTA GAMMA THETA",
                     "TIME")

    for numSteps in numStepsList:

        model = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     {'numStepsPerYear': numSteps})

        start = time.time()
        results = option.value(valueDate, stockPrice, discountCurve,
                               dividendYield, model)
        end = time.time()
        duration = end - start
        testCases.print("AMERICAN_PUT", numSteps, results, duration)

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

    callOption = FinEquityAmericanOption(expiryDate, strikePrice,
                                         FinOptionTypes.EUROPEAN_CALL)
    value = callOption.value(valueDate, stockPrice, discountCurve,
                             dividendYield, model)
    delta = callOption.delta(valueDate, stockPrice, discountCurve,
                             dividendYield, model)
    gamma = callOption.gamma(valueDate, stockPrice, discountCurve,
                             dividendYield, model)
    theta = callOption.theta(valueDate, stockPrice, discountCurve,
                             dividendYield, model)

    testCases.header("OPTION_TYPE", "VALUE", "DELTA", "GAMMA", "THETA")
    testCases.print("EUROPEAN_CALL_BS", value, delta, gamma, theta)

    option = FinEquityAmericanOption(expiryDate, strikePrice,
                                     FinOptionTypes.EUROPEAN_CALL)

    testCases.header("OPTION_TYPE", "NUMSTEPS", "VALUE DELTA GAMMA THETA",
                     "TIME")

    for numSteps in numStepsList:

        model = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     {'numStepsPerYear': numSteps})
        start = time.time()
        results = option.value(valueDate, stockPrice, discountCurve,
                               dividendYield, model)
        end = time.time()
        duration = end - start
        testCases.print("EUROPEAN_CALL_TREE", numSteps, results, duration)

    testCases.banner(
        "================== AMERICAN CALL =======================")
    testCases.header("OPTION_TYPE", "NUMSTEPS", "VALUE DELTA GAMMA THETA",
                     "TIME")

    option = FinEquityAmericanOption(expiryDate, strikePrice,
                                     FinOptionTypes.AMERICAN_CALL)

    for numSteps in numStepsList:

        model = FinModelBlackScholes(volatility,
                                     FinModelBlackScholesTypes.CRR_TREE,
                                     {'numStepsPerYear': numSteps})

        start = time.time()

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

        end = time.time()
        duration = end - start
        testCases.print("AMERICAN_CALL", numSteps, results, duration)
Пример #28
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

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

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

    spotFXRate = 1.20
    strikeFXRate = 1.250
    volatility = 0.10

    notional = 1000000.0

    domDiscountCurve = FinDiscountCurveFlat(valueDate, ccy2CCRate)
    forDiscountCurve = FinDiscountCurveFlat(valueDate, 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(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_CALL, notional,
                                        "USD")

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

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

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

        diff = (valueAmerican - valueEuropean)

        testCases.print("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(expiryDate, strikeFXRate, "EURUSD",
                                        FinOptionTypes.EUROPEAN_PUT, 1000000,
                                        "USD")

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

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

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

        diff = (valueAmerican - valueEuropean)
        testCases.print("PUT:", "%9.6f" % spotFXRate, "%9.7f" % valueEuropean,
                        "%9.7f" % valueAmerican, "%9.7f" % diff)
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")