2020NPV of the American Option without dividend: 17.9647
2121
2222"""
23- from __future__ import print_function
24-
2523from quantlib .settings import Settings
2624from quantlib .compounding import Simple
25+ from quantlib .cashflows .dividend import DividendSchedule
2726from quantlib .currency .api import USDCurrency
2827from quantlib .indexes .api import Libor
2928from quantlib .indexes .swap_index import SwapIndex
30- from quantlib .instruments .option import EuropeanExercise , AmericanExercise
31- from quantlib .instruments .option import VanillaOption , DividendVanillaOption , Call
29+ from quantlib .instruments .exercise import EuropeanExercise , AmericanExercise
30+ from quantlib .instruments .option import VanillaOption , VanillaOption , OptionType
3231from quantlib .instruments .payoffs import PlainVanillaPayoff
32+ from quantlib .math .interpolation import Linear
3333from quantlib .pricingengines .api import AnalyticDividendEuropeanEngine
34- from quantlib .pricingengines .api import FDDividendAmericanEngine
34+ from quantlib .pricingengines .api import FdBlackScholesVanillaEngine
3535from quantlib .pricingengines .api import AnalyticEuropeanEngine
36- from quantlib .pricingengines .api import FDAmericanEngine
3736from quantlib .processes .black_scholes_process import BlackScholesProcess
3837from quantlib .quotes import SimpleQuote
3938from quantlib .time .api import (
40- Date , Days , Period , Actual360 , Months , Jan , ModifiedFollowing , Years , Feb
39+ Date , Days , Period , Actual360 , Months , Jan , ModifiedFollowing , Years , Feb , pydate_from_qldate
4140)
41+ from quantlib .methods .finitedifferences .solvers .fdmbackwardsolver import FdmSchemeDesc
4242from quantlib .time .calendars .united_states import UnitedStates
4343from quantlib .termstructures .yields .api import (
44- PiecewiseYieldCurve , DepositRateHelper , Interpolator , BootstrapTrait
44+ PiecewiseYieldCurve , DepositRateHelper , BootstrapTrait , HandleYieldTermStructure
4545)
46- from quantlib .termstructures .volatility .equityfx . black_vol_term_structure import BlackConstantVol
46+ from quantlib .termstructures .volatility .api import BlackConstantVol
4747from quantlib .termstructures .yields .api import SwapRateHelper
4848
4949def dividendOption ():
@@ -61,7 +61,7 @@ def dividendOption():
6161 todaysDate , period = Period (settlement_days , Days )
6262 )
6363 dayCounter = Actual360 () # INPUT
64- currency = USDCurrency () # INPUT
64+ currency = USDCurrency () # INPUT
6565
6666 print ("Date of the evaluation: " , todaysDate )
6767 print ("Calendar used: " , calendar .name )
@@ -88,28 +88,28 @@ def dividendOption():
8888
8989 # We suppose the vol constant : his term structure is flat --> BlackConstantVol object
9090 flatVolTS = BlackConstantVol (settlementDate , calendar , underlying_vol , dayCounter )
91-
91+
9292 # ++++++++++++++++++++ Description of Yield Term Structure
93-
94- # Libor data record
93+
94+ # Libor data record
9595 print ("**********************************" )
96- print ("Description of the Libor used for the Yield Curve construction" )
97-
96+ print ("Description of the Libor used for the Yield Curve construction" )
97+
9898 Libor_dayCounter = Actual360 ();
9999
100100 liborRates = []
101101 liborRatesTenor = []
102102 # INPUT : all the following data are input : the rate and the corresponding tenor
103103 # You could make the choice of more or less data
104104 # --> However you have tho choice the instruments with different maturities
105- liborRates = [ 0.002763 , 0.004082 , 0.005601 , 0.006390 , 0.007125 , 0.007928 , 0.009446 ,
105+ liborRates = [ 0.002763 , 0.004082 , 0.005601 , 0.006390 , 0.007125 , 0.007928 , 0.009446 ,
106106 0.01110 ]
107107 liborRatesTenor = [Period (tenor , Months ) for tenor in [1 ,2 ,3 ,4 ,5 ,6 ,9 ,12 ]]
108-
108+
109109 for tenor , rate in zip (liborRatesTenor , liborRates ):
110110 print (tenor , "\t \t \t " , rate )
111111
112- # Swap data record
112+ # Swap data record
113113
114114 # description of the fixed leg of the swap
115115 Swap_fixedLegTenor = Period (12 , Months ) # INPUT
@@ -134,19 +134,19 @@ def dividendOption():
134134 swapRates = [0.005681 , 0.006970 , 0.009310 , 0.012010 , 0.014628 , 0.016881 , 0.018745 ,
135135 0.020260 , 0.021545 ]
136136 swapRatesTenor = [Period (i , Years ) for i in range (2 , 11 )]
137-
137+
138138 for tenor , rate in zip (swapRatesTenor , swapRates ):
139139 print (tenor , "\t \t \t " , rate )
140-
140+
141141 # ++++++++++++++++++++ Creation of the vector of RateHelper (need for the Yield Curve construction)
142- # ++++++++++++++++++++ Libor
142+ # ++++++++++++++++++++ Libor
143143 LiborFamilyName = currency .name + "Libor"
144144 instruments = []
145145 for rate , tenor in zip (liborRates , liborRatesTenor ):
146146 # Index description ___ creation of a Libor index
147147 liborIndex = Libor (LiborFamilyName , tenor , settlement_days , currency , calendar ,
148148 Libor_dayCounter )
149- # Initialize rate helper ___ the DepositRateHelper link the recording rate with the Libor index
149+ # Initialize rate helper ___ the DepositRateHelper link the recording rate with the Libor index
150150 instruments .append (DepositRateHelper (rate , index = liborIndex ))
151151
152152 # +++++++++++++++++++++ Swap
@@ -158,39 +158,38 @@ def dividendOption():
158158 Swap_iborIndex )
159159 # Initialize rate helper __ the SwapRateHelper links the swap index width his rate
160160 instruments .append (SwapRateHelper .from_index (rate , swapIndex ))
161-
161+
162162 # ++++++++++++++++++ Now the creation of the yield curve
163163
164- riskFreeTS = PiecewiseYieldCurve .from_reference_date (BootstrapTrait .ZeroYield ,
165- Interpolator .Linear , settlementDate , instruments , dayCounter )
164+ riskFreeTS = PiecewiseYieldCurve [BootstrapTrait .ZeroYield , Linear ].from_reference_date (settlementDate , instruments , dayCounter )
166165
167166
168- # ++++++++++++++++++ build of the underlying process : with a Black-Scholes model
167+ # ++++++++++++++++++ build of the underlying process : with a Black-Scholes model
169168
170169 print ('Creating process' )
171170
172- bsProcess = BlackScholesProcess (underlying_priceH , riskFreeTS , flatVolTS )
171+ bsProcess = BlackScholesProcess (underlying_priceH , HandleYieldTermStructure ( riskFreeTS ) , flatVolTS )
173172
174173
175174 # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
176175 # ++++++++++++++++++++ Description of the option +++++++++++++++++++++++++++++++++++++++
177176 # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
178-
177+
179178 Option_name = "IBM Option"
180179 maturity = Date (26 , Jan , 2013 )
181180 strike = 190
182- option_type = Call
181+ option_type = OptionType . Call
183182
184183 # Here, as an implementation example, we make the test with borth american and european exercise
185184 europeanExercise = EuropeanExercise (maturity )
186185 # The emericanExercise need also the settlement date, as his right to exerce the buy or call start at the settlement date!
187186 #americanExercise = AmericanExercise(settlementDate, maturity)
188187 americanExercise = AmericanExercise (maturity , settlementDate )
189-
188+
190189 print ("**********************************" )
191190 print ("Description of the option: " , Option_name )
192191 print ("Date of maturity: " , maturity )
193- print ("Type of the option: " , option_type )
192+ print ("Type of the option: " , option_type . name )
194193 print ("Strike of the option: " , strike )
195194
196195
@@ -199,7 +198,7 @@ def dividendOption():
199198 # INPUT You have to determine the frequence and rates of the discrete dividend. Here is a sollution, but she's not the only one.
200199 # Last know dividend:
201200 dividend = 0.75 #//0.75
202- next_dividend_date = Date (10 ,Feb ,2012 )
201+ next_dividend_date = Date (10 , Feb , 2012 )
203202 # HERE we have make the assumption that the dividend will grow with the quarterly croissance:
204203 dividendCroissance = 1.03
205204 dividendfrequence = Period (3 , Months )
@@ -209,26 +208,24 @@ def dividendOption():
209208
210209 d = next_dividend_date
211210 while d <= maturity :
212- dividendDates .append (d )
211+ dividendDates .append (pydate_from_qldate ( d ) )
213212 dividends .append (dividend )
214- d = d + dividendfrequence
213+ d += dividendfrequence
215214 dividend *= dividendCroissance
216215
217216 print ("Discrete dividends " )
218217 print ("Dates Dividends " )
219218 for date , div in zip (dividendDates , dividends ):
220219 print (date , " " , div )
221220
222- # ++++++++++++++++++ Description of the final payoff
221+ # ++++++++++++++++++ Description of the final payoff
223222 payoff = PlainVanillaPayoff (option_type , strike )
224223
225224 # ++++++++++++++++++ The OPTIONS : (American and European) with their dividends description:
226- dividendEuropeanOption = DividendVanillaOption (
227- payoff , europeanExercise , dividendDates , dividends
228- )
229- dividendAmericanOption = DividendVanillaOption (
230- payoff , americanExercise , dividendDates , dividends
231- )
225+ dividendEuropeanOption = VanillaOption (
226+ payoff , europeanExercise )
227+ dividendAmericanOption = VanillaOption (
228+ payoff , americanExercise )
232229
233230
234231 # just too test
@@ -238,33 +235,33 @@ def dividendOption():
238235 # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
239236 # ++++++++++++++++++++ Description of the pricing +++++++++++++++++++++++++++++++++++++
240237 # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
241-
238+
242239 # For the european options we have a closed analytic formula: The Black Scholes:
243- dividendEuropeanEngine = AnalyticDividendEuropeanEngine (bsProcess )
240+ dividendEuropeanEngine = AnalyticDividendEuropeanEngine (bsProcess , DividendSchedule ( dividendDates , dividends ) )
244241
245242 # For the american option we have make the choice of the finite difference model with the CrankNicolson scheme
246243 # this model need to precise the time and space step
247244 # More they are greater, more the calul will be precise.
248245 americanGirdPoints = 600
249246 americanTimeSteps = 600
250- dividendAmericanEngine = FDDividendAmericanEngine ( 'CrankNicolson' , bsProcess ,americanTimeSteps , americanGirdPoints )
247+ dividendAmericanEngine = FdBlackScholesVanillaEngine ( bsProcess , americanTimeSteps , americanGirdPoints , scheme = FdmSchemeDesc . CrankNicolson (), dividends = DividendSchedule ( dividendDates , dividends ) )
251248
252249 # just to test
253250 europeanEngine = AnalyticEuropeanEngine (bsProcess )
254- americanEngine = FDAmericanEngine ( 'CrankNicolson' , bsProcess ,americanTimeSteps , americanGirdPoints )
251+ americanEngine = FdBlackScholesVanillaEngine ( bsProcess , americanTimeSteps , americanGirdPoints , scheme = FdmSchemeDesc . CrankNicolson () )
255252
256253
257254 # ++++++++++++++++++++ Valorisation ++++++++++++++++++++++++++++++++++++++++
258-
255+
259256 # Link the pricing Engine to the option
260257 dividendEuropeanOption .set_pricing_engine (dividendEuropeanEngine )
261258 dividendAmericanOption .set_pricing_engine (dividendAmericanEngine )
262-
259+
263260 # just to test
264261 europeanOption .set_pricing_engine (europeanEngine )
265262 americanOption .set_pricing_engine (americanEngine )
266263
267- # Now we make all the needing calcul
264+ # Now we make all the needing calcul
268265 # ... and final results
269266 print ("NPV of the European Option with discrete dividends=0: {:.4f}" .format (dividendEuropeanOption .npv ))
270267 print ("NPV of the European Option without dividend: {:.4f}" .format (europeanOption .npv ))
@@ -279,4 +276,3 @@ def dividendOption():
279276if __name__ == '__main__' :
280277
281278 dividendOption ()
282-
0 commit comments