Esempio n. 1
0
    def test_american_vanilla_option_with_earliest_date_wrong_order(self):

        with self.assertRaises(RuntimeError):
            AmericanExercise(
                self.settlement_date,
                self.maturity
            )
Esempio n. 2
0
    def test_american_vanilla_option(self):

        american_exercise = AmericanExercise(self.maturity)
        american_option = VanillaOption(self.payoff, american_exercise)

        engine = BaroneAdesiWhaleyApproximationEngine(
            self.black_scholes_merton_process)

        american_option.set_pricing_engine(engine)

        self.assertAlmostEquals(4.459628, american_option.net_present_value, 6)
Esempio n. 3
0
    def test_dividend_american_option(self):

        american_exercise = AmericanExercise(self.maturity)
        american_option = DividendVanillaOption(self.payoff, american_exercise,
                                                self.dividend_dates,
                                                self.dividends)

        engine = FDDividendAmericanEngine('CrankNicolson',
                                          self.black_scholes_merton_process,
                                          self.american_time_steps,
                                          self.american_grid_points)

        american_option.set_pricing_engine(engine)

        #Note slightly different value using CrankNicolson
        self.assertAlmostEquals(4.485992, american_option.net_present_value, 6)
Esempio n. 4
0
    def test_dividend_american_option_implied_volatility(self):

        american_exercise = AmericanExercise(self.maturity)
        american_option = DividendVanillaOption(self.payoff, american_exercise,
                                                self.dividend_dates,
                                                self.dividends)

        engine = FdBlackScholesVanillaEngine(self.black_scholes_merton_process,
                                             self.american_time_steps,
                                             self.american_grid_points)

        american_option.set_pricing_engine(engine)

        implied_volatility = american_option.implied_volatility(
            self.target_price, self.black_scholes_merton_process,
            self.accuracy, self.max_evaluations, self.min_vol, self.max_vol)

        self.assertAlmostEqual(0.200, implied_volatility, 3)
