Skip to content

Commit

Permalink
feat: quantlib
Browse files Browse the repository at this point in the history
  • Loading branch information
m-truscott committed Feb 5, 2024
1 parent 53e2535 commit ea4cae1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 36 deletions.
37 changes: 37 additions & 0 deletions src/libraries/quantlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,40 @@ LibQuantLib::PriceOption(Real underlyingPrice, Real strike, Rate riskFreeRate, V
europeanOption.setPricingEngine(mcengine);
return europeanOption.NPV();
}

/** @brief Prices a fixed rate bond
*
* @param faceValue
* @param couponRate
* @param issueDate
* @param maturityDate
* @param frequency
* @param dayCounter
*
* Usage:
Real faceValue = 1000.0;
Real couponRate = 0.05;
Date issueDate(1, January, 2022);
Date maturityDate(1, January, 2032);
Frequency frequency = Semiannual;
DayCounter dayCounter = ActualActual(ActualActual::ISMA);
*/
Real
LibQuantLib::FixedRateBond(Real faceValue, Real couponRate, Date issueDate, Date maturityDate, Frequency frequency,
DayCounter dayCounter) {
// Create a schedule of coupon payment dates
Schedule schedule(issueDate, maturityDate, Period(frequency), TARGET(), ModifiedFollowing, ModifiedFollowing,
DateGeneration::Backward, false);

// Calculate cash flows
std::vector<Rate> couponRates(schedule.size() - 1, couponRate);
std::vector<Real> notionals(schedule.size() - 1, faceValue);
notionals.back() += faceValue; // Add face value to the last payment
Leg cashFlows = FixedRateLeg(schedule).withNotionals(notionals).withCouponRates(couponRates, dayCounter);

// Discount cash flows manually
Handle<YieldTermStructure> discountCurve(
boost::shared_ptr<YieldTermStructure>(new FlatForward(0, TARGET(), 0.05, ActualActual(ActualActual::ISMA))));

return CashFlows::npv(cashFlows, *discountCurve);
}
45 changes: 9 additions & 36 deletions src/libraries/quantlib.h
Original file line number Diff line number Diff line change
@@ -1,43 +1,16 @@
#ifndef _LIB_QUANTLIB_H_
#define _LIB_QUANTLIB_H_

#include <iostream>
#include <ql/quantlib.hpp>

using namespace QuantLib;

Real
PriceOption(Real underlyingPrice, Real strike, Real riskFreeRate, Volatility) {
// Market data
Real underlyingPrice = 100.0;
Real strike = 100.0;
Rate riskFreeRate = 0.05;
Volatility volatility = 0.20;
Date maturity(20, September, 2024);

// Option type
Option::Type type(Option::Call);

// Constructing the European option
EuropeanExercise europeanExercise(maturity);
Handle<Quote> underlyingH(boost::shared_ptr<Quote>(new SimpleQuote(underlyingPrice)));
Handle<YieldTermStructure> flatTermStructure(
boost::shared_ptr<YieldTermStructure>(new FlatForward(0, TARGET(), riskFreeRate, Actual365Fixed())));
Handle<BlackVolTermStructure> flatVolTS(
boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(0, TARGET(), volatility, Actual365Fixed())));
boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, strike));
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH, flatTermStructure, flatTermStructure, flatVolTS));

// Create a European option
VanillaOption europeanOption(payoff, europeanExercise);

// Pricing using Monte Carlo with low number of paths (suboptimal)
Size numPaths = 100; // Very low number of paths
boost::shared_ptr<PricingEngine> mcengine;
mcengine = MakeMCEuropeanEngine<PseudoRandom>(bsmProcess).withSteps(10).withAbsoluteTolerance(0.02).withSeed(42);

europeanOption.setPricingEngine(mcengine);
Real npv = europeanOption.NPV();
namespace LibQuantLib {

std::cout << "European Option NPV (Monte Carlo method): " << npv << std::endl;
Real PriceOption(Real underlyingPrice, Real strike, Real riskFreeRate, Volatility volatility, Date maturity);
Real FixedRateBond(Real faceValue, Real couponRate, Date issueDate, Date maturityDate, Frequency frequency,
DayCounter dayCounter);
} // namespace LibQuantLib

return 0;
}
#endif // !_LIB_QUANTLIB_H_

0 comments on commit ea4cae1

Please sign in to comment.