├── 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 |
--------------------------------------------------------------------------------