Esempio n. 5
0
def dividendOption():
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++ General Parameter for all the computation +++++++++++++++++++++++
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    # declaration of the today's date (date where the records are done)
    todaysDate = Date(24, Jan, 2012)  # INPUT
    Settings.instance(
    ).evaluation_date = todaysDate  #!\ IMPORTANT COMMAND REQUIRED FOR ALL VALUATIONS
    calendar = UnitedStates()  # INPUT
    settlement_days = 2  # INPUT
    # Calcul of the settlement date : need to add a period of 2 days to the todays date
    settlementDate = calendar.advance(todaysDate,
                                      period=Period(settlement_days, Days))
    dayCounter = Actual360()  # INPUT
    currency = USDCurrency()  # INPUT

    print("Date of the evaluation:			", todaysDate)
    print("Calendar used:         			", calendar.name)
    print("Number of settlement Days:		", settlement_days)
    print("Date of settlement:       		", settlementDate)
    print("Convention of day counter:		", dayCounter.name())
    print("Currency of the actual context:\t\t", currency.name)

    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++ Description of the underlying +++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    underlying_name = "IBM"
    underlying_price = 191.75  # INPUT
    underlying_vol = 0.2094  # INPUT

    print("**********************************")
    print("Name of the underlying:			", underlying_name)
    print("Price of the underlying at t0:	", underlying_price)
    print("Volatility of the underlying:		", underlying_vol)

    # For a great managing of price and vol objects --> Handle
    underlying_priceH = SimpleQuote(underlying_price)

    # We suppose the vol constant : his term structure is flat --> BlackConstantVol object
    flatVolTS = BlackConstantVol(settlementDate, calendar, underlying_vol,
                                 dayCounter)

    # ++++++++++++++++++++ Description of Yield Term Structure

    #  Libor data record
    print("**********************************")
    print("Description of the Libor used for the Yield Curve construction")

    Libor_dayCounter = Actual360()

    liborRates = []
    liborRatesTenor = []
    # INPUT : all the following data are input : the rate and the corresponding tenor
    #		You could make the choice of more or less data
    #		--> However you have tho choice the instruments with different maturities
    liborRates = [
        0.002763, 0.004082, 0.005601, 0.006390, 0.007125, 0.007928, 0.009446,
        0.01110
    ]
    liborRatesTenor = [
        Period(tenor, Months) for tenor in [1, 2, 3, 4, 5, 6, 9, 12]
    ]

    for tenor, rate in zip(liborRatesTenor, liborRates):
        print(tenor, "\t\t\t", rate)

    # Swap data record

    # description of the fixed leg of the swap
    Swap_fixedLegTenor = Period(12, Months)  # INPUT
    Swap_fixedLegConvention = ModifiedFollowing  # INPUT
    Swap_fixedLegDayCounter = Actual360()  # INPUT
    # description of the float leg of the swap
    Swap_iborIndex = Libor("USDLibor", Period(3, Months), settlement_days,
                           USDCurrency(), UnitedStates(), Actual360())

    print("Description of the Swap used for the Yield Curve construction")
    print("Tenor of the fixed leg:			", Swap_fixedLegTenor)
    print("Index of the floated leg: 		", Swap_iborIndex.name)
    print("Maturity		Rate				")

    swapRates = []
    swapRatesTenor = []
    # INPUT : all the following data are input : the rate and the corresponding tenor
    #		You could make the choice of more or less data
    #		--> However you have tho choice the instruments with different maturities
    swapRates = [
        0.005681, 0.006970, 0.009310, 0.012010, 0.014628, 0.016881, 0.018745,
        0.020260, 0.021545
    ]
    swapRatesTenor = [Period(i, Years) for i in range(2, 11)]

    for tenor, rate in zip(swapRatesTenor, swapRates):
        print(tenor, "\t\t\t", rate)

    # ++++++++++++++++++++ Creation of the vector of RateHelper (need for the Yield Curve construction)
    # ++++++++++++++++++++ Libor
    LiborFamilyName = currency.name + "Libor"
    instruments = []
    for rate, tenor in zip(liborRates, liborRatesTenor):
        # Index description ___ creation of a Libor index
        liborIndex = Libor(LiborFamilyName, tenor, settlement_days, currency,
                           calendar, Libor_dayCounter)
        # Initialize rate helper	___ the DepositRateHelper link the recording rate with the Libor index
        instruments.append(DepositRateHelper(rate, index=liborIndex))

    # +++++++++++++++++++++ Swap
    SwapFamilyName = currency.name + "swapIndex"
    for tenor, rate in zip(swapRatesTenor, swapRates):
        # swap description ___ creation of a swap index. The floating leg is described in the index 'Swap_iborIndex'
        swapIndex = SwapIndex(SwapFamilyName, tenor, settlement_days, currency,
                              calendar, Swap_fixedLegTenor,
                              Swap_fixedLegConvention, Swap_fixedLegDayCounter,
                              Swap_iborIndex)
        # Initialize rate helper __ the SwapRateHelper links the swap index width his rate
        instruments.append(SwapRateHelper.from_index(rate, swapIndex))

    # ++++++++++++++++++  Now the creation of the yield curve

    riskFreeTS = PiecewiseYieldCurve.from_reference_date(
        BootstrapTrait.ZeroYield, Interpolator.Linear, settlementDate,
        instruments, dayCounter)

    # ++++++++++++++++++  build of the underlying process : with a Black-Scholes model

    print('Creating process')

    bsProcess = BlackScholesProcess(underlying_priceH, riskFreeTS, flatVolTS)

    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++ Description of the option +++++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Option_name = "IBM Option"
    maturity = Date(26, Jan, 2013)
    strike = 190
    option_type = 'call'

    # Here, as an implementation exemple, we make the test with borth american and european exercise
    europeanExercise = EuropeanExercise(maturity)
    # The emericanExercise need also the settlement date, as his right to exerce the buy or call start at the settlement date!
    #americanExercise = AmericanExercise(settlementDate, maturity)
    americanExercise = AmericanExercise(maturity, settlementDate)

    print("**********************************")
    print("Description of the option:		", Option_name)
    print("Date of maturity:     			", maturity)
    print("Type of the option:   			", option_type)
    print("Strike of the option:		    ", strike)

    # ++++++++++++++++++ Description of the discrete dividends
    # INPUT You have to determine the frequece and rates of the discrete dividend. Here is a sollution, but she's not the only one.
    # Last know dividend:
    dividend = 0.75  #//0.75
    next_dividend_date = Date(10, Feb, 2012)
    # HERE we have make the assumption that the dividend will grow with the quarterly croissance:
    dividendCroissance = 1.03
    dividendfrequence = Period(3, Months)
    dividendDates = []
    dividends = []

    d = next_dividend_date
    while d <= maturity:
        dividendDates.append(d)
        dividends.append(dividend)
        d = d + dividendfrequence
        dividend *= dividendCroissance

    print("Discrete dividends				")
    print("Dates				Dividends		")
    for date, div in zip(dividendDates, dividends):
        print(date, "		", div)

    # ++++++++++++++++++ Description of the final payoff
    payoff = PlainVanillaPayoff(option_type, strike)

    # ++++++++++++++++++ The OPTIONS : (American and European) with their dividends description:
    dividendEuropeanOption = DividendVanillaOption(payoff, europeanExercise,
                                                   dividendDates, dividends)
    dividendAmericanOption = DividendVanillaOption(payoff, americanExercise,
                                                   dividendDates, dividends)

    # just too test
    europeanOption = VanillaOption(payoff, europeanExercise)
    americanOption = VanillaOption(payoff, americanExercise)

    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++ Description of the pricing  +++++++++++++++++++++++++++++++++++++
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    # For the european options we have a closed analytic formula: The Black Scholes:
    dividendEuropeanEngine = AnalyticDividendEuropeanEngine(bsProcess)

    # For the american option we have make the choice of the finite difference model with the CrankNicolson scheme
    #		this model need to precise the time and space step
    #		More they are greater, more the calul will be precise.
    americanGirdPoints = 600
    americanTimeSteps = 600
    dividendAmericanEngine = FDDividendAmericanEngine('CrankNicolson',
                                                      bsProcess,
                                                      americanTimeSteps,
                                                      americanGirdPoints)

    # just to test
    europeanEngine = AnalyticEuropeanEngine(bsProcess)
    americanEngine = FDAmericanEngine('CrankNicolson', bsProcess,
                                      americanTimeSteps, americanGirdPoints)

    # ++++++++++++++++++++ Valorisation ++++++++++++++++++++++++++++++++++++++++

    # Link the pricing Engine to the option
    dividendEuropeanOption.set_pricing_engine(dividendEuropeanEngine)
    dividendAmericanOption.set_pricing_engine(dividendAmericanEngine)

    # just	to test
    europeanOption.set_pricing_engine(europeanEngine)
    americanOption.set_pricing_engine(americanEngine)

    # Now we make all the needing calcul
    # ... and final results
    print(
        "NPV of the European Option with discrete dividends=0:	{:.4f}".format(
            dividendEuropeanOption.npv))
    print("NPV of the European Option without dividend:		{:.4f}".format(
        europeanOption.npv))
    print(
        "NPV of the American Option with discrete dividends=0:	{:.4f}".format(
            dividendAmericanOption.npv))
    print("NPV of the American Option without dividend:		{:.4f}".format(
        americanOption.npv))
    # just a single test
    print("ZeroRate with a maturity at ", maturity, ": ", \
            riskFreeTS.zero_rate(maturity, dayCounter, Simple))
