def make_rate_helper(market, quote, reference_date=None): """ Wrapper for deposit and swaps rate helpers makers TODO: class method of RateHelper? """ rate_type, tenor, quote_value = quote if rate_type == 'SWAP': libor_index = market._floating_rate_index spread = SimpleQuote(0) fwdStart = Period(0, Days) helper = SwapRateHelper.from_tenor( quote_value, Period(tenor), market._floating_rate_index.fixing_calendar, Period(market._params.fixed_leg_period).frequency, BusinessDayConvention.from_name( market._params.fixed_leg_convention), DayCounter.from_name(market._params.fixed_leg_daycount), libor_index, spread, fwdStart) elif rate_type == 'DEP': end_of_month = True helper = DepositRateHelper( quote_value, Period(tenor), market._params.settlement_days, market._floating_rate_index.fixing_calendar, market._floating_rate_index.business_day_convention, end_of_month, DayCounter.from_name(market._deposit_daycount)) elif rate_type == 'ED': if reference_date is None: raise Exception("Reference date needed with ED Futures data") forward_date = next_imm_date(reference_date, tenor) helper = FuturesRateHelper( price=SimpleQuote(quote_value), imm_date=qldate_from_pydate(forward_date), length_in_months=3, calendar=market._floating_rate_index.fixing_calendar, convention=market._floating_rate_index.business_day_convention, end_of_month=True, day_counter=DayCounter.from_name( market._params.floating_leg_daycount)) elif rate_type.startswith('ER'): # TODO For Euribor futures, we found it useful to supply the `imm_date` # parameter directly, instead of as a number of periods from the # evaluation date, as for ED futures. To achieve this, we pass the # `imm_date` in the `tenor` field of the quote. helper = FuturesRateHelper( price=SimpleQuote(quote_value), imm_date=tenor, length_in_months=3, calendar=market._floating_rate_index.fixing_calendar, convention=market._floating_rate_index.business_day_convention, end_of_month=True, day_counter=DayCounter.from_name( market._params.floating_leg_daycount)) else: raise Exception("Rate type %s not supported" % rate_type) return helper
def example03(): print("example 3:\n") todays_date = Date(13, 6, 2011) Settings.instance().evaluation_date = todays_date quotes = [0.00445, 0.00949, 0.01234, 0.01776, 0.01935, 0.02084] tenors = [1, 2, 3, 6, 9, 12] calendar = WeekendsOnly() deps = [ DepositRateHelper(q, Period(t, Months), 2, calendar, ModifiedFollowing, False, Actual360()) for q, t in zip(quotes, tenors) ] quotes = [ 0.01652, 0.02018, 0.02303, 0.02525, 0.0285, 0.02931, 0.03017, 0.03092, 0.03160, 0.03231, 0.03367, 0.03419, 0.03411, 0.03411, 0.03412 ] tenors = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 20, 25, 30] swaps = [ SwapRateHelper.from_tenor(q, Period(t, Years), calendar, Annual, ModifiedFollowing, Thirty360(), Euribor6M(), SimpleQuote(0)) for q, t in zip(quotes, tenors) ] yield_helpers = deps + swaps isda_yts = PiecewiseYieldCurve(BootstrapTrait.Discount, Interpolator.LogLinear, 0, WeekendsOnly(), yield_helpers, Actual365Fixed()) spreads = [0.007927, 0.012239, 0.016979, 0.019271, 0.020860] tenors = [1, 3, 5, 7, 10] spread_helpers = [SpreadCdsHelper(0.007927, Period(6, Months), 1, WeekendsOnly(), Quarterly, Following, Rule.CDS2015, Actual360(), 0.4, isda_yts, True, True, Date(), Actual360(True), True, PricingModel.ISDA)] + \ [SpreadCdsHelper(s, Period(t, Years), 1, WeekendsOnly(), Quarterly, Following, Rule.CDS2015, Actual360(), 0.4, isda_yts, True, True, Date(), Actual360(True), True, PricingModel.ISDA) for s, t in zip(spreads, tenors)] isda_cts = PiecewiseDefaultCurve(ProbabilityTrait.SurvivalProbability, Interpolator.LogLinear, 0, WeekendsOnly(), spread_helpers, Actual365Fixed()) isda_pricer = IsdaCdsEngine(isda_cts, 0.4, isda_yts) print("Isda yield curve:") for h in yield_helpers: d = h.latest_date t = isda_yts.time_from_reference(d) print(d, t, isda_yts.zero_rate(d, Actual365Fixed()).rate) print() print("Isda credit curve:") for h in spread_helpers: d = h.latest_date t = isda_cts.time_from_reference(d) print(d, t, isda_cts.survival_probability(d))
def example02(): print("example 2:\n") todays_date = Date(25, 9, 2014) Settings.instance().evaluation_date = todays_date calendar = TARGET() term_date = calendar.adjust(todays_date + Period(2, Years), Following) cds_schedule = Schedule(todays_date, term_date, Period(Quarterly), WeekendsOnly(), ModifiedFollowing, ModifiedFollowing, date_generation_rule=Rule.CDS) for date in cds_schedule: print(date) print() todays_date = Date(21, 10, 2014) Settings.instance().evaluation_date = todays_date quotes = [0.00006, 0.00045, 0.00081, 0.001840, 0.00256, 0.00337] tenors = [1, 2, 3, 6, 9, 12] deps = [DepositRateHelper(q, Period(t, Months), 2, calendar, ModifiedFollowing, False, Actual360()) for q, t in zip(quotes, tenors)] tenors = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30] quotes = [0.00223, 0.002760, 0.003530, 0.004520, 0.005720, 0.007050, 0.008420, 0.009720, 0.010900, 0.012870, 0.014970, 0.017, 0.01821] swaps = [SwapRateHelper.from_tenor(q, Period(t, Years), calendar, Annual, ModifiedFollowing, Thirty360(), Euribor6M(), SimpleQuote(0)) for q, t in zip(quotes, tenors)] helpers = deps + swaps YC = PiecewiseYieldCurve.from_reference_date(BootstrapTrait.Discount, Interpolator.LogLinear, todays_date, helpers, Actual365Fixed()) YC.extrapolation = True print("ISDA rate curve:") for h in helpers: print("{0}: {1:.6f}\t{2:.6f}".format(h.latest_date, YC.zero_rate(h.latest_date, Actual365Fixed(), 2).rate, YC.discount(h.latest_date))) defaultTs0 = FlatHazardRate(0, WeekendsOnly(), 0.016739207493630, Actual365Fixed()) cds_schedule = Schedule.from_rule(Date(22, 9, 2014), Date(20, 12, 2019), Period(3, Months), WeekendsOnly(), Following, Unadjusted, Rule.CDS, False) nominal = 100000000 trade = CreditDefaultSwap(Side.Buyer, nominal, 0.01, cds_schedule, Following, Actual360(), True, True, Date(22, 10, 2014), Actual360(True), True) engine = IsdaCdsEngine(defaultTs0, 0.4, YC, False) trade.set_pricing_engine(engine) print("reference trade NPV = {0}\n".format(trade.npv))
def example03(): print("example 3:\n") todays_date = Date(13, 6, 2011) Settings.instance().evaluation_date = todays_date quotes = [0.00445, 0.00949, 0.01234, 0.01776, 0.01935, 0.02084] tenors = [1, 2, 3, 6, 9, 12] calendar = WeekendsOnly() deps = [DepositRateHelper(q, Period(t, Months), 2, calendar, ModifiedFollowing, False, Actual360()) for q, t in zip(quotes, tenors)] quotes = [0.01652, 0.02018, 0.02303, 0.02525, 0.0285, 0.02931, 0.03017, 0.03092, 0.03160, 0.03231, 0.03367, 0.03419, 0.03411, 0.03411, 0.03412] tenors = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 20, 25, 30] swaps = [SwapRateHelper.from_tenor(q, Period(t, Years), calendar, Annual, ModifiedFollowing, Thirty360(), Euribor6M(), SimpleQuote(0)) for q, t in zip(quotes, tenors)] yield_helpers = deps + swaps isda_yts = PiecewiseYieldCurve(BootstrapTrait.Discount, Interpolator.LogLinear, 0, WeekendsOnly(), yield_helpers, Actual365Fixed()) spreads = [0.007927, 0.012239, 0.016979, 0.019271, 0.020860] tenors = [1, 3, 5, 7, 10] spread_helpers = [SpreadCdsHelper(0.007927, Period(6, Months), 1, WeekendsOnly(), Quarterly, Following, Rule.CDS2015, Actual360(), 0.4, isda_yts, True, True, Date(), Actual360(True), True, PricingModel.ISDA)] + \ [SpreadCdsHelper(s, Period(t, Years), 1, WeekendsOnly(), Quarterly, Following, Rule.CDS2015, Actual360(), 0.4, isda_yts, True, True, Date(), Actual360(True), True, PricingModel.ISDA) for s, t in zip(spreads, tenors)] isda_cts = PiecewiseDefaultCurve(ProbabilityTrait.SurvivalProbability, Interpolator.LogLinear, 0, WeekendsOnly(), spread_helpers, Actual365Fixed()) isda_pricer = IsdaCdsEngine(isda_cts, 0.4, isda_yts) print("Isda yield curve:") for h in yield_helpers: d = h.latest_date t = isda_yts.time_from_reference(d) print(d, t, isda_yts.zero_rate(d, Actual365Fixed()).rate) print() print("Isda credit curve:") for h in spread_helpers: d = h.latest_date t = isda_cts.time_from_reference(d) print(d, t, isda_cts.survival_probability(d))
def example02(): print("example 2:\n") todays_date = Date(25, 9, 2014) Settings.instance().evaluation_date = todays_date calendar = TARGET() term_date = calendar.adjust(todays_date + Period(2, Years), Following) cds_schedule = Schedule(todays_date, term_date, Period(Quarterly), WeekendsOnly(), ModifiedFollowing, ModifiedFollowing, date_generation_rule=Rule.CDS) for date in cds_schedule: print(date) print() todays_date = Date(21, 10, 2014) Settings.instance().evaluation_date = todays_date quotes = [0.00006, 0.00045, 0.00081, 0.001840, 0.00256, 0.00337] tenors = [1, 2, 3, 6, 9, 12] deps = [DepositRateHelper(q, Period(t, Months), 2, calendar, ModifiedFollowing, False, Actual360()) for q, t in zip(quotes, tenors)] tenors = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30] quotes = [0.00223, 0.002760, 0.003530, 0.004520, 0.005720, 0.007050, 0.008420, 0.009720, 0.010900, 0.012870, 0.014970, 0.017, 0.01821] swaps = [SwapRateHelper.from_tenor(q, Period(t, Years), calendar, Annual, ModifiedFollowing, Thirty360(), Euribor6M(), SimpleQuote(0)) for q, t in zip(quotes, tenors)] helpers = deps + swaps YC = PiecewiseYieldCurve.from_reference_date(BootstrapTrait.Discount, Interpolator.LogLinear, todays_date, helpers, Actual365Fixed()) YC.extrapolation = True print("ISDA rate curve:") for h in helpers: print("{0}: {1:.6f}\t{2:.6f}".format(h.latest_date, YC.zero_rate(h.latest_date, Actual365Fixed(), 2).rate, YC.discount(h.latest_date))) defaultTs0 = FlatHazardRate(0, WeekendsOnly(), 0.016739207493630, Actual365Fixed()) cds_schedule = Schedule.from_rule(Date(22, 9, 2014), Date(20, 12, 2019), Period(3, Months), WeekendsOnly(), Following, Unadjusted, Rule.CDS, False) nominal = 100000000 trade = CreditDefaultSwap(Side.Buyer, nominal, 0.01, cds_schedule, Following, Actual360(), True, True, Date(22, 10, 2014), Actual360(True), True) engine = IsdaCdsEngine(defaultTs0, 0.4, YC, False) trade.set_pricing_engine(engine) print("reference trade NPV = {0}\n".format(trade.npv))
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))
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))
def make_rate_helper(market, quote, reference_date=None): """ Wrapper for deposit and swaps rate helpers makers TODO: class method of RateHelper? """ rate_type, tenor, quote_value = quote if rate_type == 'SWAP': libor_index = market._floating_rate_index spread = SimpleQuote(0) fwdStart = Period(0, Days) helper = SwapRateHelper.from_tenor( quote_value, Period(tenor), market._floating_rate_index.fixing_calendar, code_to_frequency(market._params.fixed_leg_period), BusinessDayConvention.from_name( market._params.fixed_leg_convention), DayCounter.from_name(market._params.fixed_leg_daycount), libor_index, spread, fwdStart) elif rate_type == 'DEP': end_of_month = True helper = DepositRateHelper( quote_value, Period(tenor), market._params.settlement_days, market._floating_rate_index.fixing_calendar, market._floating_rate_index.business_day_convention, end_of_month, DayCounter.from_name(market._deposit_daycount)) elif rate_type == 'ED': if reference_date is None: raise Exception("Reference date needed with ED Futures data") forward_date = next_imm_date(reference_date, tenor) helper = FuturesRateHelper( rate =SimpleQuote(quote_value), imm_date = qldate_from_pydate(forward_date), length_in_months = 3, calendar = market._floating_rate_index.fixing_calendar, convention = market._floating_rate_index.business_day_convention, end_of_month = True, day_counter = DayCounter.from_name( market._params.floating_leg_daycount)) elif rate_type.startswith('ER'): # TODO For Euribor futures, we found it useful to supply the `imm_date` # parameter directly, instead of as a number of periods from the # evaluation date, as for ED futures. To achieve this, we pass the # `imm_date` in the `tenor` field of the quote. helper = FuturesRateHelper( rate=SimpleQuote(quote_value), imm_date=tenor, length_in_months=3, calendar=market._floating_rate_index.fixing_calendar, convention=market._floating_rate_index.business_day_convention, end_of_month=True, day_counter=DayCounter.from_name( market._params.floating_leg_daycount)) else: raise Exception("Rate type %s not supported" % rate_type) return helper
futuresHelpers = [ FuturesRateHelper(futures[d], d, months, calendar, ModifiedFollowing, True, day_counter) for d in futures.keys() ] settlementDays = 2 fixedLegFrequency = Annual fixedLegTenor = Period(1,Years) fixedLegAdjustment = Unadjusted fixedLegDayCounter = Thirty360() floatingLegFrequency = Semiannual floatingLegTenor = Period(6,Months) floatingLegAdjustment = ModifiedFollowing swapHelpers = [ SwapRateHelper.from_tenor(swaps[(n,unit)], Period(n,unit), calendar, fixedLegFrequency, fixedLegAdjustment, fixedLegDayCounter, Euribor6M()) for n, unit in swaps.keys() ] ### Curve building ts_daycounter = ActualActual(ISDA) # term-structure construction helpers = depositHelpers + swapHelpers depoSwapCurve = PiecewiseYieldCurve.from_reference_date( BootstrapTrait.Discount, Interpolator.LogLinear, settlementDate, helpers, ts_daycounter ) helpers = depositHelpers[:2] + futuresHelpers + swapHelpers[1:] depoFuturesSwapCurve = PiecewiseYieldCurve.from_reference_date(