From 15a20fc96583fe895570c88ac44b331bc8b0e623 Mon Sep 17 00:00:00 2001 From: David Doebel Date: Tue, 3 Mar 2026 23:33:32 +0100 Subject: [PATCH] Create core structure --- CMakeLists.txt | 10 ++++++++++ Notes.md | 4 ++++ README.md | 4 +++- src/CMakeLists.txt | 9 +++++++++ src/black_scholes.cpp | 5 +++++ src/black_scholes.hpp | 30 ++++++++++++++++++++++++++++++ src/main.cpp | 22 ++++++++++++++++++++++ src/monte_carlo.cpp | 5 +++++ src/monte_carlo.hpp | 36 ++++++++++++++++++++++++++++++++++++ src/payoff.cpp | 11 +++++++++++ src/payoff.hpp | 21 +++++++++++++++++++++ 11 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 Notes.md create mode 100644 src/CMakeLists.txt create mode 100644 src/black_scholes.cpp create mode 100644 src/black_scholes.hpp create mode 100644 src/main.cpp create mode 100644 src/monte_carlo.cpp create mode 100644 src/monte_carlo.hpp create mode 100644 src/payoff.cpp create mode 100644 src/payoff.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..10f8d8f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) +project(QuantEngine) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_FLAGS "-O3 -march=native") + +find_package(Eigen3 REQUIRED) + +add_subdirectory(src) + diff --git a/Notes.md b/Notes.md new file mode 100644 index 0000000..8fa1b31 --- /dev/null +++ b/Notes.md @@ -0,0 +1,4 @@ +### Coding Language +First we need to decide on the language that we will use. +As C++ is very efficient, the core engine will be written in C++, and +exposed to the Research layer via `pybind11`. diff --git a/README.md b/README.md index 5efe65c..d1bb550 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # pricing -Monte Carlo pricing of European options under Black–Scholes \ No newline at end of file +Monte Carlo pricing of European options under Black–Scholes + +### Project structure diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..73539b5 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(qengine + black_scholes.cpp + monte_carlo.cpp + payoff.cpp + main.cpp +) + +target_include_directories(qengine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(qengine Eigen3::Eigen) \ No newline at end of file diff --git a/src/black_scholes.cpp b/src/black_scholes.cpp new file mode 100644 index 0000000..96fe5ac --- /dev/null +++ b/src/black_scholes.cpp @@ -0,0 +1,5 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#include "black_scholes.hpp" \ No newline at end of file diff --git a/src/black_scholes.hpp b/src/black_scholes.hpp new file mode 100644 index 0000000..e207d04 --- /dev/null +++ b/src/black_scholes.hpp @@ -0,0 +1,30 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#ifndef OPTION_PRICING_BLACK_SCHOLES_HPP +#define OPTION_PRICING_BLACK_SCHOLES_HPP + +#include + +class BlackScholes { +public: + BlackScholes(double S0, double r, double sigma, double T) + : S0_(S0), r_(r), sigma_(sigma), T_(T) {} + + double terminal_price(double Z) const { + return S0_ * std::exp( + (r_ - 0.5 * sigma_ * sigma_) * T_ + + sigma_ * std::sqrt(T_) * Z + ); + } + + double discount() const { + return std::exp(-r_ * T_); + } + +private: + double S0_, r_, sigma_, T_; +}; + +#endif //OPTION_PRICING_BLACK_SCHOLES_HPP \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..cfb565e --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,22 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#include "black_scholes.hpp" +#include "monte_carlo.hpp" +#include "payoff.hpp" +#include + +int main() { + + BlackScholes model(100.0, 0.05, 0.2, 1.0); + CallPayoff payoff(100.0); + + MonteCarloEngine mc; + + double price = mc.price(model, payoff, 1000000); + + std::cout << "MC Price: " << price << std::endl; + + return 0; +} \ No newline at end of file diff --git a/src/monte_carlo.cpp b/src/monte_carlo.cpp new file mode 100644 index 0000000..a24d7bd --- /dev/null +++ b/src/monte_carlo.cpp @@ -0,0 +1,5 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#include "monte_carlo.hpp" \ No newline at end of file diff --git a/src/monte_carlo.hpp b/src/monte_carlo.hpp new file mode 100644 index 0000000..81efee4 --- /dev/null +++ b/src/monte_carlo.hpp @@ -0,0 +1,36 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#ifndef OPTION_PRICING_MONTE_CARLO_HPP +#define OPTION_PRICING_MONTE_CARLO_HPP +#pragma once +#include +#include + +class MonteCarloEngine { +public: + MonteCarloEngine(unsigned long seed = 42) + : gen_(seed), dist_(0.0, 1.0) {} + + template + double price(const Model& model, + const Payoff& payoff, + std::size_t N) { + + double sum = 0.0; + + for (std::size_t i = 0; i < N; ++i) { + double Z = dist_(gen_); + double ST = model.terminal_price(Z); + sum += payoff(ST); + } + + return model.discount() * sum / N; + } + +private: + std::mt19937_64 gen_; + std::normal_distribution<> dist_; +}; +#endif //OPTION_PRICING_MONTE_CARLO_HPP \ No newline at end of file diff --git a/src/payoff.cpp b/src/payoff.cpp new file mode 100644 index 0000000..b03bf83 --- /dev/null +++ b/src/payoff.cpp @@ -0,0 +1,11 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#include "payoff.hpp" + +#include + +double CallPayoff::operator()(double ST) const { + return std::max(ST - K_, 0.0); +} diff --git a/src/payoff.hpp b/src/payoff.hpp new file mode 100644 index 0000000..10cc0fd --- /dev/null +++ b/src/payoff.hpp @@ -0,0 +1,21 @@ +// +// Created by David Doebel on 03.03.2026. +// + +#ifndef OPTION_PRICING_PAYOFF_HPP +#define OPTION_PRICING_PAYOFF_HPP +class Payoff { +public: + virtual double operator()(double ST) const = 0; + virtual ~Payoff() = default; +}; + +class CallPayoff : public Payoff { +public: + CallPayoff(double K) : K_(K) {} + + double operator()(double ST) const override; +private: + double K_; +}; +#endif //OPTION_PRICING_PAYOFF_HPP \ No newline at end of file