3
Copyright (C) 2007 Richard Gomes
4
Copyright (C) 2007 Tito Ingargiola
6
This file is part of QuantLib, a free-software/open-source library
7
for financial quantitative analysts and developers - http://quantlib.org/
9
QuantLib is free software: you can redistribute it and/or modify it
10
under the terms of the QuantLib license. You should have received a
11
copy of the license along with this program; if not, please email
12
<quantlib-dev@lists.sf.net>. The license is also available online at
13
<http://quantlib.org/license.shtml>.
15
This program is distributed in the hope that it will be useful, but WITHOUT
16
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
FOR A PARTICULAR PURPOSE. See the license for more details.
22
import org.quantlib.Actual365Fixed;
23
import org.quantlib.AmericanExercise;
24
import org.quantlib.AnalyticEuropeanEngine;
25
import org.quantlib.BaroneAdesiWhaleyEngine;
26
import org.quantlib.BermudanExercise;
27
import org.quantlib.BinomialVanillaEngine;
28
import org.quantlib.BjerksundStenslandEngine;
29
import org.quantlib.BlackConstantVol;
30
import org.quantlib.BlackScholesMertonProcess;
31
import org.quantlib.BlackVolTermStructure;
32
import org.quantlib.BlackVolTermStructureHandle;
33
import org.quantlib.Calendar;
34
import org.quantlib.Date;
35
import org.quantlib.DateVector;
36
import org.quantlib.DayCounter;
37
import org.quantlib.EuropeanExercise;
38
import org.quantlib.Exercise;
39
import org.quantlib.FDAmericanEngine;
40
import org.quantlib.FDBermudanEngine;
41
import org.quantlib.FDEuropeanEngine;
42
import org.quantlib.FlatForward;
43
import org.quantlib.IntegralEngine;
44
import org.quantlib.MCEuropeanEngine;
45
import org.quantlib.Month;
46
import org.quantlib.Option;
47
import org.quantlib.Payoff;
48
import org.quantlib.Period;
49
import org.quantlib.PlainVanillaPayoff;
50
import org.quantlib.Quote;
51
import org.quantlib.QuoteHandle;
52
import org.quantlib.Settings;
53
import org.quantlib.SimpleQuote;
54
import org.quantlib.StochasticProcess;
55
import org.quantlib.TARGET;
56
import org.quantlib.TimeUnit;
57
import org.quantlib.VanillaOption;
58
import org.quantlib.YieldTermStructure;
59
import org.quantlib.YieldTermStructureHandle;
62
* EquityOption Test app - java version of QuantLib/Examples/EquityOption
63
* to illustrate use of Quantlib through supplied SWIG interfaces.
65
* You need to run this with a correctly set library path and something like:
67
* -Djava.library.path=/usr/local/lib
69
* @author Richard Gomes
70
* @author Tito Ingargiola
72
public class EquityOptions {
76
System.loadLibrary("QuantLibJNI");
77
} catch (RuntimeException e) {
82
public static void main(String[] args) throws Exception {
83
long beginTime = System.currentTimeMillis();
86
Option.Type type = Option.Type.Put;
88
double underlying = 36.0;
89
double riskFreeRate = 0.06;
90
double dividendYield = 0.00;
91
double volatility = 0.2;
93
Date todaysDate = new Date(15, Month.May, 1998);
94
Date settlementDate = new Date(17, Month.May, 1998);
95
Settings.instance().setEvaluationDate(todaysDate);
97
Date maturity = new Date(17, Month.May, 1999);
98
DayCounter dayCounter = new Actual365Fixed();
99
Calendar calendar = new TARGET();
101
// write column headings
102
String fmt = "\n%-35s %-14s %-14s %-14s\n";
103
System.out.printf(fmt, "Method", "European", "Bermudan", "American");
104
System.out.println("============================================================================");
107
// define European, Bermudan, and American exercises
108
DateVector exerciseDates = new DateVector();
109
for (int i = 1; i <= 4; i++) {
110
Date forward = settlementDate.add(new Period(3*i, TimeUnit.Months));
111
exerciseDates.add(forward);
113
Exercise europeanExercise = new EuropeanExercise(maturity);
114
Exercise bermudanExercise = new BermudanExercise(exerciseDates);
115
Exercise americanExercise = new AmericanExercise(settlementDate,
119
// define the underlying asset and the yield/dividend/volatility curves
120
QuoteHandle underlyingH = new QuoteHandle(new SimpleQuote(underlying));
121
YieldTermStructureHandle flatTermStructure =
122
new YieldTermStructureHandle(new FlatForward(
123
settlementDate, riskFreeRate, dayCounter));
124
YieldTermStructureHandle flatDividendYield =
125
new YieldTermStructureHandle(new FlatForward(
126
settlementDate, dividendYield, dayCounter));
127
BlackVolTermStructureHandle flatVolatility =
128
new BlackVolTermStructureHandle(new BlackConstantVol(
129
settlementDate, calendar, volatility, dayCounter));
131
BlackScholesMertonProcess stochasticProcess =
132
new BlackScholesMertonProcess(underlyingH,
138
Payoff payoff = new PlainVanillaPayoff(type, strike);
140
VanillaOption europeanOption =
141
new VanillaOption(payoff, europeanExercise);
142
VanillaOption bermudanOption =
143
new VanillaOption(payoff, bermudanExercise);
144
VanillaOption americanOption =
145
new VanillaOption(payoff, americanExercise);
147
fmt = "%34s %13.9f %13.9f %13.9f\n";
149
// Analytic formulas:
151
// Black-Scholes for European
152
String method = "Black-Scholes";
153
europeanOption.setPricingEngine(
154
new AnalyticEuropeanEngine(stochasticProcess));
155
System.out.printf(fmt, new Object[] { method,
156
europeanOption.NPV(),
160
// Barone-Adesi and Whaley approximation for American
161
method = "Barone-Adesi/Whaley";
162
americanOption.setPricingEngine(
163
new BaroneAdesiWhaleyEngine(stochasticProcess));
164
System.out.printf(fmt, new Object[] { method,
167
americanOption.NPV() } );
169
// Bjerksund and Stensland approximation for American
170
method = "Bjerksund/Stensland";
171
americanOption.setPricingEngine(
172
new BjerksundStenslandEngine(stochasticProcess));
173
System.out.printf(fmt, new Object[] { method,
176
americanOption.NPV() } );
180
europeanOption.setPricingEngine(new IntegralEngine(stochasticProcess));
181
System.out.printf(fmt, new Object[] { method, europeanOption.NPV(),
182
Double.NaN, Double.NaN } );
184
// Finite differences
186
method = "Finite differences";
187
europeanOption.setPricingEngine(new FDEuropeanEngine(stochasticProcess,
190
bermudanOption.setPricingEngine(new FDBermudanEngine(stochasticProcess,
193
americanOption.setPricingEngine(new FDAmericanEngine(stochasticProcess,
196
System.out.printf(fmt, new Object[] { method,
197
europeanOption.NPV(),
198
bermudanOption.NPV(),
199
americanOption.NPV() });
202
method = "Binomial Jarrow-Rudd";
203
europeanOption.setPricingEngine(
204
new BinomialVanillaEngine(stochasticProcess,
205
"JarrowRudd", timeSteps));
206
bermudanOption.setPricingEngine(new BinomialVanillaEngine(
208
"JarrowRudd", timeSteps));
209
americanOption.setPricingEngine(new BinomialVanillaEngine(
211
"JarrowRudd", timeSteps));
212
System.out.printf(fmt, new Object[] { method,
213
europeanOption.NPV(),
214
bermudanOption.NPV(),
215
americanOption.NPV() } );
217
method = "Binomial Cox-Ross-Rubinstein";
218
europeanOption.setPricingEngine(
219
new BinomialVanillaEngine(stochasticProcess,
220
"CoxRossRubinstein", timeSteps));
221
bermudanOption.setPricingEngine(
222
new BinomialVanillaEngine(stochasticProcess,
223
"CoxRossRubinstein", timeSteps));
224
americanOption.setPricingEngine(
225
new BinomialVanillaEngine(stochasticProcess,
226
"CoxRossRubinstein", timeSteps));
227
System.out.printf(fmt, new Object[] { method,
228
europeanOption.NPV(),
229
bermudanOption.NPV(),
230
americanOption.NPV() } );
232
method = "Additive equiprobabilities";
233
europeanOption.setPricingEngine(
234
new BinomialVanillaEngine(stochasticProcess,
235
"AdditiveEQPBinomialTree", timeSteps));
236
bermudanOption.setPricingEngine(
237
new BinomialVanillaEngine(stochasticProcess,
238
"AdditiveEQPBinomialTree", timeSteps));
239
americanOption.setPricingEngine(
240
new BinomialVanillaEngine(stochasticProcess,
241
"AdditiveEQPBinomialTree", timeSteps));
242
System.out.printf(fmt, new Object[] { method,
243
europeanOption.NPV(),
244
bermudanOption.NPV(),
245
americanOption.NPV() } );
247
method = "Binomial Trigeorgis";
248
europeanOption.setPricingEngine(
249
new BinomialVanillaEngine(stochasticProcess,
250
"Trigeorgis", timeSteps));
251
bermudanOption.setPricingEngine(
252
new BinomialVanillaEngine(stochasticProcess,
253
"Trigeorgis", timeSteps));
254
americanOption.setPricingEngine(
255
new BinomialVanillaEngine(stochasticProcess,
256
"Trigeorgis", timeSteps));
257
System.out.printf(fmt, new Object[] { method,
258
europeanOption.NPV(),
259
bermudanOption.NPV(),
260
americanOption.NPV() } );
262
method = "Binomial Tian";
263
europeanOption.setPricingEngine(
264
new BinomialVanillaEngine(stochasticProcess,
266
bermudanOption.setPricingEngine(
267
new BinomialVanillaEngine(stochasticProcess,
269
americanOption.setPricingEngine(
270
new BinomialVanillaEngine(stochasticProcess,
272
System.out.printf(fmt, new Object[] { method,
273
europeanOption.NPV(),
274
bermudanOption.NPV(),
275
americanOption.NPV() } );
277
method = "Binomial Leisen-Reimer";
278
europeanOption.setPricingEngine(
279
new BinomialVanillaEngine(stochasticProcess,
280
"LeisenReimer", timeSteps));
281
bermudanOption.setPricingEngine(
282
new BinomialVanillaEngine(stochasticProcess,
283
"LeisenReimer", timeSteps));
284
americanOption.setPricingEngine(
285
new BinomialVanillaEngine(stochasticProcess,
286
"LeisenReimer", timeSteps));
287
System.out.printf(fmt, new Object[] { method,
288
europeanOption.NPV(),
289
bermudanOption.NPV(),
290
americanOption.NPV() } );
292
method = "Binomial Joshi";
293
europeanOption.setPricingEngine(
294
new BinomialVanillaEngine(stochasticProcess,
295
"Joshi4", timeSteps));
296
bermudanOption.setPricingEngine(
297
new BinomialVanillaEngine(stochasticProcess,
298
"Joshi4", timeSteps));
299
americanOption.setPricingEngine(
300
new BinomialVanillaEngine(stochasticProcess,
301
"Joshi4", timeSteps));
302
System.out.printf(fmt, new Object[] { method,
303
europeanOption.NPV(),
304
bermudanOption.NPV(),
305
americanOption.NPV() } );
308
// Monte Carlo Method
311
int nSamples = 32768; // 2^15
312
int maxSamples = 1048576; // 2^20
314
method = "MC (crude)";
315
europeanOption.setPricingEngine(
316
new MCEuropeanEngine(stochasticProcess,
317
"PseudoRandom", timeSteps, 252,
319
nSamples, 0.02, maxSamples, mcSeed));
320
System.out.printf(fmt, new Object[] { method,
321
europeanOption.NPV(),
325
method = "MC (Sobol)";
326
europeanOption.setPricingEngine(
327
new MCEuropeanEngine(stochasticProcess,
328
"LowDiscrepancy", timeSteps, 252,
330
nSamples, 0.02, maxSamples, mcSeed));
331
System.out.printf(fmt, new Object[] { method,
332
europeanOption.NPV(),
338
method = "MC (Longstaff Schwartz)";
339
// This is the original C++ code:
340
// MakeMCAmericanEngine<PseudoRandom>().withSteps(100)
341
// .withAntitheticVariate()
342
// .withCalibrationSamples(4096)
343
// .withTolerance(0.02)
344
// .withSeed(mcSeed);
346
System.out.printf(fmt, new Object[] { method,
349
americanOption.NPV() });
352
long msecs = (System.currentTimeMillis()-beginTime);
353
System.out.println("Run completed in "+msecs+" ms.");