diff --git a/CMakeLists.txt b/CMakeLists.txt index e7b7bb0..46caaf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,9 +24,8 @@ FetchContent_MakeAvailable(googletest) add_executable(qengine_tests tests/test_black_scholes.cpp tests/stubs/FlatYieldCurve.cpp - tests/stubs/FlatVolatilitySurface.cpp - tests/stubs/FakeMarketData.cpp) + tests/stubs/FlatVolatilitySurface.cpp) target_link_libraries(qengine_tests qengine GTest::gtest_main) include(GoogleTest) -gtest_discover_tests(qengine_tests) \ No newline at end of file +gtest_discover_tests(qengine_tests) diff --git a/src/BlackScholesProcess.hpp b/src/BlackScholesProcess.hpp index 97769ab..320f34f 100644 --- a/src/BlackScholesProcess.hpp +++ b/src/BlackScholesProcess.hpp @@ -9,8 +9,7 @@ class BlackScholesProcess : public StochasticProcess{ public: - BlackScholesProcess() = default; - BlackScholesProcess(std::unique_ptr data) : StochasticProcess(std::move(data)){} + explicit BlackScholesProcess(MarketData data) : StochasticProcess(std::move(data)){} double drift(double t, double s) override; @@ -21,4 +20,4 @@ public: }; -#endif //QUANTENGINE_BLACKSCHOLESPROCESS_HPP \ No newline at end of file +#endif //QUANTENGINE_BLACKSCHOLESPROCESS_HPP diff --git a/src/MarketData.cpp b/src/MarketData.cpp index eba40df..16bf3c4 100644 --- a/src/MarketData.cpp +++ b/src/MarketData.cpp @@ -5,5 +5,5 @@ #include "MarketData.hpp" double MarketData::spot() const { return spot_; } -YieldCurve& MarketData::yield_curve() { return *yield_curve_; } -VolatilitySurface& MarketData::volatility_surface() { return *volatility_surface_; } \ No newline at end of file +const YieldCurve& MarketData::yield_curve() const { return *yield_curve_; } +const VolatilitySurface& MarketData::volatility_surface() const { return *volatility_surface_; } diff --git a/src/MarketData.hpp b/src/MarketData.hpp index 1c61c8c..9b8d200 100644 --- a/src/MarketData.hpp +++ b/src/MarketData.hpp @@ -10,24 +10,24 @@ class MarketData { public: - MarketData() = default; + MarketData() = delete; - MarketData(double spot, std::unique_ptr yield_curve, - std::unique_ptr volatility_surface) + MarketData(double spot, std::shared_ptr yield_curve, + std::shared_ptr volatility_surface) : spot_(spot), yield_curve_(std::move(yield_curve)), volatility_surface_(std::move(volatility_surface)) { } double spot() const; - YieldCurve& yield_curve(); - VolatilitySurface& volatility_surface(); + const YieldCurve& yield_curve() const; + const VolatilitySurface& volatility_surface() const; private: double spot_; - std::unique_ptr yield_curve_; - std::unique_ptr volatility_surface_; + std::shared_ptr yield_curve_; + std::shared_ptr volatility_surface_; }; -#endif //QUANTENGINE_MARKETDATA_HPP \ No newline at end of file +#endif //QUANTENGINE_MARKETDATA_HPP diff --git a/src/Statistics.hpp b/src/Statistics.hpp index 153cd7b..a4de629 100644 --- a/src/Statistics.hpp +++ b/src/Statistics.hpp @@ -9,7 +9,7 @@ class Statistics { public: - Statistics() : moments_({0., 0., 0.}), max_(0.), min_(0.) {} + Statistics() : moments_({0., 0., 0.}), n(0), max_(0.), min_(0.) {} void dump(double value); void clear(); double mean(); @@ -27,4 +27,4 @@ private: }; -#endif //QUANTENGINE_STATISTICS_HPP \ No newline at end of file +#endif //QUANTENGINE_STATISTICS_HPP diff --git a/src/StochasticProcess.hpp b/src/StochasticProcess.hpp index c326020..a0ebb49 100644 --- a/src/StochasticProcess.hpp +++ b/src/StochasticProcess.hpp @@ -9,20 +9,20 @@ class StochasticProcess { public: - StochasticProcess() = default; - StochasticProcess(std::unique_ptr data) : data_(std::move(data)){} + StochasticProcess() = delete; + explicit StochasticProcess(MarketData data) : data_(std::move(data)){} virtual ~StochasticProcess() = default; virtual double drift(double t, double s) = 0; virtual double diffusion(double t, double s) = 0; virtual double step(double t, double s, double dt, double dW) = 0; - MarketData& data() const {return *data_;} + const MarketData& data() const {return data_;} private: - std::shared_ptr data_; + MarketData data_; }; -#endif //QUANTENGINE_STOCHASTICPROCESS_HPP \ No newline at end of file +#endif //QUANTENGINE_STOCHASTICPROCESS_HPP diff --git a/src/VolatilitySurface.hpp b/src/VolatilitySurface.hpp index 8d2622c..438df63 100644 --- a/src/VolatilitySurface.hpp +++ b/src/VolatilitySurface.hpp @@ -9,10 +9,10 @@ class VolatilitySurface { public: virtual ~VolatilitySurface() = default; - virtual double sigma(double K, double T) = 0; + virtual double sigma(double K, double T) const = 0; private: }; -#endif //QUANTENGINE_VOLATILITYSURFACE_HPP \ No newline at end of file +#endif //QUANTENGINE_VOLATILITYSURFACE_HPP diff --git a/src/YieldCurve.hpp b/src/YieldCurve.hpp index 4a4f78d..7853382 100644 --- a/src/YieldCurve.hpp +++ b/src/YieldCurve.hpp @@ -28,10 +28,10 @@ public: return *this; } virtual ~YieldCurve() = default; - virtual double discount(double t) = 0; - virtual double zeroRate(double t) = 0; + virtual double discount(double t) const = 0; + virtual double zeroRate(double t) const = 0; }; -#endif //QUANTENGINE_YIELDCURVE_HPP \ No newline at end of file +#endif //QUANTENGINE_YIELDCURVE_HPP diff --git a/tests/stubs/FakeMarketData.cpp b/tests/stubs/FakeMarketData.cpp deleted file mode 100644 index 6fd84e1..0000000 --- a/tests/stubs/FakeMarketData.cpp +++ /dev/null @@ -1,2 +0,0 @@ -// Minimal TU to satisfy CMake for test stubs -#include "FakeMarketData.hpp" diff --git a/tests/stubs/FakeMarketData.hpp b/tests/stubs/FakeMarketData.hpp deleted file mode 100644 index 52f6115..0000000 --- a/tests/stubs/FakeMarketData.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by David Doebel on 07.03.2026. -// -#ifndef QUANTENGINE_FAKEMARKETDATA_HPP -#define QUANTENGINE_FAKEMARKETDATA_HPP -#include "MarketData.hpp" -#include "FlatYieldCurve.hpp" -#include "FlatVolatilitySurface.hpp" - -class FakeMarketData : public MarketData { -public: - FakeMarketData() = default; - - FakeMarketData(const FakeMarketData &other) - { - } - - FakeMarketData(FakeMarketData &&other) noexcept - { - } - - FakeMarketData & operator=(const FakeMarketData &other) { - return *this; - } - - FakeMarketData & operator=(FakeMarketData &&other) noexcept { - return *this; - } - - double spot() const {return 100.0;} - YieldCurve& yield_curve(){return *yieldCurve_; }; - VolatilitySurface& volatility_surface(){return *volatilitySurface_; }; - -private: - std::unique_ptr yieldCurve_ = std::make_unique(); - std::unique_ptr volatilitySurface_ = std::make_unique(); -}; -#endif \ No newline at end of file diff --git a/tests/stubs/FlatVolatilitySurface.hpp b/tests/stubs/FlatVolatilitySurface.hpp index f56eb25..fcb2b9c 100644 --- a/tests/stubs/FlatVolatilitySurface.hpp +++ b/tests/stubs/FlatVolatilitySurface.hpp @@ -6,6 +6,12 @@ #include "VolatilitySurface.hpp" class FlatVolatilitySurface : public VolatilitySurface { - double sigma(double K, double T) {return 0.2;} +public: + explicit FlatVolatilitySurface(double sigma = 0.2) : sigma_(sigma) {} + + double sigma(double K, double T) const override {return sigma_;} + +private: + double sigma_; }; -#endif \ No newline at end of file +#endif diff --git a/tests/stubs/FlatYieldCurve.hpp b/tests/stubs/FlatYieldCurve.hpp index 87aba7e..9781d82 100644 --- a/tests/stubs/FlatYieldCurve.hpp +++ b/tests/stubs/FlatYieldCurve.hpp @@ -7,10 +7,12 @@ #include class FlatYieldCurve : public YieldCurve{ +public: + explicit FlatYieldCurve(double rate = 0.01) : rate_(rate) {} - double discount(double t) override {return std::exp(-rate_ * t); }; - double zeroRate(double t) override {return rate_; } + double discount(double t) const override {return std::exp(-rate_ * t); }; + double zeroRate(double t) const override {return rate_; } private: double rate_ = 0.01; }; -#endif \ No newline at end of file +#endif diff --git a/tests/test_black_scholes.cpp b/tests/test_black_scholes.cpp index a10bb88..b9f0f01 100644 --- a/tests/test_black_scholes.cpp +++ b/tests/test_black_scholes.cpp @@ -11,7 +11,6 @@ #include "stubs/FlatYieldCurve.hpp" #include "stubs/FlatVolatilitySurface.hpp" -#include "stubs/FakeMarketData.hpp" TEST(BlackScholesProcess, ExpectedValue) { // Market setup (via test stubs): S0=100, r=1%, sigma=20% @@ -19,9 +18,14 @@ TEST(BlackScholesProcess, ExpectedValue) { const double T = 1.0; const int numPaths = 300000; // enough for stable MC estimate - // Build Black-Scholes process with fake flat market data - auto processCall = std::make_unique(std::make_unique()); - auto processPut = std::make_unique(std::make_unique()); + const MarketData marketData( + 100.0, + std::make_shared(0.01), + std::make_shared(0.2)); + + // Build Black-Scholes process from an immutable market snapshot + auto processCall = std::make_unique(marketData); + auto processPut = std::make_unique(marketData); // RNG shared between engines is fine auto rng = std::make_shared(); @@ -38,12 +42,12 @@ TEST(BlackScholesProcess, ExpectedValue) { const double putPrice = putInstr.price(); // Ground truth Black–Scholes prices provided - const double callGT = 10.450583572; - const double putGT = 5.573526022; + const double callGT = 8.4333186901; + const double putGT = 7.4383020650; // Monte Carlo tolerance const double tol = 0.10; // 10 cents tolerance ASSERT_NEAR(callPrice, callGT, tol); ASSERT_NEAR(putPrice, putGT, tol); -} \ No newline at end of file +}