Beispiel #1
0
def test_EquityChooserOptionMatlab():
    """https://fr.mathworks.com/help/fininst/chooserbybls.html """

    valuation_date = Date(1, 6, 2007)
    chooseDate = Date(31, 8, 2007)
    call_expiry_date = Date(2, 12, 2007)
    put_expiry_date = Date(2, 12, 2007)
    call_strike = 60.0
    put_strike = 60.0
    stock_price = 50.0
    volatility = 0.20
    interest_rate = 0.10
    dividend_yield = 0.05

    model = BlackScholes(volatility)

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

    chooserOption = EquityChooserOption(chooseDate, call_expiry_date,
                                        put_expiry_date, call_strike,
                                        put_strike)

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

    v_mc = chooserOption.value_mc(valuation_date, stock_price, discount_curve,
                                  dividend_curve, model, 20000)

    v_matlab = 8.9308
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "MATLAB", v_matlab, "MC", v_mc)
Beispiel #2
0
def test_EquityChooserOptionHaug():
    """ Following example in Haug Page 130 """

    valuation_date = Date(1, 1, 2015)
    choose_date = Date(2, 4, 2015)
    call_expiry_date = Date(1, 7, 2015)
    put_expiry_date = Date(2, 8, 2015)
    call_strike = 55.0
    put_strike = 48.0
    stock_price = 50.0
    volatility = 0.35
    interest_rate = 0.10
    dividend_yield = 0.05

    model = BlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    chooserOption = EquityChooserOption(choose_date, call_expiry_date,
                                        put_expiry_date, call_strike,
                                        put_strike)

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

    v_mc = chooserOption.value_mc(valuation_date, stock_price, discount_curve,
                                  dividend_curve, model, 20000)

    v_haug = 6.0508
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "HAUG", v_haug, "MC", v_mc)
Beispiel #3
0
def test_EquityChooserOptionHaug():
    """ Following example in Haug Page 130 """

    valuation_date = Date(1, 1, 2015)
    choose_date = Date(2, 4, 2015)
    call_expiry_date = Date(1, 7, 2015)
    put_expiry_date = Date(2, 8, 2015)
    call_strike = 55.0
    put_strike = 48.0
    stock_price = 50.0
    volatility = 0.35
    interest_rate = 0.10
    dividend_yield = 0.05

    model = BlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    chooserOption = EquityChooserOption(choose_date, call_expiry_date,
                                        put_expiry_date, call_strike,
                                        put_strike)

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

    v_mc = chooserOption.value_mc(valuation_date, stock_price, discount_curve,
                                  dividend_curve, model, 20000)

    v_haug = 6.0508

    assert round(v, 4) == 6.0342
    assert round(v_haug, 4) == 6.0508
    assert round(v_mc, 4) == 6.0587
Beispiel #4
0
def test_EquityChooserOptionDerivicom():
    """http://derivicom.com/support/finoptionsxl/index.html?complex_chooser.htm """

    valuation_date = Date(1, 1, 2007)
    chooseDate = Date(1, 2, 2007)
    call_expiry_date = Date(1, 4, 2007)
    put_expiry_date = Date(1, 5, 2007)
    call_strike = 40.0
    put_strike = 35.0
    stock_price = 38.0
    volatility = 0.20
    interest_rate = 0.08
    dividend_yield = 0.0625

    model = BlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    chooserOption = EquityChooserOption(chooseDate, call_expiry_date,
                                        put_expiry_date, call_strike,
                                        put_strike)

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

    v_mc = chooserOption.value_mc(valuation_date, stock_price, discount_curve,
                                  dividend_curve, model, 20000)

    v_derivicom = 1.0989

    assert round(v, 4) == 1.1052
    assert round(v_derivicom, 4) == 1.0989
    assert round(v_mc, 4) == 1.1095
Beispiel #5
0
def test_example():

    expiry_date = Date(1, 1, 2021)
    strike_price = 105.0
    option_typeCall = FinOptionTypes.EUROPEAN_CALL
    option_typePut = FinOptionTypes.EUROPEAN_PUT
    lookbackCall = EquityFixedLookbackOption(expiry_date, option_typeCall,
                                             strike_price)
    lookbackPut = EquityFixedLookbackOption(expiry_date, option_typePut,
                                            strike_price)

    valuation_date = Date(1, 1, 2020)
    interest_rate = 0.10
    stock_price = 100.0
    dividend_yield = 0.0
    stock_min_max = 100.0

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

    volatilities = [0.30]

    testCases.header("VALUE")
    for vol in volatilities:
        v = lookbackCall.value(valuation_date, stock_price, discount_curve,
                               dividend_curve, vol, stock_min_max)
        testCases.print(v)
