├── blog_american_and_european_option.py ├── blog_american_option.py ├── blog_american_option_with_implied_vol.py ├── blog_bond_example.py ├── blog_european_option.py └── blog_frn_example.py /blog_american_and_european_option.py: -------------------------------------------------------------------------------- 1 | ''' 2 | QuantLib with Python example 3 | Copyright (C) 2014 John Orford 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as 7 | published by the Free Software Foundation, either version 3 of the 8 | License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | ''' 18 | 19 | 20 | from QuantLib import * 21 | 22 | 23 | def getProcess(valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price): 24 | 25 | 26 | ################################################### 27 | ##2) 28 | #Date setup 29 | ################################################### 30 | 31 | #Assumptions 32 | calendar = UnitedStates() 33 | day_counter = ActualActual() 34 | 35 | Settings.instance().evaluation_date = valuation_date 36 | 37 | 38 | ################################################### 39 | ##3) 40 | #Curve setup 41 | ################################################### 42 | 43 | interest_curve = FlatForward(valuation_date, interest_rate, day_counter ) 44 | 45 | dividend_curve = FlatForward(valuation_date, dividend_rate, day_counter ) 46 | 47 | volatility_curve = BlackConstantVol(valuation_date, calendar, volatility_rate, day_counter ) 48 | 49 | #Collate market data together 50 | u = QuoteHandle(underlying_price) 51 | d = YieldTermStructureHandle(dividend_curve) 52 | r = YieldTermStructureHandle(interest_curve) 53 | v = BlackVolTermStructureHandle(volatility_curve) 54 | 55 | return BlackScholesMertonProcess(u, d, r, v) 56 | 57 | 58 | ################################################### 59 | ##4) 60 | #Option setup 61 | ################################################### 62 | 63 | def getEuroOption(expiry_date, put_or_call, strike_price, process): 64 | 65 | exercise = EuropeanExercise(expiry_date) 66 | payoff = PlainVanillaPayoff(put_or_call, strike_price) 67 | 68 | #Option Setup 69 | option = VanillaOption(payoff, exercise) 70 | 71 | engine = AnalyticEuropeanEngine(process) 72 | 73 | option.setPricingEngine(engine) 74 | 75 | return option 76 | 77 | 78 | def getAmericanOption(valuation_date, expiry_date, put_or_call, strike_price, process): 79 | 80 | exercise = AmericanExercise(valuation_date, expiry_date) 81 | 82 | payoff = PlainVanillaPayoff(put_or_call, strike_price) 83 | 84 | #Option Setup 85 | option = VanillaOption(payoff, exercise) 86 | 87 | time_steps = 100 88 | grid_points = 100 89 | 90 | #engine = BinomialVanillaEngine(process,'crr',time_steps) 91 | engine = FDAmericanEngine(process,time_steps,grid_points) 92 | 93 | option.setPricingEngine(engine) 94 | 95 | return option 96 | 97 | 98 | ################################################### 99 | ##5) 100 | ##Collate results 101 | ################################################### 102 | 103 | def getAmericanResults(option): 104 | print "NPV: ", option.NPV() 105 | print "Delta: ", option.delta() 106 | print "Gamma: ", option.gamma() 107 | #print "Theta: ", option.theta() 108 | 109 | def getEuropeanResults(option): 110 | print "NPV: ", option.NPV() 111 | print "Delta: ", option.delta() 112 | print "Gamma: ", option.gamma() 113 | print "Vega: ", option.vega() 114 | print "Theta: ", option.theta() 115 | print "Rho: ", option.rho() 116 | print "Dividend Rho: ", option.dividendRho() 117 | print "Theta per Day: ", option.thetaPerDay() 118 | print "Strike Sensitivity: ", option.strikeSensitivity() 119 | 120 | 121 | ################################################### 122 | ##1) 123 | ##Inputs 124 | ################################################### 125 | 126 | #dates 127 | valuation_date = Date(17,4,2014) 128 | expiry_date = Date(15,1,2016) 129 | 130 | #terms and conditions 131 | strike_price = 35 132 | put_or_call = Option.Call 133 | 134 | #market data 135 | interest_rate = 0.01 136 | #see idivs.org for expected dividend yields 137 | dividend_rate = 0 138 | volatility_rate = 0.5 139 | underlying_price = SimpleQuote(36.35) 140 | 141 | market_value = 7.5 142 | 143 | 144 | 145 | process = getProcess( valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price) 146 | 147 | 148 | eOption = getEuroOption( expiry_date, put_or_call, strike_price, process) 149 | 150 | implied_volatility_rate = eOption.impliedVolatility(market_value, process) 151 | 152 | calibrated_process = getProcess( valuation_date, interest_rate, dividend_rate, implied_volatility_rate, underlying_price) 153 | 154 | calibrated_eOption = getEuroOption( expiry_date, put_or_call, strike_price, calibrated_process) 155 | 156 | 157 | aOption = getAmericanOption( valuation_date, expiry_date, put_or_call, strike_price, process) 158 | 159 | implied_volatility_rate = aOption.impliedVolatility(market_value, process) 160 | 161 | calibrated_process = getProcess( valuation_date, interest_rate, dividend_rate, implied_volatility_rate, underlying_price) 162 | 163 | calibrated_aOption = getAmericanOption( valuation_date, expiry_date, put_or_call, strike_price, calibrated_process) 164 | 165 | 166 | 167 | print "" 168 | print "European Results" 169 | 170 | getEuropeanResults(calibrated_eOption) 171 | 172 | print "" 173 | print "American Results" 174 | 175 | getAmericanResults(calibrated_aOption) 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /blog_american_option.py: -------------------------------------------------------------------------------- 1 | ''' 2 | QuantLib with Python example 3 | Copyright (C) 2014 John Orford 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as 7 | published by the Free Software Foundation, either version 3 of the 8 | License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | ''' 18 | 19 | 20 | from QuantLib import * 21 | 22 | 23 | ################################################### 24 | ##1) 25 | ##Inputs 26 | ################################################### 27 | 28 | #dates 29 | valuation_date = Date(17,4,2014) 30 | expiry_date = Date(15,1,2016) 31 | 32 | #terms and conditions 33 | strike_price = 35 34 | put_or_call = Option.Call 35 | 36 | #market data 37 | interest_rate = 0.01 38 | #see idivs.org for expected dividend yields 39 | dividend_rate = 0.02 40 | volatility_rate = 0.5 41 | underlying_price = SimpleQuote(36.35) 42 | 43 | market_value = 7.5 44 | 45 | 46 | def getProcess(valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price): 47 | 48 | 49 | ################################################### 50 | ##2) 51 | #Date setup 52 | ################################################### 53 | 54 | #Assumptions 55 | calendar = UnitedStates() 56 | day_counter = ActualActual() 57 | 58 | Settings.instance().evaluation_date = valuation_date 59 | 60 | 61 | ################################################### 62 | ##3) 63 | #Curve setup 64 | ################################################### 65 | 66 | interest_curve = FlatForward(valuation_date, interest_rate, day_counter ) 67 | 68 | dividend_curve = FlatForward(valuation_date, dividend_rate, day_counter ) 69 | 70 | volatility_curve = BlackConstantVol(valuation_date, calendar, volatility_rate, day_counter ) 71 | 72 | #Collate market data together 73 | u = QuoteHandle(underlying_price) 74 | d = YieldTermStructureHandle(dividend_curve) 75 | r = YieldTermStructureHandle(interest_curve) 76 | v = BlackVolTermStructureHandle(volatility_curve) 77 | 78 | return BlackScholesMertonProcess(u, d, r, v) 79 | 80 | 81 | ################################################### 82 | ##4) 83 | #Option setup 84 | ################################################### 85 | 86 | def getAmericanOption(valuation_date, expiry_date, put_or_call, strike_price, process): 87 | 88 | exercise = AmericanExercise(valuation_date, expiry_date) 89 | 90 | payoff = PlainVanillaPayoff(put_or_call, strike_price) 91 | 92 | #Option Setup 93 | option = VanillaOption(payoff, exercise) 94 | 95 | time_steps = 100 96 | grid_points = 100 97 | 98 | engine = FDAmericanEngine(process,time_steps,grid_points) 99 | 100 | option.setPricingEngine(engine) 101 | 102 | return option 103 | 104 | 105 | ################################################### 106 | ##5) 107 | ##Collate results 108 | ################################################### 109 | 110 | def getAmericanResults(option): 111 | print "NPV: ", option.NPV() 112 | print "Delta: ", option.delta() 113 | print "Gamma: ", option.gamma() 114 | #print "Theta: ", option.theta() 115 | 116 | 117 | 118 | 119 | 120 | process = getProcess( valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price) 121 | 122 | option = getAmericanOption( valuation_date, expiry_date, put_or_call, strike_price, process) 123 | 124 | getAmericanResults(option) 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /blog_american_option_with_implied_vol.py: -------------------------------------------------------------------------------- 1 | ''' 2 | QuantLib with Python example 3 | Copyright (C) 2014 John Orford 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as 7 | published by the Free Software Foundation, either version 3 of the 8 | License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | ''' 18 | 19 | 20 | from QuantLib import * 21 | 22 | 23 | ################################################### 24 | ##1) 25 | ##Inputs 26 | ################################################### 27 | 28 | #dates 29 | valuation_date = Date(17,4,2014) 30 | expiry_date = Date(15,1,2016) 31 | 32 | #terms and conditions 33 | strike_price = 35 34 | put_or_call = Option.Call 35 | 36 | #market data 37 | interest_rate = 0.01 38 | #see idivs.org for expected dividend yields 39 | dividend_rate = 0.02 40 | volatility_rate = 0.5 41 | underlying_price = SimpleQuote(36.35) 42 | 43 | market_value = 7.5 44 | 45 | 46 | def getProcess(valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price): 47 | 48 | 49 | ################################################### 50 | ##2) 51 | #Date setup 52 | ################################################### 53 | 54 | #Assumptions 55 | calendar = UnitedStates() 56 | day_counter = ActualActual() 57 | 58 | Settings.instance().evaluation_date = valuation_date 59 | 60 | 61 | ################################################### 62 | ##3) 63 | #Curve setup 64 | ################################################### 65 | 66 | interest_curve = FlatForward(valuation_date, interest_rate, day_counter ) 67 | 68 | dividend_curve = FlatForward(valuation_date, dividend_rate, day_counter ) 69 | 70 | volatility_curve = BlackConstantVol(valuation_date, calendar, volatility_rate, day_counter ) 71 | 72 | #Collate market data together 73 | u = QuoteHandle(underlying_price) 74 | d = YieldTermStructureHandle(dividend_curve) 75 | r = YieldTermStructureHandle(interest_curve) 76 | v = BlackVolTermStructureHandle(volatility_curve) 77 | 78 | return BlackScholesMertonProcess(u, d, r, v) 79 | 80 | 81 | ################################################### 82 | ##4) 83 | #Option setup 84 | ################################################### 85 | 86 | def getAmericanOption(valuation_date, expiry_date, put_or_call, strike_price, process): 87 | 88 | exercise = AmericanExercise(valuation_date, expiry_date) 89 | 90 | payoff = PlainVanillaPayoff(put_or_call, strike_price) 91 | 92 | #Option Setup 93 | option = VanillaOption(payoff, exercise) 94 | 95 | time_steps = 100 96 | grid_points = 100 97 | 98 | engine = FDAmericanEngine(process,time_steps,grid_points) 99 | 100 | option.setPricingEngine(engine) 101 | 102 | return option 103 | 104 | 105 | ################################################### 106 | ##5) 107 | ##Collate results 108 | ################################################### 109 | 110 | def getAmericanResults(option): 111 | print "NPV: ", option.NPV() 112 | print "Delta: ", option.delta() 113 | print "Gamma: ", option.gamma() 114 | #print "Theta: ", option.theta() 115 | 116 | process = getProcess( valuation_date, interest_rate, dividend_rate, volatility_rate, underlying_price) 117 | 118 | option = getAmericanOption( valuation_date, expiry_date, put_or_call, strike_price, process) 119 | 120 | implied_volatility_rate = option.impliedVolatility(market_value, process) 121 | 122 | calibrated_process = getProcess( valuation_date, interest_rate, dividend_rate, implied_volatility_rate, underlying_price) 123 | 124 | calibrated_option = getAmericanOption( valuation_date, expiry_date, put_or_call, strike_price, calibrated_process) 125 | 126 | #getAmericanResults(calibrated_option) 127 | 128 | print "Implied Volatility: ", implied_volatility_rate 129 | print "NPV: ", option.NPV() 130 | print "Delta: ", option.delta() 131 | print "Gamma: ", option.gamma() 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /blog_bond_example.py: -------------------------------------------------------------------------------- 1 | 2 | ''' 3 | QuantLib with python example 4 | Copyright (C) 2014 John Orford 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as 8 | published by the Free Software Foundation, either version 3 of the 9 | License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see . 18 | ''' 19 | 20 | 21 | ####################################################################### 22 | ## 1) Global data 23 | ## 2) Date setup 24 | ## 3) Construct yield term structure 25 | ## 4) Setup initial bond 26 | ## 5) Calibrate and find spread 27 | ## 6) Collate results 28 | 29 | 30 | from QuantLib import * 31 | 32 | 33 | ####################################################################### 34 | ## 1) Global data 35 | 36 | #switch to quantlib date object 37 | valuation_date = Date(14,4,2014) 38 | maturity_date = Date(1,9,2041) 39 | 40 | payment_frequency = Semiannual 41 | 42 | #Global data defaults 43 | day_counter = ActualActual(ActualActual.Bond) 44 | compounding = QuantLib.SimpleThenCompounded 45 | 46 | settlement_days = 0 47 | 48 | calendar = UnitedStates() 49 | payment_convention = ModifiedFollowing 50 | 51 | face = 100 52 | coupon = 0.06875 53 | market_value = 101.5 54 | 55 | # Create a dictionary of yield quotes by tenor 56 | zcQuotes = [ (0.0003, Period(1,Months)), 57 | (0.0004, Period(3,Months)), 58 | (0.0006, Period(6,Months)), 59 | (0.0010, Period(1,Years)), 60 | (0.0037, Period(2,Years)), 61 | (0.0082, Period(3,Years)), 62 | (0.0161, Period(5,Years)), 63 | (0.0218, Period(7,Years)), 64 | (0.0265, Period(10,Years)), 65 | (0.0323, Period(20,Years)), 66 | (0.0333, Period(25,Years)), 67 | (0.0348, Period(30,Years)) 68 | ] 69 | 70 | 71 | ####################################################################### 72 | ## 2) Date setup 73 | 74 | #if the date is a hol or wknd I then adjust appropriately (advance method) 75 | valuation_date = calendar.advance(valuation_date,0,Days) 76 | 77 | 78 | #figure out and set today's date, use advance to change as necessary.. 79 | #assume that todaysDate = valuation_date 80 | #todays_date = calendar.advance(valuation_date,0,Days) 81 | Settings.instance().evaluationDate = valuation_date 82 | 83 | 84 | ####################################################################### 85 | ## 3) Construct yield term structure 86 | 87 | def getTermStructure(valuation_date, zcQuotes, calendar, payment_convention, day_counter): 88 | 89 | fixing_days = 0 90 | 91 | # Create deposit rate helpers 92 | zcHelpers = [ DepositRateHelper(QuoteHandle(SimpleQuote(r)), 93 | tenor, 94 | fixing_days, 95 | calendar, 96 | payment_convention, 97 | True, 98 | day_counter) 99 | for (r,tenor) in zcQuotes ] 100 | 101 | # Term structure to be used in discounting bond cash flows 102 | return PiecewiseFlatForward(valuation_date, zcHelpers, day_counter) 103 | 104 | 105 | ####################################################################### 106 | ## 4) Setup initial bond 107 | 108 | def getBond( valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure, z_spread = 0): 109 | 110 | #move back a year in order to capture all accrued interest 111 | #may be caught out if there's an irregular coupon payment at beginning 112 | issue_date = calendar.advance(valuation_date,-1,Years) 113 | 114 | #Bond schedule T&Cs 115 | fixedBondSchedule = Schedule( issue_date, 116 | maturity_date, 117 | Period(payment_frequency), 118 | calendar, 119 | Unadjusted, 120 | Unadjusted, 121 | DateGeneration.Backward, 122 | False) 123 | #Bond T&Cs 124 | fixedRateBond = FixedRateBond( 0, 125 | face, 126 | fixedBondSchedule, 127 | [coupon], 128 | bondDiscountingTermStructure.dayCounter(), 129 | payment_convention, 130 | 100, 131 | issue_date) 132 | 133 | #Zero spread needs to be a 'quote handle' object whatever that is 134 | zSpreadQuoteHandle = QuoteHandle( SimpleQuote(z_spread) ) 135 | 136 | discountingTermStructure = RelinkableYieldTermStructureHandle() 137 | discountingTermStructure.linkTo(bondDiscountingTermStructure) 138 | 139 | zSpreadedTermStructure = ZeroSpreadedTermStructure(discountingTermStructure, zSpreadQuoteHandle) 140 | 141 | #Create new relinkable handle for calibrated zero spread 142 | zSpreadRelinkableHandle = RelinkableYieldTermStructureHandle() 143 | 144 | #Link up 145 | zSpreadRelinkableHandle.linkTo(zSpreadedTermStructure) 146 | bondEngine_with_added_zspread = DiscountingBondEngine(zSpreadRelinkableHandle) 147 | 148 | #Set new bond engine 149 | #Ready for use 150 | fixedRateBond.setPricingEngine(bondEngine_with_added_zspread) 151 | 152 | return fixedRateBond 153 | 154 | 155 | ####################################################################### 156 | ## 6) Collate results 157 | 158 | def getResults(fixedRateBond, compounding): 159 | #find yield 160 | yield_rate = fixedRateBond.bondYield(fixedRateBond.dayCounter(),compounding,fixedRateBond.frequency()) 161 | #convert yield to interest rate object 162 | y = InterestRate(yield_rate,fixedRateBond.dayCounter(),compounding,fixedRateBond.frequency()) 163 | 164 | result_duration = BondFunctions.duration(fixedRateBond,y) 165 | result_convexity = BondFunctions.convexity(fixedRateBond,y) 166 | result_bps = BondFunctions.bps(fixedRateBond,y) 167 | result_basis_pt_value = BondFunctions.basisPointValue(fixedRateBond,y) 168 | result_npv = fixedRateBond.NPV() 169 | result_yield_value_bp = BondFunctions.yieldValueBasisPoint(fixedRateBond,y) 170 | result_yield_to_maturity = yield_rate 171 | 172 | print "Duration: ",result_duration 173 | print "Convexity: ",result_convexity 174 | print "Bps: ",result_bps 175 | print "Basis Pt Value: ",result_basis_pt_value 176 | print "NPV: ",result_npv 177 | print "Yield Value Bp: ",result_yield_value_bp 178 | print "Yield to Maturity: ",result_yield_to_maturity 179 | print "Accrued: ",fixedRateBond.accruedAmount() 180 | 181 | 182 | # Handle for the term structure linked to flat forward curve 183 | # I think this is used so that curves can be swapped in and out 184 | # Unsure how to do that yet though 185 | bondDiscountingTermStructure = getTermStructure(valuation_date, zcQuotes, calendar, payment_convention, day_counter) 186 | 187 | fixedRateBond = getBond(valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure) 188 | 189 | ####################################################################### 190 | ## 5) Calibrate and find spread 191 | 192 | z_spread = CashFlows.zSpread( fixedRateBond.cashflows(), 193 | #Assume market value input is quoted clean 194 | market_value + fixedRateBond.accruedAmount(), 195 | bondDiscountingTermStructure, 196 | fixedRateBond.dayCounter(), 197 | compounding, 198 | fixedRateBond.frequency(), 199 | True 200 | ) 201 | 202 | fixedRateBond = getBond(valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure, z_spread) 203 | 204 | getResults(fixedRateBond, compounding) 205 | 206 | -------------------------------------------------------------------------------- /blog_european_option.py: -------------------------------------------------------------------------------- 1 | ''' 2 | QuantLib with python example 3 | Copyright (C) 2014 John Orford 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as 7 | published by the Free Software Foundation, either version 3 of the 8 | License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | ''' 18 | 19 | 20 | 21 | from QuantLib import * 22 | 23 | 24 | ################################################### 25 | ##1) 26 | ##Inputs 27 | ################################################### 28 | 29 | #dates 30 | valuation_date = Date(13,1,2014) 31 | expiry_date = Date(13,1,2015) 32 | 33 | #terms and conditions 34 | strike_price = 123 35 | put_or_call = Option.Call 36 | 37 | #market data 38 | interest_rate = 0.01 39 | #see idivs.org for expected dividend yields 40 | dividend_rate = 0.02 41 | volatility_rate = 0.03 42 | underlying_price = SimpleQuote(123) 43 | 44 | 45 | ################################################### 46 | ##2) 47 | #Date setup 48 | ################################################### 49 | Settings.instance().evaluation_date = valuation_date 50 | 51 | #Asumptions 52 | calendar = UnitedStates() 53 | day_counter = ActualActual() 54 | 55 | 56 | ################################################### 57 | ##3) 58 | #Curve setup 59 | ################################################### 60 | interest_curve = FlatForward(valuation_date, interest_rate, day_counter ) 61 | 62 | dividend_curve = FlatForward(valuation_date, dividend_rate, day_counter ) 63 | 64 | volatility_curve = BlackConstantVol(valuation_date, calendar, volatility_rate, day_counter ) 65 | 66 | 67 | ################################################### 68 | ##4) 69 | #Option setup 70 | ################################################### 71 | exercise = EuropeanExercise(expiry_date) 72 | payoff = PlainVanillaPayoff(put_or_call, strike_price) 73 | 74 | #Option Setup 75 | option = VanillaOption(payoff, exercise) 76 | 77 | #Collate market data together 78 | u = QuoteHandle(underlying_price) 79 | d = YieldTermStructureHandle(dividend_curve) 80 | r = YieldTermStructureHandle(interest_curve) 81 | v = BlackVolTermStructureHandle(volatility_curve) 82 | process = BlackScholesMertonProcess(u, d, r, v) 83 | 84 | #Set pricing engine 85 | engine = AnalyticEuropeanEngine(process) 86 | option.setPricingEngine(engine) 87 | 88 | 89 | ################################################### 90 | ##5) 91 | ##Collate results 92 | ################################################### 93 | print "NPV: ", option.NPV() 94 | print "Delta: ", option.delta() 95 | print "Gamma: ", option.gamma() 96 | print "Vega: ", option.vega() 97 | print "Theta: ", option.theta() 98 | print "Rho: ", option.rho() 99 | print "Dividend Rho: ", option.dividendRho() 100 | print "Theta per Day: ", option.thetaPerDay() 101 | print "Strike Sensitivity: ", option.strikeSensitivity() -------------------------------------------------------------------------------- /blog_frn_example.py: -------------------------------------------------------------------------------- 1 | ''' 2 | QuantLib with python example 3 | Copyright (C) 2014 John Orford 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as 7 | published by the Free Software Foundation, either version 3 of the 8 | License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see . 17 | ''' 18 | 19 | ####################################################################### 20 | ## 1) Global data 21 | ## 2) Date setup 22 | ## 3) Construct yield term structure 23 | ## 4) Setup initial bond 24 | ## 5) Calibrate and find spread 25 | ## 6) Collate results 26 | 27 | 28 | from QuantLib import * 29 | 30 | 31 | ####################################################################### 32 | ## 1) Global data 33 | 34 | #switch to quantlib date object 35 | valuation_date = Date(14,4,2014) 36 | maturity_date = Date(1,9,2041) 37 | 38 | payment_frequency = Semiannual 39 | 40 | #Global data defaults 41 | day_counter = ActualActual(ActualActual.Bond) 42 | compounding = QuantLib.SimpleThenCompounded 43 | 44 | settlement_days = 0 45 | 46 | calendar = UnitedStates() 47 | payment_convention = ModifiedFollowing 48 | 49 | face = 100 50 | coupon = 0.06875 51 | market_value = 101.5 52 | 53 | # Create a dictionary of yield quotes by tenor 54 | zcQuotes = [ (0.0003, Period(1,Months)), 55 | (0.0004, Period(3,Months)), 56 | (0.0006, Period(6,Months)), 57 | (0.0010, Period(1,Years)), 58 | (0.0037, Period(2,Years)), 59 | (0.0082, Period(3,Years)), 60 | (0.0161, Period(5,Years)), 61 | (0.0218, Period(7,Years)), 62 | (0.0265, Period(10,Years)), 63 | (0.0323, Period(20,Years)), 64 | (0.0333, Period(25,Years)), 65 | (0.0348, Period(30,Years)) 66 | ] 67 | 68 | 69 | ####################################################################### 70 | ## 2) Date setup 71 | 72 | #if the date is a hol or wknd I then adjust appropriately (advance method) 73 | valuation_date = calendar.advance(valuation_date,0,Days) 74 | 75 | 76 | #figure out and set today's date, use advance to change as necessary.. 77 | #assume that todaysDate = valuation_date 78 | #todays_date = calendar.advance(valuation_date,0,Days) 79 | Settings.instance().evaluationDate = valuation_date 80 | 81 | 82 | ####################################################################### 83 | ## 3) Construct yield term structure 84 | 85 | def getTermStructure(valuation_date, zcQuotes, calendar, payment_convention, day_counter): 86 | 87 | fixing_days = 0 88 | 89 | # Create deposit rate helpers 90 | zcHelpers = [ DepositRateHelper(QuoteHandle(SimpleQuote(r)), 91 | tenor, 92 | fixing_days, 93 | calendar, 94 | payment_convention, 95 | True, 96 | day_counter) 97 | for (r,tenor) in zcQuotes ] 98 | 99 | # Term structure to be used in discounting bond cash flows 100 | return PiecewiseFlatForward(valuation_date, zcHelpers, day_counter) 101 | 102 | 103 | ####################################################################### 104 | ## 4) Setup initial bond 105 | 106 | def getBond( valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure, z_spread = 0): 107 | 108 | #move back a year in order to capture all accrued interest 109 | #may be caught out if there's an irregular coupon payment at beginning 110 | issue_date = calendar.advance(valuation_date,-1,Years) 111 | 112 | #Bond schedule T&Cs 113 | fixedBondSchedule = Schedule( issue_date, 114 | maturity_date, 115 | Period(payment_frequency), 116 | calendar, 117 | Unadjusted, 118 | Unadjusted, 119 | DateGeneration.Backward, 120 | False) 121 | #Bond T&Cs 122 | fixedRateBond = FixedRateBond( 0, 123 | face, 124 | fixedBondSchedule, 125 | [coupon], 126 | bondDiscountingTermStructure.dayCounter(), 127 | payment_convention, 128 | 100, 129 | issue_date) 130 | 131 | #Zero spread needs to be a 'quote handle' object whatever that is 132 | zSpreadQuoteHandle = QuoteHandle( SimpleQuote(z_spread) ) 133 | 134 | discountingTermStructure = RelinkableYieldTermStructureHandle() 135 | discountingTermStructure.linkTo(bondDiscountingTermStructure) 136 | 137 | zSpreadedTermStructure = ZeroSpreadedTermStructure(discountingTermStructure, zSpreadQuoteHandle) 138 | 139 | #Create new relinkable handle for calibrated zero spread 140 | zSpreadRelinkableHandle = RelinkableYieldTermStructureHandle() 141 | 142 | #Link up 143 | zSpreadRelinkableHandle.linkTo(zSpreadedTermStructure) 144 | bondEngine_with_added_zspread = DiscountingBondEngine(zSpreadRelinkableHandle) 145 | 146 | #Set new bond engine 147 | #Ready for use 148 | fixedRateBond.setPricingEngine(bondEngine_with_added_zspread) 149 | 150 | return fixedRateBond 151 | 152 | 153 | ####################################################################### 154 | ## 6) Collate results 155 | 156 | def getResults(fixedRateBond, compounding): 157 | #find yield 158 | yield_rate = fixedRateBond.bondYield(fixedRateBond.dayCounter(),compounding,fixedRateBond.frequency()) 159 | #convert yield to interest rate object 160 | y = InterestRate(yield_rate,fixedRateBond.dayCounter(),compounding,fixedRateBond.frequency()) 161 | 162 | result_duration = BondFunctions.duration(fixedRateBond,y) 163 | result_convexity = BondFunctions.convexity(fixedRateBond,y) 164 | result_bps = BondFunctions.bps(fixedRateBond,y) 165 | result_basis_pt_value = BondFunctions.basisPointValue(fixedRateBond,y) 166 | result_npv = fixedRateBond.NPV() 167 | result_yield_value_bp = BondFunctions.yieldValueBasisPoint(fixedRateBond,y) 168 | result_yield_to_maturity = yield_rate 169 | 170 | print "Duration: ",result_duration 171 | print "Convexity: ",result_convexity 172 | print "Bps: ",result_bps 173 | print "Basis Pt Value: ",result_basis_pt_value 174 | print "NPV: ",result_npv 175 | print "Yield Value Bp: ",result_yield_value_bp 176 | print "Yield to Maturity: ",result_yield_to_maturity 177 | print "Accrued: ",fixedRateBond.accruedAmount() 178 | 179 | 180 | # Handle for the term structure linked to flat forward curve 181 | # I think this is used so that curves can be swapped in and out 182 | # Unsure how to do that yet though 183 | bondDiscountingTermStructure = getTermStructure(valuation_date, zcQuotes, calendar, payment_convention, day_counter) 184 | 185 | fixedRateBond = getBond(valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure) 186 | 187 | ####################################################################### 188 | ## 5) Calibrate and find spread 189 | 190 | z_spread = CashFlows.zSpread( fixedRateBond.cashflows(), 191 | #Assume market value input is quoted clean 192 | market_value + fixedRateBond.accruedAmount(), 193 | bondDiscountingTermStructure, 194 | fixedRateBond.dayCounter(), 195 | compounding, 196 | fixedRateBond.frequency(), 197 | True 198 | ) 199 | 200 | fixedRateBond = getBond(valuation_date, maturity_date, payment_frequency, calendar, face, coupon, payment_convention, bondDiscountingTermStructure, z_spread) 201 | 202 | getResults(fixedRateBond, compounding) 203 | 204 | --------------------------------------------------------------------------------