Skip to content

Commit 03f3efd

Browse files
committed
Support time to expiry or maturity date in AmericanOption
1 parent 6a9ae85 commit 03f3efd

File tree

8 files changed

+62
-53
lines changed

8 files changed

+62
-53
lines changed

ChangeLog

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
2026-03-09 Dirk Eddelbuettel <edd@debian.org>
22

3-
* src/vanilla.cpp (europeanOptionEngine): More careful about use of evaluation date,
4-
new parameter daycounter
5-
* R/option.R (EuropeanOption.default): Allow fractional year to
6-
expiry as well as date, support daycounter
7-
* man/EuropeanOption.Rd: Updated
3+
* src/vanilla.cpp (europeanOptionEngine,americanOptionEngine): More
4+
careful about use of evaluation date, new parameter daycounter
5+
* R/option.R (EuropeanOption.default,AmericanOption.default): Allow
6+
fractional year to expiry as well as date, support daycounter
7+
* man/AmericanOption.Rd: Updated
8+
* man/EuropeanOption.Rd: Idem
89
* inst/include/RQuantLib_RcppExports.h: Regenerated
910
* src/RcppExports.cpp: Idem
1011
* R/RcppExports.R: Idem

R/RcppExports.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ europeanOptionEngine <- function(type, underlying, strike, dividendYield, riskFr
232232
.Call(`_RQuantLib_europeanOptionEngine`, type, underlying, strike, dividendYield, riskFreeRate, maturity, exDate, volatility, discreteDividends, discreteDividendsTimeUntil, dayCounter)
233233
}
234234