Beispiel #6
0
def test_EquityChooserOptionDerivicom():
    """http://derivicom.com/support/finoptionsxl/index.html?complex_chooser.htm """

    valuation_date = Date(1, 1, 2007)
    chooseDate = Date(1, 2, 2007)
    call_expiry_date = Date(1, 4, 2007)
    put_expiry_date = Date(1, 5, 2007)
    call_strike = 40.0
    put_strike = 35.0
    stock_price = 38.0
    volatility = 0.20
    interest_rate = 0.08
    dividend_yield = 0.0625

    model = BlackScholes(volatility)
    discount_curve = DiscountCurveFlat(valuation_date, interest_rate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield)

    chooserOption = EquityChooserOption(chooseDate, call_expiry_date,
                                        put_expiry_date, call_strike,
                                        put_strike)

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

    v_mc = chooserOption.value_mc(valuation_date, stock_price, discount_curve,
                                  dividend_curve, model, 20000)

    v_derivicom = 1.0989
    testCases.header("", "", "", "", "", "")
    testCases.print("FINANCEPY", v, "DERIVICOM", v_derivicom, "MC", v_mc)
Beispiel #7
0
def test_value_mc():
    #   Example from Hull 4th edition page 284
    valuation_date = Date(1, 1, 2015)
    expiry_date = valuation_date.add_months(4)
    spot_fx_rate = 1.60
    volatility = 0.1411
    dom_interest_rate = 0.08
    forInterestRate = 0.11
    model = BlackScholes(volatility)
    dom_discount_curve = DiscountCurveFlat(valuation_date, dom_interest_rate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forInterestRate)
    num_paths = 100000

    strike_fx_rate = 1.6

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

    value_mc = call_option.value_mc(valuation_date, spot_fx_rate,
                                    dom_discount_curve, for_discount_curve,
                                    model, num_paths)

    assert round(value_mc, 4) == 0.0429

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

    value_mc = put_option.value_mc(valuation_date, spot_fx_rate,
                                   dom_discount_curve, for_discount_curve,
                                   model, num_paths)

    assert round(value_mc, 4) == 0.0582
