double uo_put_ql(const Date& todaysDate_, const Date& settlementDate_, const Date& maturity_, Real spot_, Real strike, Real barrier_, Real rebate_, Spread dividendYield, Rate riskFreeRate, Volatility volatility ) { // set up dates Calendar calendar = TARGET(); Date todaysDate = todaysDate_; Date settlementDate = settlementDate_; Date maturity = maturity_; Settings::instance().evaluationDate() = todaysDate_; DayCounter dc = Actual360(); Real barrier = barrier_; Real rebate = rebate_; Handle <Quote > spot(boost::shared_ptr<SimpleQuote>(new SimpleQuote(spot_))); Handle<YieldTermStructure> qTS(boost::shared_ptr<YieldTermStructure>( new FlatForward(settlementDate, dividendYield, dc))); Handle<YieldTermStructure> rTS(boost::shared_ptr<YieldTermStructure>( new FlatForward(settlementDate, riskFreeRate, dc))); Handle<BlackVolTermStructure> volTS(boost::shared_ptr<BlackVolTermStructure>( new BlackConstantVol(settlementDate, calendar, volatility, dc))); boost::shared_ptr<BlackScholesMertonProcess> stochProcess(new BlackScholesMertonProcess(spot, qTS, rTS, volTS)); boost::shared_ptr<PricingEngine> engine( new AnalyticBarrierEngine(stochProcess)); Option::Type type = Option::Put; boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, strike)); boost::shared_ptr<Exercise> exercise(new EuropeanExercise(maturity)); BarrierOption option( Barrier::UpOut, barrier, rebate, payoff, exercise); option.setPricingEngine(engine); return option.NPV(); }
// dumped core when we tried last // no longer under 0.3.10 and g++ 4.0.1 (Aug 2005) // [[Rcpp::export]] double binaryOptionImpliedVolatilityEngine(std::string type, double value, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, double cashPayoff) { #ifdef QL_HIGH_RESOLUTION_DATE // in minutes boost::posix_time::time_duration length = boost::posix_time::minutes(maturity * 360 * 24 * 60); #else int length = int(maturity*360 + 0.5); // FIXME: this could be better #endif QuantLib::Option::Type optionType = getOptionType(type); // updated again for QuantLib 0.9.0, // cf QuantLib-0.9.0/test-suite/digitaloption.cpp QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dc = QuantLib::Actual360(); boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today, qRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today, rRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::CashOrNothingPayoff(optionType, strike, cashPayoff)); #ifdef QL_HIGH_RESOLUTION_DATE QuantLib::Date exDate(today.dateTime() + length); #else QuantLib::Date exDate = today + length; #endif boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(exDate)); boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); //boost::shared_ptr<PricingEngine> engine(new AnalyticEuropeanEngine(stochProcess)); boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::AnalyticBarrierEngine(stochProcess)); QuantLib::VanillaOption opt(payoff, exercise); opt.setPricingEngine(engine); return opt.impliedVolatility(value, stochProcess); }
// [[Rcpp::export]] Rcpp::List binaryOptionEngine(std::string binType, std::string type, std::string excType, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, double cashPayoff) { #ifdef QL_HIGH_RESOLUTION_DATE // in minutes boost::posix_time::time_duration length = boost::posix_time::minutes(maturity * 360 * 24 * 60); #else int length = int(maturity*360 + 0.5); // FIXME: this could be better, but same rounding in QL #endif QuantLib::Option::Type optionType = getOptionType(type); // new QuantLib 0.3.5 framework: digitals, updated for 0.3.7 // updated again for QuantLib 0.9.0, // cf QuantLib-0.9.0/test-suite/digitaloption.cpp QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dc = QuantLib::Actual360(); boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today,qRate,dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today,rRate,dc); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff; if (binType=="cash") { boost::shared_ptr<QuantLib::StrikedTypePayoff> con(new QuantLib::CashOrNothingPayoff(optionType, strike, cashPayoff)); payoff = con; } else if (binType=="asset") { boost::shared_ptr<QuantLib::StrikedTypePayoff> aon(new QuantLib::AssetOrNothingPayoff(optionType, strike)); payoff = aon; } else if (binType=="gap") { boost::shared_ptr<QuantLib::StrikedTypePayoff> gap(new QuantLib::GapPayoff(optionType, strike, cashPayoff)); payoff = gap; } else { throw std::range_error("Unknown binary option type " + binType); } #ifdef QL_HIGH_RESOLUTION_DATE QuantLib::Date exDate(today.dateTime() + length); #else QuantLib::Date exDate = today + length; #endif boost::shared_ptr<QuantLib::Exercise> exercise; if (excType=="american") { boost::shared_ptr<QuantLib::Exercise> amEx(new QuantLib::AmericanExercise(today, exDate)); exercise = amEx; } else if (excType=="european") { boost::shared_ptr<QuantLib::Exercise> euEx(new QuantLib::EuropeanExercise(exDate)); exercise = euEx; } else { throw std::range_error("Unknown binary exercise type " + excType); } boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); boost::shared_ptr<QuantLib::PricingEngine> engine; if (excType=="american") { boost::shared_ptr<QuantLib::PricingEngine> amEng(new QuantLib::AnalyticDigitalAmericanEngine(stochProcess)); engine = amEng; } else if (excType=="european") { boost::shared_ptr<QuantLib::PricingEngine> euEng(new QuantLib::AnalyticEuropeanEngine(stochProcess)); engine = euEng; } else { throw std::range_error("Unknown binary exercise type " + excType); } QuantLib::VanillaOption opt(payoff, exercise); opt.setPricingEngine(engine); Rcpp::List rl = Rcpp::List::create(Rcpp::Named("value") = opt.NPV(), Rcpp::Named("delta") = opt.delta(), Rcpp::Named("gamma") = opt.gamma(), Rcpp::Named("vega") = (excType=="european") ? opt.vega() : R_NaN, Rcpp::Named("theta") = (excType=="european") ? opt.theta() : R_NaN, Rcpp::Named("rho") = (excType=="european") ? opt.rho() : R_NaN, Rcpp::Named("divRho") = (excType=="european") ? opt.dividendRho() : R_NaN); return rl; }
// [[Rcpp::export]] Rcpp::List barrierOptionEngine(std::string barrType, std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, double barrier, double rebate) { #ifdef QL_HIGH_RESOLUTION_DATE // in minutes boost::posix_time::time_duration length = boost::posix_time::minutes(maturity * 360 * 24 * 60); #else int length = int(maturity*360 + 0.5); // FIXME: this could be better #endif QuantLib::Barrier::Type barrierType = QuantLib::Barrier::DownIn; if (barrType=="downin") { barrierType = QuantLib::Barrier::DownIn; } else if (barrType=="upin") { barrierType = QuantLib::Barrier::UpIn; } else if (barrType=="downout") { barrierType = QuantLib::Barrier::DownOut; } else if (barrType=="upout") { barrierType = QuantLib::Barrier::UpOut; } else { throw std::range_error("Unknown barrier type " + type); } QuantLib::Option::Type optionType = getOptionType(type); // new QuantLib 0.3.5 framework, updated for 0.3.7 // updated again for QuantLib 0.9.0, // cf QuantLib-0.9.0/test-suite/barrieroption.cpp QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dc = QuantLib::Actual360(); boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today, qRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today,rRate,dc); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); #ifdef QL_HIGH_RESOLUTION_DATE QuantLib::Date exDate(today.dateTime() + length); #else QuantLib::Date exDate = today + length; #endif boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(exDate)); boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::PlainVanillaPayoff(optionType, strike)); boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); // Size timeSteps = 1; // bool antitheticVariate = false; // bool controlVariate = false; // Size requiredSamples = 10000; // double requiredTolerance = 0.02; // Size maxSamples = 1000000; // bool isBiased = false; boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::AnalyticBarrierEngine(stochProcess)); // need to explicitly reference BarrierOption from QuantLib here QuantLib::BarrierOption barrierOption(barrierType, barrier, rebate, payoff, exercise); barrierOption.setPricingEngine(engine); Rcpp::List rl = Rcpp::List::create(Rcpp::Named("value") = barrierOption.NPV(), Rcpp::Named("delta") = R_NaReal, Rcpp::Named("gamma") = R_NaReal, Rcpp::Named("vega") = R_NaReal, Rcpp::Named("theta") = R_NaReal, Rcpp::Named("rho") = R_NaReal, Rcpp::Named("divRho") = R_NaReal); return rl; }
// [[Rcpp::export]] Rcpp::List asianOptionEngine(std::string averageType, std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, double first, double length, size_t fixings) { QuantLib::Option::Type optionType = getOptionType(type); //from test-suite/asionoptions.cpp QuantLib::DayCounter dc = QuantLib::Actual360(); QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); QuantLib::ext::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today, qRate, dc); QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); QuantLib::ext::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today, rRate, dc); QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); QuantLib::ext::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); QuantLib::ext::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); QuantLib::ext::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::PlainVanillaPayoff(optionType,strike)); Rcpp::List rl = R_NilValue; if (averageType=="geometric"){ QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::AnalyticContinuousGeometricAveragePriceAsianEngine(stochProcess)); #ifdef QL_HIGH_RESOLUTION_DATE // in minutes QuantLib::Date exDate(today.dateTime() + boost::posix_time::minutes(boost::uint64_t(maturity * 360 * 24 * 60))); #else QuantLib::Date exDate = today + int(maturity * 360 + 0.5); #endif boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(exDate)); QuantLib::ContinuousAveragingAsianOption option(QuantLib::Average::Geometric, payoff, exercise); option.setPricingEngine(engine); rl = Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = option.delta(), Rcpp::Named("gamma") = option.gamma(), Rcpp::Named("vega") = option.vega(), Rcpp::Named("theta") = option.theta(), Rcpp::Named("rho") = option.rho(), Rcpp::Named("divRho") = option.dividendRho()); } else if (averageType=="arithmetic") { // TODO: check fixings > 1, first, length if (first < 0) Rcpp::stop("Parameter 'first' must be non-negative."); if (length < 0) Rcpp::stop("Parameter 'length' must be non-negative."); if (fixings <= 1) Rcpp::stop("Parameter 'fixings' must be larger than one."); boost::shared_ptr<QuantLib::PricingEngine> engine = QuantLib::MakeMCDiscreteArithmeticAPEngine<QuantLib::LowDiscrepancy>(stochProcess) .withSamples(2047) .withControlVariate(); //boost::shared_ptr<PricingEngine> engine = // MakeMCDiscreteArithmeticASEngine<LowDiscrepancy>(stochProcess) // .withSeed(3456789) // .withSamples(1023); QuantLib::Time dt = length / (fixings - 1); std::vector<QuantLib::Time> timeIncrements(fixings); std::vector<QuantLib::Date> fixingDates(fixings); timeIncrements[0] = first; fixingDates[0] = today + QuantLib::Integer(timeIncrements[0] * 360 + 0.5); for (QuantLib::Size i=1; i<fixings; i++) { timeIncrements[i] = i*dt + first; #ifdef QL_HIGH_RESOLUTION_DATE fixingDates[i]= QuantLib::Date(today.dateTime() + boost::posix_time::minutes(boost::uint64_t(timeIncrements[i] * 360 * 24 * 60))); #else fixingDates[i] = today + QuantLib::Integer(timeIncrements[i]*360+0.5); #endif } QuantLib::Real runningSum = 0.0; QuantLib::Size pastFixing = 0; boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(fixingDates[fixings-1])); QuantLib::DiscreteAveragingAsianOption option(QuantLib::Average::Arithmetic, runningSum, pastFixing, fixingDates, payoff, exercise); option.setPricingEngine(engine); rl = Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = R_NaReal, Rcpp::Named("gamma") = R_NaReal, Rcpp::Named("vega") = R_NaReal, Rcpp::Named("theta") = R_NaReal, Rcpp::Named("rho") = R_NaReal, Rcpp::Named("divRho") = R_NaReal); } return rl; }
RcppExport SEXP AsianOption(SEXP optionParameters){ try{ Rcpp::List rparam(optionParameters); std::string avgType = Rcpp::as<std::string>(rparam["averageType"]); std::string type = Rcpp::as<std::string>(rparam["type"]); double underlying = Rcpp::as<double>(rparam["underlying"]); double strike = Rcpp::as<double>(rparam["strike"]); QuantLib::Spread dividendYield = Rcpp::as<double>(rparam["dividendYield"]); QuantLib::Rate riskFreeRate = Rcpp::as<double>(rparam["riskFreeRate"]); QuantLib::Time maturity = Rcpp::as<double>(rparam["maturity"]); // int length = int(maturity*360 + 0.5); // FIXME: this could be better double volatility = Rcpp::as<double>(rparam["volatility"]); QuantLib::Option::Type optionType = getOptionType(type); //from test-suite/asionoptions.cpp QuantLib::DayCounter dc = QuantLib::Actual360(); QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today, qRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today, rRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::PlainVanillaPayoff(optionType,strike)); QuantLib::Average::Type averageType = QuantLib::Average::Geometric; Rcpp::List rl = R_NilValue; if (avgType=="geometric"){ averageType = QuantLib::Average::Geometric; boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::AnalyticContinuousGeometricAveragePriceAsianEngine(stochProcess)); QuantLib::Date exDate = today + int(maturity * 360 + 0.5); boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(exDate)); QuantLib::ContinuousAveragingAsianOption option(averageType, payoff, exercise); option.setPricingEngine(engine); rl = Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = option.delta(), Rcpp::Named("gamma") = option.gamma(), Rcpp::Named("vega") = option.vega(), Rcpp::Named("theta") = option.theta(), Rcpp::Named("rho") = option.rho(), Rcpp::Named("divRho") = option.dividendRho(), Rcpp::Named("parameters") = optionParameters); } else if (avgType=="arithmetic"){ averageType = QuantLib::Average::Arithmetic; boost::shared_ptr<QuantLib::PricingEngine> engine = QuantLib::MakeMCDiscreteArithmeticAPEngine<QuantLib::LowDiscrepancy>(stochProcess) .withSamples(2047) .withControlVariate(); //boost::shared_ptr<PricingEngine> engine = // MakeMCDiscreteArithmeticASEngine<LowDiscrepancy>(stochProcess) // .withSeed(3456789) // .withSamples(1023); QuantLib::Size fixings = Rcpp::as<double>(rparam["fixings"]); QuantLib::Time length = Rcpp::as<double>(rparam["length"]); QuantLib::Time first = Rcpp::as<double>(rparam["first"]); QuantLib::Time dt = length / (fixings - 1); std::vector<QuantLib::Time> timeIncrements(fixings); std::vector<QuantLib::Date> fixingDates(fixings); timeIncrements[0] = first; fixingDates[0] = today + QuantLib::Integer(timeIncrements[0] * 360 + 0.5); for (QuantLib::Size i=1; i<fixings; i++) { timeIncrements[i] = i*dt + first; fixingDates[i] = today + QuantLib::Integer(timeIncrements[i]*360+0.5); } QuantLib::Real runningSum = 0.0; QuantLib::Size pastFixing = 0; boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(fixingDates[fixings-1])); QuantLib::DiscreteAveragingAsianOption option(QuantLib::Average::Arithmetic, runningSum, pastFixing, fixingDates, payoff, exercise); option.setPricingEngine(engine); rl = Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = R_NaN, Rcpp::Named("gamma") = R_NaN, Rcpp::Named("vega") = R_NaN, Rcpp::Named("theta") = R_NaN, Rcpp::Named("rho") = R_NaN, Rcpp::Named("divRho") = R_NaN, Rcpp::Named("parameters") = optionParameters); } else { throw std::range_error("Unknown average type " + type); } return rl; } catch(std::exception &ex) { forward_exception_to_r(ex); } catch(...) { ::Rf_error("c++ exception (unknown reason)"); } return R_NilValue; }
// [[Rcpp::export]] Rcpp::List europeanOptionEngine(std::string type, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility, Rcpp::Nullable<Rcpp::NumericVector> discreteDividends, Rcpp::Nullable<Rcpp::NumericVector> discreteDividendsTimeUntil) { #ifdef QL_HIGH_RESOLUTION_DATE // in minutes boost::posix_time::time_duration length = boost::posix_time::minutes(boost::uint64_t(maturity * 360 * 24 * 60)); #else int length = int(maturity*360 + 0.5); // FIXME: this could be better #endif QuantLib::Option::Type optionType = getOptionType(type); QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; // new framework as per QuantLib 0.3.5 QuantLib::DayCounter dc = QuantLib::Actual360(); boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote( underlying )); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote( volatility )); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote( dividendYield )); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today, qRate, dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote( riskFreeRate )); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today, rRate, dc); bool withDividends = discreteDividends.isNotNull() && discreteDividendsTimeUntil.isNotNull(); #ifdef QL_HIGH_RESOLUTION_DATE QuantLib::Date exDate(today.dateTime() + length); #else QuantLib::Date exDate = today + length; #endif boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::EuropeanExercise(exDate)); boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::PlainVanillaPayoff(optionType, strike)); if (withDividends) { Rcpp::NumericVector divvalues(discreteDividends), divtimes(discreteDividendsTimeUntil); int n = divvalues.size(); std::vector<QuantLib::Date> discDivDates(n); std::vector<double> discDividends(n); for (int i = 0; i < n; i++) { #ifdef QL_HIGH_RESOLUTION_DATE boost::posix_time::time_duration discreteDividendLength = boost::posix_time::minutes(boost::uint64_t(divtimes[i] * 360 * 24 * 60)); discDivDates[i] = QuantLib::Date(today.dateTime() + discreteDividendLength); #else discDivDates[i] = today + int(divtimes[i] * 360 + 0.5); #endif discDividends[i] = divvalues[i]; } boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::AnalyticDividendEuropeanEngine(stochProcess)); QuantLib::DividendVanillaOption option(payoff, exercise, discDivDates, discDividends); option.setPricingEngine(engine); return Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = option.delta(), Rcpp::Named("gamma") = option.gamma(), Rcpp::Named("vega") = option.vega(), Rcpp::Named("theta") = option.theta(), Rcpp::Named("rho") = option.rho(), Rcpp::Named("divRho") = R_NaReal); } else { boost::shared_ptr<QuantLib::VanillaOption> option = makeOption(payoff, exercise, spot, qTS, rTS, volTS); return Rcpp::List::create(Rcpp::Named("value") = option->NPV(), Rcpp::Named("delta") = option->delta(), Rcpp::Named("gamma") = option->gamma(), Rcpp::Named("vega") = option->vega(), Rcpp::Named("theta") = option->theta(), Rcpp::Named("rho") = option->rho(), Rcpp::Named("divRho") = option->dividendRho()); } }
// [[Rcpp::export]] 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) { #ifdef QL_HIGH_RESOLUTION_DATE // in minutes boost::posix_time::time_duration length = boost::posix_time::minutes(boost::uint64_t(maturity * 360 * 24 * 60)); #else int length = int(maturity * 360 + 0.5); // FIXME: this could be better #endif QuantLib::Option::Type optionType = getOptionType(type); // new framework as per QuantLib 0.3.5, updated for 0.3.7 // updated again for 0.9.0, see eg test-suite/americanoption.cpp QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dc = QuantLib::Actual360(); boost::shared_ptr<QuantLib::SimpleQuote> spot(new QuantLib::SimpleQuote(underlying)); boost::shared_ptr<QuantLib::SimpleQuote> qRate(new QuantLib::SimpleQuote(dividendYield)); boost::shared_ptr<QuantLib::YieldTermStructure> qTS = flatRate(today,qRate,dc); boost::shared_ptr<QuantLib::SimpleQuote> rRate(new QuantLib::SimpleQuote(riskFreeRate)); boost::shared_ptr<QuantLib::YieldTermStructure> rTS = flatRate(today,rRate,dc); boost::shared_ptr<QuantLib::SimpleQuote> vol(new QuantLib::SimpleQuote(volatility)); boost::shared_ptr<QuantLib::BlackVolTermStructure> volTS = flatVol(today, vol, dc); bool withDividends = discreteDividends.isNotNull() && discreteDividendsTimeUntil.isNotNull(); #ifdef QL_HIGH_RESOLUTION_DATE QuantLib::Date exDate(today.dateTime() + length); #else QuantLib::Date exDate = today + length; #endif boost::shared_ptr<QuantLib::StrikedTypePayoff> payoff(new QuantLib::PlainVanillaPayoff(optionType, strike)); boost::shared_ptr<QuantLib::Exercise> exercise(new QuantLib::AmericanExercise(today, exDate)); boost::shared_ptr<QuantLib::BlackScholesMertonProcess> stochProcess(new QuantLib::BlackScholesMertonProcess(QuantLib::Handle<QuantLib::Quote>(spot), QuantLib::Handle<QuantLib::YieldTermStructure>(qTS), QuantLib::Handle<QuantLib::YieldTermStructure>(rTS), QuantLib::Handle<QuantLib::BlackVolTermStructure>(volTS))); if (withDividends) { Rcpp::NumericVector divvalues(discreteDividends), divtimes(discreteDividendsTimeUntil); int n = divvalues.size(); std::vector<QuantLib::Date> discDivDates(n); std::vector<double> discDividends(n); for (int i = 0; i < n; i++) { #ifdef QL_HIGH_RESOLUTION_DATE boost::posix_time::time_duration discreteDividendLength = boost::posix_time::minutes(boost::uint64_t(divtimes[i] * 360 * 24 * 60)); discDivDates[i] = QuantLib::Date(today.dateTime() + discreteDividendLength); #else discDivDates[i] = today + int(divtimes[i] * 360 + 0.5); #endif discDividends[i] = divvalues[i]; } QuantLib::DividendVanillaOption option(payoff, exercise, discDivDates, discDividends); if (engine=="BaroneAdesiWhaley") { Rcpp::warning("Discrete dividends, engine switched to CrankNicolson"); engine = "CrankNicolson"; } if (engine=="CrankNicolson") { // FDDividendAmericanEngine only works with CrankNicolson // suggestion by Bryan Lewis: use CrankNicolson for greeks boost::shared_ptr<QuantLib::PricingEngine> fdcnengine(new QuantLib::FDDividendAmericanEngine<QuantLib::CrankNicolson>(stochProcess, timeSteps, gridPoints)); option.setPricingEngine(fdcnengine); return Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = option.delta(), Rcpp::Named("gamma") = option.gamma(), Rcpp::Named("vega") = R_NaReal, Rcpp::Named("theta") = R_NaReal, Rcpp::Named("rho") = R_NaReal, Rcpp::Named("divRho") = R_NaReal); } else { throw std::range_error("Unknown engine " + engine); } } else { QuantLib::VanillaOption option(payoff, exercise); if (engine=="BaroneAdesiWhaley") { // new from 0.3.7 BaroneAdesiWhaley boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::BaroneAdesiWhaleyApproximationEngine(stochProcess)); option.setPricingEngine(engine); return Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = R_NaReal, Rcpp::Named("gamma") = R_NaReal, Rcpp::Named("vega") = R_NaReal, Rcpp::Named("theta") = R_NaReal, Rcpp::Named("rho") = R_NaReal, Rcpp::Named("divRho") = R_NaReal); } else if (engine=="CrankNicolson") { // suggestion by Bryan Lewis: use CrankNicolson for greeks boost::shared_ptr<QuantLib::PricingEngine> fdcnengine(new QuantLib::FDAmericanEngine<QuantLib::CrankNicolson>(stochProcess, timeSteps, gridPoints)); option.setPricingEngine(fdcnengine); return Rcpp::List::create(Rcpp::Named("value") = option.NPV(), Rcpp::Named("delta") = option.delta(), Rcpp::Named("gamma") = option.gamma(), Rcpp::Named("vega") = R_NaReal, Rcpp::Named("theta") = R_NaReal, Rcpp::Named("rho") = R_NaReal, Rcpp::Named("divRho") = R_NaReal); } else { throw std::range_error("Unknown engine " + engine); } } }