Esempio n. 6
0
def main():
    # global data
    todays_date = Date(15, May, 1998)
    Settings.instance().evaluation_date = todays_date
    settlement_date = Date(17, May, 1998)

    risk_free_rate = FlatForward(reference_date=settlement_date,
                                 forward=0.06,
                                 daycounter=Actual365Fixed())

    # option parameters
    exercise = AmericanExercise(earliest_exercise_date=settlement_date,
                                latest_exercise_date=Date(17, May, 1999))
    payoff = PlainVanillaPayoff(Put, 40.0)

    # market data
    underlying = SimpleQuote(36.0)
    volatility = BlackConstantVol(todays_date, TARGET(), 0.20,
                                  Actual365Fixed())
    dividend_yield = FlatForward(reference_date=settlement_date,
                                 forward=0.00,
                                 daycounter=Actual365Fixed())

    # report
    header = '%19s' % 'method' + ' |' + \
            ' |'.join(['%17s' % tag for tag in ['value',
                                                'estimated error',
                                                'actual error' ] ])
    print
    print header
    print '-' * len(header)

    refValue = None

    def report(method, x, dx=None):
        e = '%.4f' % abs(x - refValue)
        x = '%.5f' % x
        if dx:
            dx = '%.4f' % dx
        else:
            dx = 'n/a'
        print '%19s' % method + ' |' + \
            ' |'.join(['%17s' % y for y in [x, dx, e] ])

    # good to go

    process = BlackScholesMertonProcess(underlying, dividend_yield,
                                        risk_free_rate, volatility)

    option = VanillaOption(payoff, exercise)

    refValue = 4.48667344
    report('reference value', refValue)

    # method: analytic

    option.set_pricing_engine(BaroneAdesiWhaleyApproximationEngine(process))
    report('Barone-Adesi-Whaley', option.net_present_value)

    # method: finite differences
    time_steps = 801
    grid_points = 800

    option.set_pricing_engine(
        FDAmericanEngine('CrankNicolson', process, time_steps, grid_points))
    report('finite differences', option.net_present_value)

    print 'This is work in progress.'
    print 'Some pricing engines are not yet interfaced.'

    return

    option.set_pricing_engine(BjerksundStenslandEngine(process))
    report('Bjerksund-Stensland', option.NPV())

    # method: binomial
    timeSteps = 801

    option.setPricingEngine(BinomialVanillaEngine(process, 'jr', timeSteps))
    report('binomial (JR)', option.NPV())

    option.setPricingEngine(BinomialVanillaEngine(process, 'crr', timeSteps))
    report('binomial (CRR)', option.NPV())

    option.setPricingEngine(BinomialVanillaEngine(process, 'eqp', timeSteps))
    report('binomial (EQP)', option.NPV())

    option.setPricingEngine(
        BinomialVanillaEngine(process, 'trigeorgis', timeSteps))
    report('bin. (Trigeorgis)', option.NPV())

    option.setPricingEngine(BinomialVanillaEngine(process, 'tian', timeSteps))
    report('binomial (Tian)', option.NPV())

    option.setPricingEngine(BinomialVanillaEngine(process, 'lr', timeSteps))
    report('binomial (LR)', option.NPV())