Beispiel #8
0
def test_vega_theta():
    #   Example from Hull 4th edition page 284
    valuation_date = Date(1, 1, 2015)
    expiry_date = valuation_date.add_months(4)
    spot_fx_rate = 1.60
    volatility = 0.1411
    dom_interest_rate = 0.08
    forInterestRate = 0.11
    model = BlackScholes(volatility)
    dom_discount_curve = DiscountCurveFlat(valuation_date, dom_interest_rate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forInterestRate)

    strike_fx_rate = 1.6

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

    vega = call_option.vega(valuation_date, spot_fx_rate, dom_discount_curve,
                            for_discount_curve, model)

    assert round(vega, 4) == 0.3518

    theta = call_option.theta(valuation_date, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    assert round(theta, 4) == -0.0504
Beispiel #9
0
def test_EquityForward():

    valuation_date = Date(13, 2, 2018)
    expiry_date = valuation_date.add_months(12)

    stock_price = 130.0
    forward_price = 125.0  # Locked
    discountRate = 0.05
    dividendRate = 0.02

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

    expiry_date = valuation_date.add_months(12)
    notional = 100.0

    discount_curve = DiscountCurveFlat(valuation_date, discountRate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividendRate)

    equityForward = EquityForward(expiry_date, forward_price, notional,
                                  FinLongShort.LONG)

    testCases.header("SPOT FX", "FX FWD", "VALUE_BS")

    fwdPrice = equityForward.forward(valuation_date, stock_price,
                                     discount_curve, dividend_curve)

    fwdValue = equityForward.value(valuation_date, stock_price, discount_curve,
                                   dividend_curve)

    #    print(stock_price, fwdPrice, fwdValue)
    testCases.print(stock_price, fwdPrice, fwdValue)
Beispiel #10
0
def test_FinFXMktVolSurface4(capsys):
    # USDJPY Example from Paper by Uwe Wystup using Tables 4

    valuation_date = Date(20, 1, 2009)

    forName = "USD"
    domName = "JPY"
    forCCRate = 0.003525  # USD
    domCCRate = 0.0042875  # JPY

    dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

    currency_pair = forName + domName
    spot_fx_rate = 90.68

    tenors = ['1M']
    atm_vols = [21.00]
    marketStrangle25DeltaVols = [0.184]
    riskReversal25DeltaVols = [-5.30]

    notional_currency = forName

    atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
    deltaMethod = FinFXDeltaMethod.SPOT_DELTA_PREM_ADJ

    fxMarket = FXVolSurface(valuation_date, spot_fx_rate, currency_pair,
                            notional_currency, dom_discount_curve,
                            for_discount_curve, tenors, atm_vols,
                            marketStrangle25DeltaVols, riskReversal25DeltaVols,
                            atmMethod, deltaMethod)

    fxMarket.check_calibration(verboseCalibration)
    captured = capsys.readouterr()
    assert captured.out == ""
def test_FinFXMktVolSurface5(verboseCalibration):

    ###########################################################################
    # Here I remove the 10D Vols
    ###########################################################################

    if 1 == 1:

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

        valuation_date = Date(10, 4, 2020)

        forName = "EUR"
        domName = "USD"
        forCCRate = 0.03460  # EUR
        domCCRate = 0.02940  # USD

        dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
        for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

        currency_pair = forName + domName
        spot_fx_rate = 1.3465

        tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
        atm_vols = [21.00, 21.00, 20.750, 19.400, 18.250, 17.677]
        marketStrangle25DeltaVols = [0.65, 0.75, 0.85, 0.90, 0.95, 0.85]
        riskReversal25DeltaVols = [-0.20, -0.25, -0.30, -0.50, -0.60, -0.562]
        marketStrangle10DeltaVols = [2.433, 2.83, 3.228, 3.485, 3.806, 3.208]
        riskReversal10DeltaVols = [-1.258, -
                                   1.297, -1.332, -1.408, -1.359, -1.208]

        marketStrangle10DeltaVols = None
        riskReversal10DeltaVols = None

        notional_currency = forName

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

        fxMarketPlus = FXVolSurfacePlus(valuation_date,
                                        spot_fx_rate,
                                        currency_pair,
                                        notional_currency,
                                        dom_discount_curve,
                                        for_discount_curve,
                                        tenors,
                                        atm_vols,
                                        marketStrangle25DeltaVols,
                                        riskReversal25DeltaVols,
                                        marketStrangle10DeltaVols,
                                        riskReversal10DeltaVols,
                                        alpha,
                                        atmMethod,
                                        deltaMethod,
                                        vol_functionType)

        fxMarketPlus.check_calibration(False)
Beispiel #12
0
def test_equity_vol_surface():
    valuation_date = Date(11, 1, 2021)

    stock_price = 3800.0  # Check

    expiry_dates = [
        Date(11, 2, 2021),
        Date(11, 3, 2021),
        Date(11, 4, 2021),
        Date(11, 7, 2021),
        Date(11, 10, 2021),
        Date(11, 1, 2022),
        Date(11, 1, 2023)
    ]

    strikes = np.array([3037, 3418, 3608, 3703, 3798, 3893, 3988, 4178, 4557])

    volSurface = [
        [42.94, 31.30, 25.88, 22.94, 19.72, 16.90, 15.31, 17.54, 25.67],
        [37.01, 28.25, 24.19, 21.93, 19.57, 17.45, 15.89, 15.34, 21.15],
        [34.68, 27.38, 23.82, 21.85, 19.83, 17.98, 16.52, 15.31, 18.94],
        [31.41, 26.25, 23.51, 22.05, 20.61, 19.25, 18.03, 16.01, 15.90],
        [29.91, 25.58, 23.21, 22.01, 20.83, 19.70, 18.62, 16.63, 14.94],
        [29.26, 25.24, 23.03, 21.91, 20.81, 19.73, 18.69, 16.76, 14.63],
        [27.59, 24.33, 22.72, 21.93, 21.17, 20.43, 19.71, 18.36, 16.26]
    ]

    volSurface = np.array(volSurface)
    volSurface = volSurface / 100.0

    r = 0.020  # USD
    discount_curve = DiscountCurveFlat(valuation_date, r)

    q = 0.010  # USD
    dividend_curve = DiscountCurveFlat(valuation_date, q)

    vol_functionType = VolFunctionTypes.SVI

    equitySurface = EquityVolSurface(valuation_date, stock_price,
                                     discount_curve, dividend_curve,
                                     expiry_dates, strikes, volSurface,
                                     vol_functionType)

    expiry_date = expiry_dates[0]
    delta = 0.10
    vol = equitySurface.volatility_from_delta_date(delta, expiry_date)
    assert round(vol[0], 4) == 0.1544
    assert round(vol[1], 4) == 4032.9156

    expiry_date = expiry_dates[1]
    delta = 0.20
    vol = equitySurface.volatility_from_delta_date(delta, expiry_date)
    assert round(vol[0], 4) == 0.1555
    assert round(vol[1], 4) == 4019.3793

    expiry_date = expiry_dates[6]
    delta = 0.90
    vol = equitySurface.volatility_from_delta_date(delta, expiry_date)
    assert round(vol[0], 4) == 0.3530
    assert round(vol[1], 4) == 2190.7766
Beispiel #13
0
def test_equity_forward():

    valuation_date = Date(13, 2, 2018)
    expiry_date = valuation_date.add_months(12)

    stock_price = 130.0
    forward_price = 125.0  # Locked
    discountRate = 0.05
    dividendRate = 0.02

    expiry_date = valuation_date.add_months(12)
    notional = 100.0

    discount_curve = DiscountCurveFlat(valuation_date, discountRate)
    dividend_curve = DiscountCurveFlat(valuation_date, dividendRate)

    equityForward = EquityForward(expiry_date, forward_price, notional,
                                  FinLongShort.LONG)

    fwdPrice = equityForward.forward(valuation_date, stock_price,
                                     discount_curve, dividend_curve)

    fwdValue = equityForward.value(valuation_date, stock_price, discount_curve,
                                   dividend_curve)

    assert round(fwdPrice, 4) == 133.9591
    assert round(fwdValue, 4) == 852.2149
Beispiel #14
0
def test_swapFloatLeg():

    effective_date = Date(1, 9, 2021)

    fixedleg_2 = SwapFixedLeg(effective_date,
                              end_date='3y',
                              leg_type=SwapTypes.PAY,
                              freq_type=FrequencyTypes.SEMI_ANNUAL,
                              day_count_type=DayCountTypes.THIRTY_E_360,
                              calendar_type=CalendarTypes.UNITED_STATES,
                              coupon=0)

    floatleg_2 = SwapFloatLeg(effective_date,
                              end_date='3y',
                              leg_type=SwapTypes.PAY,
                              freq_type=FrequencyTypes.SEMI_ANNUAL,
                              day_count_type=DayCountTypes.THIRTY_E_360,
                              calendar_type=CalendarTypes.UNITED_STATES,
                              spread=0)

    fixedleg_2.generate_payments()
    floatleg_2.generate_payment_dates()

    discount_curve = DiscountCurveFlat(
        effective_date, 0.05, day_count_type=DayCountTypes.THIRTY_E_360)
    index_curve = DiscountCurveFlat(effective_date,
                                    0.05,
                                    day_count_type=DayCountTypes.ACT_ACT_ISDA)

    floatleg_2.value(effective_date, discount_curve, index_curve)
Beispiel #15
0
def test_FinFXDigitalOption():

    # Not exactly T=1.0 but close so don't exact exact agreement
    # (in fact I do not get exact agreement even if I do set T=1.0)
    valuation_date = Date(13, 2, 2018)
    expiry_date = Date(13, 2, 2019)

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

    currency_pair = ccy1 + ccy2  # Always ccy1ccy2
    spot_fx_rate = 1.20
    strike_fx_rate = 1.250
    volatility = 0.10

    notional = 1.0

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

    model = BlackScholes(volatility)

    digital_option = FXDigitalOption(expiry_date, strike_fx_rate,
                                     currency_pair, OptionTypes.DIGITAL_CALL,
                                     notional, "USD")

    spot_fx_rate = np.linspace(0.01, 2.0, 10)

    value = digital_option.value(valuation_date, spot_fx_rate,
                                 dom_discount_curve, for_discount_curve, model)
Beispiel #16
0
def test_FinFXMktVolSurface1(verboseCalibration):

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

    if 1 == 1:

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

        valuation_date = Date(10, 4, 2020)

        forName = "EUR"
        domName = "USD"
        forCCRate = 0.03460  # EUR
        domCCRate = 0.02940  # USD

        dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
        for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

        currency_pair = forName + domName
        spot_fx_rate = 1.3465

        tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
        atm_vols = [21.00, 21.00, 20.750, 19.400, 18.250, 17.677]
        marketStrangle25DeltaVols = [0.65, 0.75, 0.85, 0.90, 0.95, 0.85]
        riskReversal25DeltaVols = [-0.20, -0.25, -0.30, -0.50, -0.60, -0.562]
        marketStrangle10DeltaVols = [2.433, 2.83, 3.228, 3.485, 3.806, 3.208]
        riskReversal10DeltaVols = [
            -1.258, -1.297, -1.332, -1.408, -1.359, -1.208
        ]

        notional_currency = forName

        atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
        deltaMethod = FinFXDeltaMethod.SPOT_DELTA
        vol_functionType = VolFunctionTypes.CLARK5
        alpha = 0.5  # FIT WINGS AT 10D if ALPHA = 1.0

        fxMarketPlus = FXVolSurfacePlus(
            valuation_date, spot_fx_rate, currency_pair, notional_currency,
            dom_discount_curve, for_discount_curve, tenors, atm_vols,
            marketStrangle25DeltaVols, riskReversal25DeltaVols,
            marketStrangle10DeltaVols, riskReversal10DeltaVols, alpha,
            atmMethod, deltaMethod, vol_functionType)

        fxMarketPlus.check_calibration(False)

        if 1 == 0:  # PLOT_GRAPHS:

            fxMarketPlus.plot_vol_curves()

            plt.figure()

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

            for i in range(0, len(dbns)):
                plt.plot(dbns[i]._x, dbns[i]._densitydx)
                plt.title(vol_functionType)
                print("SUM:", dbns[i].sum())
Beispiel #17
0
def testBlackScholes():

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

    strike_price = 130.0
    stock_price = 127.62
    volatility = 0.20
    interest_rate = 0.001
    dividend_yield = 0.0163

    option_type = OptionTypes.AMERICAN_CALL
    euOptionType = OptionTypes.EUROPEAN_CALL

    amOption = EquityAmericanOption(expiry_date, strike_price, option_type)

    ameuOption = EquityAmericanOption(expiry_date, strike_price, euOptionType)

    euOption = EquityVanillaOption(expiry_date, strike_price, euOptionType)

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

    dividend_curve = DiscountCurveFlat(valuation_date, dividend_yield,
                                       FrequencyTypes.CONTINUOUS,
                                       DayCountTypes.ACT_365F)

    num_steps_per_year = 400

    modelTree = BlackScholes(volatility, BlackScholesTypes.CRR_TREE,
                             num_steps_per_year)

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

    modelApprox = BlackScholes(volatility, BlackScholesTypes.BARONE_ADESI)

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

    #    print(v)

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

    #    print(v)

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

    #    print(v)

    amTreeValue = []
    amBAWValue = []
    euTreeValue = []
    euAnalValue = []
    volatility = 0.20
Beispiel #18
0
def test_FinFXMktVolSurface2(verboseCalibration):

    # print("==============================================================")

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

    valuation_date = Date(10, 4, 2020)

    forName = "EUR"
    domName = "JPY"
    forCCRate = 0.0294  # EUR
    domCCRate = 0.0171  # USD

    dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

    currency_pair = forName + domName
    spot_fx_rate = 90.72

    tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
    atm_vols = [21.50, 20.50, 19.85, 18.00, 15.95, 14.009]
    marketStrangle25DeltaVols = [0.35, 0.325, 0.300, 0.225, 0.175, 0.100]
    riskReversal25DeltaVols = [-8.350, -8.650, -8.950, -9.250, -9.550, -9.500]
    marketStrangle10DeltaVols = [3.704, 4.047, 4.396, 4.932, 5.726, 5.709]
    riskReversal10DeltaVols = [
        -15.855, -16.467, -17.114, -17.882, -18.855, -18.217
    ]
    alpha = 0.50  # Equally fit 10 and 25 Delta

    notional_currency = forName

    atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL_PREM_ADJ
    deltaMethod = FinFXDeltaMethod.SPOT_DELTA_PREM_ADJ
    vol_functionType = VolFunctionTypes.CLARK5

    fxMarketPlus = FXVolSurfacePlus(
        valuation_date, spot_fx_rate, currency_pair, notional_currency,
        dom_discount_curve, for_discount_curve, tenors, atm_vols,
        marketStrangle25DeltaVols, riskReversal25DeltaVols,
        marketStrangle10DeltaVols, riskReversal10DeltaVols, alpha, atmMethod,
        deltaMethod, vol_functionType)

    #        fxMarketPlus.check_calibration(True)

    if PLOT_GRAPHS:
        fxMarketPlus.plot_vol_curves()

        plt.figure()

        dbns = fxMarketPlus.implied_dbns(30, 120, 1000)

        for i in range(0, len(dbns)):
            plt.plot(dbns[i]._x, dbns[i]._densitydx)
            plt.title(vol_functionType)
            print("SUM:", dbns[i].sum())
Beispiel #19
0
def test_FinFXVanillaOptionWystupExample2():
    # Example Bloomberg Pricing at
    # https://stackoverflow.com/questions/48778712/fx-vanilla-call-price-in-quantlib-doesnt-match-bloomberg

    valuation_date = Date(13, 2, 2018)
    expiry_date = Date(13, 2, 2019)

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

    currency_pair = ccy1 + ccy2  # Always ccy1ccy2
    spot_fx_rate = 0.9090
    strike_fx_rate = 0.9090
    volatility = 0.12

    notional = 1000000.0

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

    model = BlackScholes(volatility)

    # Two examples to show that changing the notional currency and notional
    # keeps the value unchanged
    notional = 1000000.0
    call_option = FXVanillaOption(expiry_date, strike_fx_rate, currency_pair,
                                  OptionTypes.EUROPEAN_PUT, notional, "EUR", 2)

    value = call_option.value(valuation_date, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    assert round(value['v'], 4) == 0.0436
    assert round(value['cash_dom'], 4) == 43612.8769
    assert round(value['cash_for'], 4) == 47978.9625
    assert round(value['pips_dom'], 4) == 0.0436
    assert round(value['pips_for'], 4) == 0.0528
    assert round(value['pct_dom'], 4) == 0.0480
    assert round(value['pct_for'], 4) == 0.0480
    assert round(value['not_dom'], 4) == 909000.0
    assert round(value['not_for'], 4) == 1000000.0
    assert value['ccy_dom'] == 'USD'
    assert value['ccy_for'] == 'EUR'

    delta = call_option.delta(valuation_date, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    assert round(delta['pips_spot_delta'], 4) == -0.4700
    assert round(delta['pips_fwd_delta'], 4) == -0.4890
    assert round(delta['pct_spot_delta_prem_adj'], 4) == -0.5180
    assert round(delta['pct_fwd_delta_prem_adj'], 4) == -0.5389
def test_FinFXVanillaOptionWystupExample1():

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

    # Not exactly T=1.0 but close so don't exact exact agreement
    # (in fact I do not get exact agreement even if I do set T=1.0)
    valuation_date = Date(13, 2, 2018)
    expiry_date = Date(13, 2, 2019)

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

    currency_pair = ccy1 + ccy2  # Always ccy1ccy2
    spot_fx_rate = 1.20
    strike_fx_rate = 1.250
    volatility = 0.10

    notional = 1000000.0

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

    model = BlackScholes(volatility)

    # Two examples to show that changing the notional currency and notional
    # keeps the value unchanged
    notional = 1000000.0
    call_option = FXVanillaOption(expiry_date, strike_fx_rate, currency_pair,
                                  OptionTypes.EUROPEAN_CALL, notional, "EUR",
                                  2)

    value = call_option.value(1.0, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    notional = 1250000.0
    call_option = FXVanillaOption(expiry_date, strike_fx_rate, currency_pair,
                                  OptionTypes.EUROPEAN_CALL, notional, "USD",
                                  2)

    value = call_option.value(valuation_date, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    delta = call_option.delta(valuation_date, spot_fx_rate, dom_discount_curve,
                              for_discount_curve, model)

    testCases.header("value", "delta")
    testCases.print(value, delta)
Beispiel #21
0
def test_BBGOneTouchOption():

    # 1YR ONETOUCH ON EURUSD

    valuation_date = Date(3, 12, 2021)
    expiry_date = Date(5, 12, 2022)
    barrier_level = 1.1865  # THIS IS NUMBER OF DOLLARS PER EURO

    spot_fx_rate = 1.1300  # EURUSD
    volatility = 0.06075

    model = BlackScholes(volatility)

    forRate = 0.00593  # EUR
    domRate = -0.00414  # USD

    num_paths = 50000
    num_steps_per_year = 252

    domCurve = DiscountCurveFlat(valuation_date, domRate)
    forCurve = DiscountCurveFlat(valuation_date, forRate)

    payment_size = 1000000  # EUR

    optionType = TouchOptionTypes.UP_AND_IN_CASH_AT_EXPIRY

    option = FXOneTouchOption(expiry_date, optionType, barrier_level,
                              payment_size)

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

    v_mc = option.value_mc(valuation_date, spot_fx_rate, domCurve, forCurve,
                           model, num_steps_per_year, num_paths)

    d = option.delta(valuation_date, spot_fx_rate, domCurve, forCurve, model)

    g = option.gamma(valuation_date, spot_fx_rate, domCurve, forCurve, model)

    v = option.vega(valuation_date, spot_fx_rate, domCurve, forCurve, model)

    # I SHOULD GET 49.4934% OR 494,934 in EUR
    # VEGA IS 68,777.26
    # GAMMA IS 916,285
    # DELTA IS -9560266

    print(optionType)
    print("Value:", v)
    print("Value MC:", v_mc)
    print("Delta: ", d)
    print("Gamma:", g)
    print("Vega:", v)
Beispiel #22
0
def test_FinFixedOIS():
    # Here I follow the example in
    # https://blog.deriscope.com/index.php/en/excel-quantlib-overnight-index-swap

    effective_date = Date(30, 11, 2018)
    end_date = Date(30, 11, 2023)

    end_date = effective_date.add_months(60)
    oisRate = 0.04
    fixed_leg_type = SwapTypes.PAY
    fixedFreqType = FrequencyTypes.ANNUAL
    fixedDayCount = DayCountTypes.ACT_360
    floatFreqType = FrequencyTypes.ANNUAL
    floatDayCount = DayCountTypes.ACT_360
    float_spread = 0.0
    notional = ONE_MILLION
    payment_lag = 1

    ois = OIS(effective_date, end_date, fixed_leg_type, oisRate, fixedFreqType,
              fixedDayCount, notional, payment_lag, float_spread,
              floatFreqType, floatDayCount)

    valuation_date = effective_date
    marketRate = 0.05
    oisCurve = DiscountCurveFlat(valuation_date, marketRate,
                                 FrequencyTypes.ANNUAL)

    v = ois.value(effective_date, oisCurve)
    assert round(v, 4) == 43915.6019
Beispiel #23
0
def testBlackModelCheck():

    # Checking Andersen paper using Black's model
    # Used to check swaption price below - we have Ts = 1 and Te = 4
    # Expect a price around 122 cents which is what I find.

    valuation_date = Date(1, 1, 2020)
    libor_curve = DiscountCurveFlat(valuation_date, 0.06,
                                    FrequencyTypes.SEMI_ANNUAL)

    settlement_date = Date(1, 1, 2020)
    exercise_date = Date(1, 1, 2021)
    maturity_date = Date(1, 1, 2024)

    fixed_coupon = 0.06
    fixed_frequency_type = FrequencyTypes.SEMI_ANNUAL
    fixed_day_count_type = DayCountTypes.THIRTY_E_360_ISDA
    notional = 100.0

    # Pricing a PAY
    swaptionType = SwapTypes.PAY
    swaption = IborSwaption(settlement_date, exercise_date, maturity_date,
                            swaptionType, fixed_coupon, fixed_frequency_type,
                            fixed_day_count_type, notional)

    model = Black(0.20)
    v = swaption.value(valuation_date, libor_curve, model)
    testCases.header("LABEL", "VALUE")
    testCases.print("BLACK'S MODEL PRICE:", v * 100)
def test_IborCapletHull():

    #  Hull Page 703, example 29.3
    todayDate = Date(20, 6, 2019)
    valuation_date = todayDate
    maturity_date = valuation_date.add_tenor("2Y")
    libor_curve = DiscountCurveFlat(valuation_date, 0.070,
                                    FrequencyTypes.QUARTERLY,
                                    DayCountTypes.THIRTY_E_360)

    k = 0.08
    capFloorType = FinCapFloorTypes.CAP
    capFloor = IborCapFloor(valuation_date, maturity_date, capFloorType, k,
                            None, FrequencyTypes.QUARTERLY,
                            DayCountTypes.THIRTY_E_360)

    # Value cap using a single flat cap volatility
    model = Black(0.20)
    capFloor.value(valuation_date, libor_curve, model)

    # Value cap by breaking it down into caplets using caplet vols
    capletStartDate = valuation_date.add_tenor("1Y")
    capletEndDate = capletStartDate.add_tenor("3M")

    vCaplet = capFloor.value_caplet_floor_let(valuation_date, capletStartDate,
                                              capletEndDate, libor_curve,
                                              model)

    # Cannot match Hull due to dates being adjusted
    testCases.header("CORRECT PRICE", "MODEL_PRICE")
    testCases.print(517.29, vCaplet)
Beispiel #25
0
def test_FinFloatIborLeg():

    effective_date = Date(28, 10, 2020)
    maturity_date = Date(28, 10, 2025)

    spread = 0.0
    freq_type = FrequencyTypes.ANNUAL
    day_count_type = DayCountTypes.THIRTY_360_BOND
    notional = 10.0 * ONE_MILLION
    legPayRecType = SwapTypes.PAY
    calendar_type = CalendarTypes.TARGET
    bus_day_adjust_type = BusDayAdjustTypes.FOLLOWING
    date_gen_rule_type = DateGenRuleTypes.BACKWARD
    payment_lag = 0
    principal = 0.0

    swapFloatLeg = SwapFloatLeg(effective_date, maturity_date, legPayRecType,
                                spread, freq_type, day_count_type, notional,
                                principal, payment_lag, calendar_type,
                                bus_day_adjust_type, date_gen_rule_type)

    libor_curve = DiscountCurveFlat(effective_date, 0.05)

    firstFixing = 0.03

    v = swapFloatLeg.value(effective_date, libor_curve, libor_curve,
                           firstFixing)
    assert round(v, 4) == -2009695.8385
Beispiel #26
0
def test_FinFixedOISSwapLeg():

    effective_date = Date(28, 10, 2020)
    maturity_date = Date(28, 10, 2025)

    coupon = -0.515039 / 100.0
    freq_type = FrequencyTypes.ANNUAL
    day_count_type = DayCountTypes.ACT_360
    notional = 10.0 * ONE_MILLION
    legPayRecType = SwapTypes.PAY
    calendar_type = CalendarTypes.TARGET
    bus_day_adjust_type = BusDayAdjustTypes.FOLLOWING
    date_gen_rule_type = DateGenRuleTypes.BACKWARD
    payment_lag = 1
    principal = 0.0

    swapFixedLeg = SwapFixedLeg(effective_date, maturity_date, legPayRecType,
                                coupon, freq_type, day_count_type, notional,
                                principal, payment_lag, calendar_type,
                                bus_day_adjust_type, date_gen_rule_type)

    libor_curve = DiscountCurveFlat(effective_date, 0.05)

    v = swapFixedLeg.value(effective_date, libor_curve)
    assert round(v, 4) == 225367.1730
Beispiel #27
0
def test_BondOptionAmericanConvergenceONE():

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

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

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

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

    timeSteps = range(30, 100, 10)

    for num_time_steps in timeSteps:

        sigma = 0.20
        a = 0.1

        start = time.time()

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

        option_type = OptionTypes.EUROPEAN_PUT
        bond_option2 = BondOption(
            bond, expiry_date, strike_price, face, option_type)
        model2 = BKTree(sigma, a, num_time_steps)
        v2put = bond_option2.value(settlement_date, discount_curve, model2)

        option_type = OptionTypes.AMERICAN_CALL
        bond_option1 = BondOption(
            bond, expiry_date, strike_price, face, option_type)
        model1 = BKTree(sigma, a, num_time_steps)
        v1call = bond_option1.value(settlement_date, discount_curve, model1)

        option_type = OptionTypes.EUROPEAN_CALL
        bond_option2 = BondOption(
            bond, expiry_date, strike_price, face, option_type)
        model2 = BKTree(sigma, a, num_time_steps)
        v2call = bond_option2.value(settlement_date, discount_curve, model2)

        end = time.time()

        period = end - start

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

    # print("==============================================================")

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

    valuation_date = Date(10, 4, 2020)

    forName = "EUR"
    domName = "JPY"
    forCCRate = 0.0294  # EUR
    domCCRate = 0.0171  # USD

    dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

    currency_pair = forName + domName
    spot_fx_rate = 90.72

    tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
    atm_vols = [21.50, 20.50, 19.85, 18.00, 15.95, 14.009]
    marketStrangle25DeltaVols = [0.35, 0.325, 0.300, 0.225, 0.175, 0.100]
    riskReversal25DeltaVols = [-8.350, -8.650, -8.950, -9.250, -9.550, -9.500]

    notional_currency = forName

    atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL_PREM_ADJ
    deltaMethod = FinFXDeltaMethod.SPOT_DELTA_PREM_ADJ

    fxMarket = FXVolSurface(valuation_date,
                            spot_fx_rate,
                            currency_pair,
                            notional_currency,
                            dom_discount_curve,
                            for_discount_curve,
                            tenors,
                            atm_vols,
                            marketStrangle25DeltaVols,
                            riskReversal25DeltaVols,
                            atmMethod,
                            deltaMethod)

    fxMarket.check_calibration(verboseCalibration)

    if PLOT_GRAPHS:
        fxMarket.plot_vol_curves()
def test_FinFXMktVolSurface3(verboseCalibration):

    # EURUSD Example from Paper by Uwe Wystup using Tables 4
    #        print("EURUSD EXAMPLE WYSTUP")

    valuation_date = Date(20, 1, 2009)

    forName = "EUR"
    domName = "USD"
    forCCRate = 0.020113  # EUR
    domCCRate = 0.003525  # USD

    dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

    currency_pair = forName + domName
    spot_fx_rate = 1.3088

    tenors = ['1M']
    atm_vols = [21.6215]
    marketStrangle25DeltaVols = [0.7375]
    riskReversal25DeltaVols = [-0.50]

    notional_currency = forName

    atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL
    deltaMethod = FinFXDeltaMethod.SPOT_DELTA

    fxMarket = FXVolSurface(valuation_date,
                            spot_fx_rate,
                            currency_pair,
                            notional_currency,
                            dom_discount_curve,
                            for_discount_curve,
                            tenors,
                            atm_vols,
                            marketStrangle25DeltaVols,
                            riskReversal25DeltaVols,
                            atmMethod,
                            deltaMethod)

    fxMarket.check_calibration(verboseCalibration)

    if PLOT_GRAPHS:
        fxMarket.plot_vol_curves()
Beispiel #30
0
def test_FinFXMktVolSurface2(capsys):
    # Example from Book extract by Iain Clarke using Tables 3.3 and 3.4
    # print("EURJPY EXAMPLE CLARK")

    valuation_date = Date(10, 4, 2020)

    forName = "EUR"
    domName = "JPY"
    forCCRate = 0.0294  # EUR
    domCCRate = 0.0171  # USD

    dom_discount_curve = DiscountCurveFlat(valuation_date, domCCRate)
    for_discount_curve = DiscountCurveFlat(valuation_date, forCCRate)

    currency_pair = forName + domName
    spot_fx_rate = 90.72

    tenors = ['1M', '2M', '3M', '6M', '1Y', '2Y']
    atm_vols = [21.50, 20.50, 19.85, 18.00, 15.95, 14.009]
    marketStrangle25DeltaVols = [0.35, 0.325, 0.300, 0.225, 0.175, 0.100]
    riskReversal25DeltaVols = [-8.350, -8.650, -8.950, -9.250, -9.550, -9.500]
    marketStrangle10DeltaVols = [3.704, 4.047, 4.396, 4.932, 5.726, 5.709]
    riskReversal10DeltaVols = [
        -15.855, -16.467, -17.114, -17.882, -18.855, -18.217
    ]
    alpha = 0.50  # Equally fit 10 and 25 Delta

    notional_currency = forName

    atmMethod = FinFXATMMethod.FWD_DELTA_NEUTRAL_PREM_ADJ
    deltaMethod = FinFXDeltaMethod.SPOT_DELTA_PREM_ADJ
    vol_functionType = VolFunctionTypes.CLARK5

    fxMarketPlus = FXVolSurfacePlus(
        valuation_date, spot_fx_rate, currency_pair, notional_currency,
        dom_discount_curve, for_discount_curve, tenors, atm_vols,
        marketStrangle25DeltaVols, riskReversal25DeltaVols,
        marketStrangle10DeltaVols, riskReversal10DeltaVols, alpha, atmMethod,
        deltaMethod, vol_functionType)

    # Fails with default stricter tolerance
    fxMarketPlus.check_calibration(verboseCalibration, tol=0.2)
    captured = capsys.readouterr()
    assert captured.out == ""