235-
americanOptionEngine <- function(type, underlying, strike, dividendYield, riskFreeRate, maturity, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil) {
236-
.Call(`_RQuantLib_americanOptionEngine`, type, underlying, strike, dividendYield, riskFreeRate, maturity, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil)
235+
americanOptionEngine <- function(type, underlying, strike, dividendYield, riskFreeRate, maturity, exDate, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil, dayCounter) {
236+
.Call(`_RQuantLib_americanOptionEngine`, type, underlying, strike, dividendYield, riskFreeRate, maturity, exDate, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil, dayCounter)
237237
}
238238

239239
europeanOptionArraysEngine <- function(type, par) {

R/option.R

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,24 @@ EuropeanOption.default <- function(type, underlying, strike, dividendYield,
3939

4040
AmericanOption <- function(type, underlying, strike, dividendYield,
4141
riskFreeRate, maturity, volatility,
42-
timeSteps=150, gridPoints=149,
43-
engine="BaroneAdesiWhaley",
44-
discreteDividends = NULL, discreteDividendsTimeUntil = NULL) {
42+
timeSteps=150, gridPoints=149, engine="BaroneAdesiWhaley",
43+
discreteDividends = NULL, discreteDividendsTimeUntil = NULL,
44+
dayCounter = 0) {
4545
UseMethod("AmericanOption")
4646
}
4747

4848
AmericanOption.default <- function(type, underlying, strike, dividendYield,
4949
riskFreeRate, maturity, volatility,
50-
timeSteps=150, gridPoints=149,
51-
engine="BaroneAdesiWhaley",
52-
discreteDividends = NULL, discreteDividendsTimeUntil = NULL) {
50+
timeSteps=150, gridPoints=149, engine="BaroneAdesiWhaley",
51+
discreteDividends = NULL, discreteDividendsTimeUntil = NULL,
52+
dayCounter = 0) {
5353
type <- match.arg(type, c("call", "put"))
5454
engine <- match.arg(engine, c("BaroneAdesiWhaley", "CrankNicolson"))
55-
val <- americanOptionEngine(type, underlying, strike, dividendYield,
56-
riskFreeRate, maturity, volatility,
57-
timeSteps, gridPoints, engine,
58-
discreteDividends, discreteDividendsTimeUntil)
55+
val <- americanOptionEngine(type, underlying, strike, dividendYield, riskFreeRate,
56+
if (inherits(maturity, "numeric")) maturity else NULL,
57+
if (inherits(maturity, "Date")) maturity else NULL,
58+
volatility, timeSteps, gridPoints, engine,
59+
discreteDividends, discreteDividendsTimeUntil, dayCounter)
5960
class(val) <- c("AmericanOption","Option")
6061
val
6162
}

inst/include/RQuantLib_RcppExports.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,17 +612,17 @@ namespace RQuantLib {
612612
return Rcpp::as<Rcpp::List >(rcpp_result_gen);
613613
}
614614

615-
inline Rcpp::List americanOptionEngine(std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, int timeSteps, int gridPoints, std::string engine, Rcpp::Nullable<Rcpp::NumericVector> discreteDividends, Rcpp::Nullable<Rcpp::NumericVector> discreteDividendsTimeUntil) {
616-
typedef SEXP(*Ptr_americanOptionEngine)(SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP);
615+
inline Rcpp::List americanOptionEngine(std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, Rcpp::Nullable<double> maturity, Rcpp::Nullable<QuantLib::Date> exDate, double volatility, int timeSteps, int gridPoints, std::string engine, Rcpp::Nullable<Rcpp::NumericVector> discreteDividends, Rcpp::Nullable<Rcpp::NumericVector> discreteDividendsTimeUntil, int dayCounter) {
616+
typedef SEXP(*Ptr_americanOptionEngine)(SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP,SEXP);
617617
static Ptr_americanOptionEngine p_americanOptionEngine = NULL;
618618
if (p_americanOptionEngine == NULL) {
619-
validateSignature("Rcpp::List(*americanOptionEngine)(std::string,double,double,double,double,double,double,int,int,std::string,Rcpp::Nullable<Rcpp::NumericVector>,Rcpp::Nullable<Rcpp::NumericVector>)");
619+
validateSignature("Rcpp::List(*americanOptionEngine)(std::string,double,double,double,double,Rcpp::Nullable<double>,Rcpp::Nullable<QuantLib::Date>,double,int,int,std::string,Rcpp::Nullable<Rcpp::NumericVector>,Rcpp::Nullable<Rcpp::NumericVector>,int)");
620620
p_americanOptionEngine = (Ptr_americanOptionEngine)R_GetCCallable("RQuantLib", "_RQuantLib_americanOptionEngine");
621621
}
622622
RObject rcpp_result_gen;
623623
{
624624
RNGScope RCPP_rngScope_gen;
625-
rcpp_result_gen = p_americanOptionEngine(Shield<SEXP>(Rcpp::wrap(type)), Shield<SEXP>(Rcpp::wrap(underlying)), Shield<SEXP>(Rcpp::wrap(strike)), Shield<SEXP>(Rcpp::wrap(dividendYield)), Shield<SEXP>(Rcpp::wrap(riskFreeRate)), Shield<SEXP>(Rcpp::wrap(maturity)), Shield<SEXP>(Rcpp::wrap(volatility)), Shield<SEXP>(Rcpp::wrap(timeSteps)), Shield<SEXP>(Rcpp::wrap(gridPoints)), Shield<SEXP>(Rcpp::wrap(engine)), Shield<SEXP>(Rcpp::wrap(discreteDividends)), Shield<SEXP>(Rcpp::wrap(discreteDividendsTimeUntil)));
625+
rcpp_result_gen = p_americanOptionEngine(Shield<SEXP>(Rcpp::wrap(type)), Shield<SEXP>(Rcpp::wrap(underlying)), Shield<SEXP>(Rcpp::wrap(strike)), Shield<SEXP>(Rcpp::wrap(dividendYield)), Shield<SEXP>(Rcpp::wrap(riskFreeRate)), Shield<SEXP>(Rcpp::wrap(maturity)), Shield<SEXP>(Rcpp::wrap(exDate)), Shield<SEXP>(Rcpp::wrap(volatility)), Shield<SEXP>(Rcpp::wrap(timeSteps)), Shield<SEXP>(Rcpp::wrap(gridPoints)), Shield<SEXP>(Rcpp::wrap(engine)), Shield<SEXP>(Rcpp::wrap(discreteDividends)), Shield<SEXP>(Rcpp::wrap(discreteDividendsTimeUntil)), Shield<SEXP>(Rcpp::wrap(dayCounter)));
626626
}
627627
if (rcpp_result_gen.inherits("interrupted-error"))
628628
throw Rcpp::internal::InterruptedException();

man/AmericanOption.Rd

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ using finite differences. The option value as well as the common first
88
derivatives ("Greeks") are returned.}
99
\usage{
1010
\method{AmericanOption}{default}(type, underlying, strike,
11-
dividendYield, riskFreeRate, maturity, volatility,
12-
timeSteps=150, gridPoints=149, engine="BaroneAdesiWhaley",
13-
discreteDividends, discreteDividendsTimeUntil)
11+
dividendYield, riskFreeRate, maturity, volatility,
12+
timeSteps=150, gridPoints=149, engine="BaroneAdesiWhaley",
13+
discreteDividends, discreteDividendsTimeUntil, dayCounter)
1414
}
1515
\arguments{
1616
\item{type}{A string with one of the values \code{call} or \code{put}}
1717
\item{underlying}{Current price of the underlying stock}
1818
\item{strike}{Strike price of the option}
1919
\item{dividendYield}{Continuous dividend yield (as a fraction) of the stock}
2020
\item{riskFreeRate}{Risk-free rate}
21-
\item{maturity}{Time to maturity (in fractional years)}
21+
\item{maturity}{Time to maturity in either fractional years or as a
22+
\sQuote{Date} object specifying the expiry date)}
2223
\item{volatility}{Volatility of the underlying stock}
2324
\item{timeSteps}{Time steps for the \dQuote{CrankNicolson} finite
2425
differences method engine, default value is 150}
@@ -27,18 +28,20 @@ derivatives ("Greeks") are returned.}
2728
\item{engine}{String selecting pricing engine, currently supported are
2829
\dQuote{BaroneAdesiWhaley} and \dQuote{CrankNicolson}}
2930
\item{discreteDividends}{Vector of discrete dividends (optional)}
30-
\item{discreteDividendsTimeUntil}{Vector of times to discrete dividends
31+
\item{discreteDividendsTimeUntil}{Vector of times to discrete dividends
3132
(in fractional years, optional)}
33+
\item{dayCounter}{Integer denoting the selected QuantLib day counter
34+
convention, default value is 0 for \sQuote{Actual360}}
3235
}
3336
\value{
3437
An object of class \code{AmericanOption} (which inherits from class
3538
\code{\link{Option}}) is returned. It contains a list with the
36-
following components:
39+
following components:
3740
\item{value}{Value of option}
3841
\item{delta}{Sensitivity of the option value for a change in the underlying}
3942
\item{gamma}{Sensitivity of the option delta for a change in the underlying}
4043
\item{vega}{Sensitivity of the option value for a change in the
41-
underlying's volatility}
44+
underlying's volatility}
4245
\item{theta}{Sensitivity of the option value for a change in t, the
4346
remaining time to maturity}
4447
\item{rho}{Sensitivity of the option value for a change in the
@@ -51,16 +54,16 @@ derivatives ("Greeks") are returned.}
5154
\dQuote{CrankNicolson} is selected, then at least delta, gamma and
5255
vega are available. With the default pricing engine of
5356
\dQuote{BaroneAdesiWhaley}, no greeks are returned.
54-
57+
5558
The \dQuote{CrankNicolson} engine needs to be used when setting
5659
discrete dividends.
5760
}
5861
\details{
5962
The Finite Differences method is used to value the American Option.
60-
63+
6164
Please see any decent Finance textbook for background reading, and
6265
the \code{QuantLib} documentation for details on the \code{QuantLib}
63-
implementation.
66+
implementation.
6467
}
6568
\references{\url{https://www.quantlib.org/} for details on \code{QuantLib}.}
6669
\author{Dirk Eddelbuettel \email{edd@debian.org} for the \R interface;
@@ -78,4 +81,3 @@ AmericanOption("put", strike=100, volatility=0.4, 100, 0.02, 0.03, 0.5)
7881
AmericanOption("put", strike=100, volatility=0.4, 100, 0.02, 0.03, 0.5, engine="CrankNicolson")
7982
}
8083
\keyword{misc}
81-

man/EuropeanOption.Rd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
\item{strike}{Strike price of the option}
2020
\item{dividendYield}{Continuous dividend yield (as a fraction) of the stock}
2121
\item{riskFreeRate}{Risk-free rate}
22-
\item{maturity}{Time to maturity (in fractional years)}
22+
\item{maturity}{Time to maturity in either fractional years or as a
23+
\sQuote{Date} object specifying the expiry date)}
2324
\item{volatility}{Volatility of the underlying stock}
2425
\item{discreteDividends}{Vector of discrete dividends (optional)}
2526
\item{discreteDividendsTimeUntil}{Vector of times to discrete dividends
2627
(in fractional years, optional)}
2728
\item{dayCounter}{Integer denoting the selected QuantLib day counter
28-
convention, default value is 0 for \sQuote{Actual360}}}
29+
convention, default value is 0 for \sQuote{Actual360}}
30+
}
2931
\value{
3032
The \code{EuropeanOption} function returns an object of class
3133
\code{EuropeanOption} (which inherits from class

src/RcppExports.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,31 +1521,33 @@ RcppExport SEXP _RQuantLib_europeanOptionEngine(SEXP typeSEXP, SEXP underlyingSE
15211521
return rcpp_result_gen;
15221522
}
15231523
// americanOptionEngine
1524-
Rcpp::List americanOptionEngine(std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, int timeSteps, int gridPoints, std::string engine, Rcpp::Nullable<Rcpp::NumericVector> discreteDividends, Rcpp::Nullable<Rcpp::NumericVector> discreteDividendsTimeUntil);
1525-
static SEXP _RQuantLib_americanOptionEngine_try(SEXP typeSEXP, SEXP underlyingSEXP, SEXP strikeSEXP, SEXP dividendYieldSEXP, SEXP riskFreeRateSEXP, SEXP maturitySEXP, SEXP volatilitySEXP, SEXP timeStepsSEXP, SEXP gridPointsSEXP, SEXP engineSEXP, SEXP discreteDividendsSEXP, SEXP discreteDividendsTimeUntilSEXP) {
1524+
Rcpp::List americanOptionEngine(std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, Rcpp::Nullable<double> maturity, Rcpp::Nullable<QuantLib::Date> exDate, double volatility, int timeSteps, int gridPoints, std::string engine, Rcpp::Nullable<Rcpp::NumericVector> discreteDividends, Rcpp::Nullable<Rcpp::NumericVector> discreteDividendsTimeUntil, int dayCounter);
1525+
static SEXP _RQuantLib_americanOptionEngine_try(SEXP typeSEXP, SEXP underlyingSEXP, SEXP strikeSEXP, SEXP dividendYieldSEXP, SEXP riskFreeRateSEXP, SEXP maturitySEXP, SEXP exDateSEXP, SEXP volatilitySEXP, SEXP timeStepsSEXP, SEXP gridPointsSEXP, SEXP engineSEXP, SEXP discreteDividendsSEXP, SEXP discreteDividendsTimeUntilSEXP, SEXP dayCounterSEXP) {
15261526
BEGIN_RCPP
15271527
Rcpp::RObject rcpp_result_gen;
15281528
Rcpp::traits::input_parameter< std::string >::type type(typeSEXP);
15291529
Rcpp::traits::input_parameter< double >::type underlying(underlyingSEXP);
15301530
Rcpp::traits::input_parameter< double >::type strike(strikeSEXP);
15311531
Rcpp::traits::input_parameter< double >::type dividendYield(dividendYieldSEXP);
15321532
Rcpp::traits::input_parameter< double >::type riskFreeRate(riskFreeRateSEXP);
1533-
Rcpp::traits::input_parameter< double >::type maturity(maturitySEXP);
1533+
Rcpp::traits::input_parameter< Rcpp::Nullable<double> >::type maturity(maturitySEXP);
1534+
Rcpp::traits::input_parameter< Rcpp::Nullable<QuantLib::Date> >::type exDate(exDateSEXP);
15341535
Rcpp::traits::input_parameter< double >::type volatility(volatilitySEXP);
15351536
Rcpp::traits::input_parameter< int >::type timeSteps(timeStepsSEXP);
15361537
Rcpp::traits::input_parameter< int >::type gridPoints(gridPointsSEXP);
15371538
Rcpp::traits::input_parameter< std::string >::type engine(engineSEXP);
15381539
Rcpp::traits::input_parameter< Rcpp::Nullable<Rcpp::NumericVector> >::type discreteDividends(discreteDividendsSEXP);
15391540
Rcpp::traits::input_parameter< Rcpp::Nullable<Rcpp::NumericVector> >::type discreteDividendsTimeUntil(discreteDividendsTimeUntilSEXP);
1540-
rcpp_result_gen = Rcpp::wrap(americanOptionEngine(type, underlying, strike, dividendYield, riskFreeRate, maturity, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil));
1541+
Rcpp::traits::input_parameter< int >::type dayCounter(dayCounterSEXP);
1542+
rcpp_result_gen = Rcpp::wrap(americanOptionEngine(type, underlying, strike, dividendYield, riskFreeRate, maturity, exDate, volatility, timeSteps, gridPoints, engine, discreteDividends, discreteDividendsTimeUntil, dayCounter));
15411543
return rcpp_result_gen;
15421544
END_RCPP_RETURN_ERROR
15431545
}
1544-
RcppExport SEXP _RQuantLib_americanOptionEngine(SEXP typeSEXP, SEXP underlyingSEXP, SEXP strikeSEXP, SEXP dividendYieldSEXP, SEXP riskFreeRateSEXP, SEXP maturitySEXP, SEXP volatilitySEXP, SEXP timeStepsSEXP, SEXP gridPointsSEXP, SEXP engineSEXP, SEXP discreteDividendsSEXP, SEXP discreteDividendsTimeUntilSEXP) {
1546+
RcppExport SEXP _RQuantLib_americanOptionEngine(SEXP typeSEXP, SEXP underlyingSEXP, SEXP strikeSEXP, SEXP dividendYieldSEXP, SEXP riskFreeRateSEXP, SEXP maturitySEXP, SEXP exDateSEXP, SEXP volatilitySEXP, SEXP timeStepsSEXP, SEXP gridPointsSEXP, SEXP engineSEXP, SEXP discreteDividendsSEXP, SEXP discreteDividendsTimeUntilSEXP, SEXP dayCounterSEXP) {
15451547
SEXP rcpp_result_gen;
15461548
{
15471549
Rcpp::RNGScope rcpp_rngScope_gen;
1548-
rcpp_result_gen = PROTECT(_RQuantLib_americanOptionEngine_try(typeSEXP, underlyingSEXP, strikeSEXP, dividendYieldSEXP, riskFreeRateSEXP, maturitySEXP, volatilitySEXP, timeStepsSEXP, gridPointsSEXP, engineSEXP, discreteDividendsSEXP, discreteDividendsTimeUntilSEXP));
1550+
rcpp_result_gen = PROTECT(_RQuantLib_americanOptionEngine_try(typeSEXP, underlyingSEXP, strikeSEXP, dividendYieldSEXP, riskFreeRateSEXP, maturitySEXP, exDateSEXP, volatilitySEXP, timeStepsSEXP, gridPointsSEXP, engineSEXP, discreteDividendsSEXP, discreteDividendsTimeUntilSEXP, dayCounterSEXP));
15491551
}
15501552
Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error");
15511553
if (rcpp_isInterrupt_gen) {
@@ -1663,7 +1665,7 @@ static int _RQuantLib_RcppExport_validate(const char* sig) {
16631665
signatures.insert("std::string(*getQuantLibVersion)()");
16641666
signatures.insert("Rcpp::LogicalVector(*getQuantLibCapabilities)()");
16651667
signatures.insert("Rcpp::List(*europeanOptionEngine)(std::string,double,double,double,double,Rcpp::Nullable<double>,Rcpp::Nullable<QuantLib::Date>,double,Rcpp::Nullable<Rcpp::NumericVector>,Rcpp::Nullable<Rcpp::NumericVector>,int)");
1666-
signatures.insert("Rcpp::List(*americanOptionEngine)(std::string,double,double,double,double,double,double,int,int,std::string,Rcpp::Nullable<Rcpp::NumericVector>,Rcpp::Nullable<Rcpp::NumericVector>)");
1668+
signatures.insert("Rcpp::List(*americanOptionEngine)(std::string,double,double,double,double,Rcpp::Nullable<double>,Rcpp::Nullable<QuantLib::Date>,double,int,int,std::string,Rcpp::Nullable<Rcpp::NumericVector>,Rcpp::Nullable<Rcpp::NumericVector>,int)");
16671669
signatures.insert("Rcpp::List(*europeanOptionArraysEngine)(std::string,Rcpp::NumericMatrix)");
16681670
}
16691671
return signatures.find(sig) != signatures.end();
@@ -1762,7 +1764,7 @@ static const R_CallMethodDef CallEntries[] = {
17621764
{"_RQuantLib_getQuantLibVersion", (DL_FUNC) &_RQuantLib_getQuantLibVersion, 0},
17631765
{"_RQuantLib_getQuantLibCapabilities", (DL_FUNC) &_RQuantLib_getQuantLibCapabilities, 0},
17641766
{"_RQuantLib_europeanOptionEngine", (DL_FUNC) &_RQuantLib_europeanOptionEngine, 11},
1765-
{"_RQuantLib_americanOptionEngine", (DL_FUNC) &_RQuantLib_americanOptionEngine, 12},
1767+
{"_RQuantLib_americanOptionEngine", (DL_FUNC) &_RQuantLib_americanOptionEngine, 14},
17661768
{"_RQuantLib_europeanOptionArraysEngine", (DL_FUNC) &_RQuantLib_europeanOptionArraysEngine, 2},
17671769
{"_RQuantLib_zeroprice", (DL_FUNC) &_RQuantLib_zeroprice, 5},
17681770
{"_RQuantLib_zeroyield", (DL_FUNC) &_RQuantLib_zeroyield, 5},

0 commit comments

Comments
 (0)