// [[Rcpp::export]] Rcpp::List europeanOptionArraysEngine(std::string type, Rcpp::NumericMatrix par) { QuantLib::Option::Type optionType = getOptionType(type); int n = par.nrow(); Rcpp::NumericVector value(n), delta(n), gamma(n), vega(n), theta(n), rho(n), divrho(n); QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dc = QuantLib::Actual360(); for (int i=0; i<n; i++) { double underlying = par(i, 0); // first column double strike = par(i, 1); // second column QuantLib::Spread dividendYield = par(i, 2); // third column QuantLib::Rate riskFreeRate = par(i, 3); // fourth column QuantLib::Time maturity = par(i, 4); // fifth column #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 double volatility = par(i, 5); // sixth column 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); #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::VanillaOption> option = makeOption(payoff, exercise, spot, qTS, rTS, volTS); value[i] = option->NPV(); delta[i] = option->delta(); gamma[i] = option->gamma(); vega[i] = option->vega(); theta[i] = option->theta(); rho[i] = option->rho(); divrho[i] = option->dividendRho(); } return Rcpp::List::create(Rcpp::Named("value") = value, Rcpp::Named("delta") = delta, Rcpp::Named("gamma") = gamma, Rcpp::Named("vega") = vega, Rcpp::Named("theta") = theta, Rcpp::Named("rho") = rho, Rcpp::Named("divRho") = divrho); }
// 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); }
Rate CreditDefaultSwap::impliedHazardRate( Real targetNPV, const Handle<YieldTermStructure>& discountCurve, const DayCounter& dayCounter, Real recoveryRate, Real accuracy) const { boost::shared_ptr<SimpleQuote> flatRate(new SimpleQuote(0.0)); Handle<DefaultProbabilityTermStructure> probability( boost::shared_ptr<DefaultProbabilityTermStructure>(new FlatHazardRate(0, WeekendsOnly(), Handle<Quote>(flatRate), dayCounter))); MidPointCdsEngine engine(probability, recoveryRate, discountCurve); setupArguments(engine.getArguments()); const CreditDefaultSwap::results* results = dynamic_cast<const CreditDefaultSwap::results*>( engine.getResults()); ObjectiveFunction f(targetNPV, *flatRate, engine, results); Rate guess = 0.001; Rate step = guess*0.1; return Brent().solve(f, accuracy, guess, step); }
// [[Rcpp::export]] double europeanOptionImpliedVolatilityEngine(std::string type, double value, double underlying, double strike, double dividendYield, double riskFreeRate, double maturity, double volatility) { const QuantLib::Size maxEvaluations = 100; const double tolerance = 1.0e-6; int length = int(maturity*360 + 0.5); // FIXME: this could be better 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 // updated for 0.3.7 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); QuantLib::Date exDate = today + length; 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::VanillaOption> option = makeOption(payoff, exercise, spot, qTS, rTS, volTS, Analytic, QuantLib::Null<QuantLib::Size>(), QuantLib::Null<QuantLib::Size>()); boost::shared_ptr<QuantLib::GeneralizedBlackScholesProcess> process = makeProcess(spot, qTS, rTS,volTS); double volguess = volatility; vol->setValue(volguess); return option->impliedVolatility(value, process, tolerance, maxEvaluations); }
// [[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; }
boost::shared_ptr<YieldTermStructure> flatRate(Rate forward, const DayCounter& dc) { return flatRate(boost::shared_ptr<Quote>(new SimpleQuote(forward)), dc); }
// [[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); } } }
void qlHazardRateFactory::calculate() { try { TiXmlDocument document; document.Parse(instInfo_.c_str(), 0, TIXML_ENCODING_UTF8); TiXmlNode* rootNode = document.FirstChild("defaultCurveCalculation"); Settings::instance().evaluationDate() = strToDate(rootNode->FirstChildElement("evaluationTime")->GetText()); DayCounter daycounter = Actual365Fixed(); TiXmlElement* pricingParametorNode = rootNode->FirstChildElement("pricingParameter"); TiXmlElement* referenceCurveNode = pricingParametorNode->FirstChildElement("referenceCurves"); Calendar calendar = SouthKorea(); Date refereceDate = Settings::instance().evaluationDate(); // must be a business day refereceDate = calendar.adjust(refereceDate); // dummy curve boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.01)); //Handle<YieldTermStructure> tsCurve( // boost::shared_ptr<FlatForward>( // new FlatForward(todaysDate, Handle<Quote>(flatRate), // Actual365Fixed()))); TiXmlNode* pricingParametorNode = document.FirstChild("pricingParameter"); TiXmlElement* referenceCurveNode = pricingParametorNode->FirstChildElement("referenceCurves"); std::vector<boost::shared_ptr<HazardRateStructure>> hazardRateCurves; TiXmlElement* tsNode = referenceCurveNode->FirstChildElement("termstructure"); if(tsNode) { for(tsNode; tsNode; tsNode = tsNode->NextSiblingElement("termstructure")) { hazardRateCurves.push_back(this->hazardRateTS(tsNode)); } } TiXmlNode* yieldNode = document.FirstChild("yieldNode"); qlYieldTermStructureFactory yieldTsFactory = qlYieldTermStructureFactory(); this->tsCurve_ = yieldTsFactory.yieldTSHandle(yieldNode); // outputTenor Build std::vector<Period> outputTenors; Size outputNum = outputTenors.size(); qlTimeUnitFactory tuFactory = qlTimeUnitFactory(); TiXmlElement* outputTenorNode = pricingParametorNode->FirstChildElement("outputCurveTemplate"); TiXmlElement* tenorNode = outputTenorNode->FirstChildElement("tenorList"); if(tenorNode) { for(tenorNode; tenorNode; tenorNode = tenorNode->NextSiblingElement("tenor")) { outputTenors.push_back(tuFactory.timeUnit(tenorNode)); } } //compositeCalculation boost::shared_ptr<DefaultProbabilityTermStructure> copulaHazardTS = boost::shared_ptr<DefaultProbabilityTermStructure>(new CopulaHazardRate<ProbabilityOfAtLeastNEvents,Linear>( dates,hazardRateCurves,0.9,1,50)); //result for (Size i=0 ; i<outputNum ; ++i) { dates_.push_back(calendar.advance(refereceDate,outputTenors[i])); dateTimes_.push_back(daycounter.yearFraction(refereceDate,dates_[i])); data_.push_back(copulaHazardTS->defaultProbability(dateTimes_[i])); } // makeXml this->buildResultXml(); //this->buildResultXml(inst_->additionalResults()); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "unknown error" << std::endl; } }