Skip to content

Commit 67f2d99

Browse files
Merge pull request #31 from anthonymakarewicz/feature/solver_MC
Feature/solver mc
2 parents e12163f + 4d6fac0 commit 67f2d99

File tree

129 files changed

+2098
-1208
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+2098
-1208
lines changed

.github/workflows/pr_ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
cmake-version: '3.26.3'
3333

3434
- name: Install dependencies
35-
run: sudo apt-get install -y libgtest-dev libgmock-dev libboost-all-dev
35+
run: sudo apt-get install -y libgtest-dev libgmock-dev libboost-all-dev libeigen3-dev
3636

3737
- name: Configure CMake
3838
run: |

.github/workflows/push_ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
cmake-version: '3.26.3'
2121

2222
- name: Install dependencies
23-
run: sudo apt-get install -y libgtest-dev libgmock-dev libboost-all-dev
23+
run: sudo apt-get install -y libgtest-dev libgmock-dev libboost-all-dev libeigen3-dev
2424

2525
- name: Configure CMake
2626
run: |

CMakeLists.txt

+24-21
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(CMAKE_TOOLCHAIN_FILE "/Users/anthony/.vcpkg-clion/vcpkg/scripts/buildsystems
1515
CACHE STRING "Vcpkg toolchain file")
1616

1717
find_package(Boost REQUIRED COMPONENTS random)
18+
find_package(Eigen3 REQUIRED)
1819

1920
# Check if random has been found before compiling src
2021
if (Boost_FOUND)
@@ -39,24 +40,18 @@ add_library(marketdata SHARED
3940
src/market_data/market_data.cpp
4041
src/market_data/market_data_observer.cpp
4142
src/market_data/stock_data.cpp
43+
include/solver/monte_carlo/builder/mc_builder_american.h
4244
)
4345

4446
# Create dynamic library for payoff
4547
add_library(payoff SHARED
4648
src/payoff/base_payoff.cpp
49+
src/payoff/payoff_floating_strike_lookback.cpp
4750
src/payoff/single_strike/base_payoff_single_strike.cpp
48-
src/payoff/single_strike/base_payoff_vanilla.cpp
49-
src/payoff/single_strike/payoff_vanilla_call.cpp
50-
src/payoff/single_strike/payoff_vanilla_put.cpp
51-
src/payoff/single_strike/base_payoff_digital.cpp
52-
src/payoff/single_strike/payoff_digital_call.cpp
53-
src/payoff/single_strike/payoff_digital_put.cpp
51+
src/payoff/single_strike/payoff_vanilla.cpp
52+
src/payoff/single_strike/payoff_digital.cpp
5453
src/payoff/double_strikes/base_payoff_double_strikes.cpp
5554
src/payoff/double_strikes/payoff_double_digital.cpp
56-
# Factories
57-
src/payoff/single_strike/factory_payoff_vanilla.cpp
58-
src/payoff/single_strike/factory_payoff_digital.cpp
59-
src/payoff/double_strikes/factory_payoff_double_digital.cpp
6055
)
6156

6257
# Create dynamic library for option, linking against marketdata and payoff
@@ -72,42 +67,50 @@ add_library(option SHARED
7267
src/option/path_dependent/american_option.cpp
7368
src/option/path_dependent/asian_option.cpp
7469
src/option/path_dependent/barrier_option.cpp
70+
src/option/path_dependent/lookback_option.cpp
7571
# Factories
76-
src/option/factory_option.cpp
7772
src/option/single_path/factory_european_option.cpp
7873
src/option/single_path/factory_digital_option.cpp
7974
src/option/single_path/factory_double_digital_option.cpp
8075
src/option/path_dependent/factory_american_option.cpp
8176
src/option/path_dependent/factory_asian_option.cpp
8277
src/option/path_dependent/factory_barrier_option.cpp
78+
src/option/path_dependent/factory_lookback_option.cpp
8379
)
8480

8581
# Create dynamic library for marketdata
8682
add_library(solver SHARED
8783
src/solver/base_solver.cpp
8884
src/solver/monte_carlo/mc_solver.cpp
89-
include/solver/monte_carlo/mc_base_strategy.h
90-
src/solver/monte_carlo/mc_base_strategy.cpp
91-
include/solver/monte_carlo/stock_price_model.h
9285
src/solver/monte_carlo/stock_price_model.cpp
9386
src/solver/monte_carlo/gbm_stock_price_model.cpp
94-
include/solver/monte_carlo/gbm_stock_price_model.h
95-
include/solver/monte_carlo/generator.h
96-
87+
src/solver/monte_carlo/base_mc.cpp
88+
src/solver/monte_carlo/mc_single_path.cpp
89+
src/solver/monte_carlo/base_mc_path_dependent.cpp
90+
src/solver/monte_carlo/mc_asian.cpp
91+
src/solver/monte_carlo/mc_barrier.cpp
92+
src/solver/monte_carlo/mc_lookback.cpp
93+
src/solver/monte_carlo/mc_american.cpp
94+
src/solver/monte_carlo/builder/base_mc_builder.cpp
95+
src/solver/monte_carlo/builder/mc_builder_single_path.cpp
96+
src/solver/monte_carlo/builder/base_mc_builder_path_dependent.cpp
97+
src/solver/monte_carlo/builder/mc_builder_asian.cpp
98+
src/solver/monte_carlo/builder/mc_builder_barrier.cpp
99+
src/solver/monte_carlo/builder/mc_builder_lookback.cpp
100+
src/solver/monte_carlo/builder/mc_builder_american.cpp
97101
)
98102

99-
# Link random library to the solver ONLY
100-
target_link_libraries(solver PUBLIC Boost::random)
101-
102103
# Link the option library against marketdata and payoff
103104
target_link_libraries(option PUBLIC marketdata payoff)
104105

106+
# Link random library to the solver ONLY
107+
target_link_libraries(solver PUBLIC option Boost::random Eigen3::Eigen)
108+
105109
# Create main executable
106110
add_executable(Option_pricer main.cpp)
107111

108112
# Link the main executable to our dynamic libraries
109113
target_link_libraries(Option_pricer PUBLIC marketdata payoff option solver)
110-
#target_link_libraries(Option_pricer marketdata payoff option solver)
111114

112115
# Enable testing and add the tests directory
113116
enable_testing()

examples/notebooks/.ipynb_checkpoints/sobol-checkpoint.ipynb

+6-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"metadata": {},
2222
"outputs": [],
2323
"source": [
24-
"output_dir = Path(\"/Users/anthony/CLionProjects/Option_pricer/examples/output\")\n",
24+
"output_path = \"/Users/anthony/CLionProjects/Option_pricer/examples/output\"\n",
25+
"output_dir = Path(output_path)\n",
2526
"sequences_2_file = output_dir / \"sequences_2.csv\"\n",
2627
"sequences_50_file = output_dir / \"sequences_50.csv\""
2728
]
@@ -33,8 +34,9 @@
3334
"metadata": {},
3435
"outputs": [],
3536
"source": [
36-
"sequences_2 = pd.read_csv(sequences_2_file, index_col=[\"Sample\", \"Dimension\"])\n",
37-
"sequences_50 = pd.read_csv(sequences_50_file, index_col=[\"Sample\", \"Dimension\"])"
37+
"cols = [\"Sample\", \"Dimension\"]\n",
38+
"sequences_2 = pd.read_csv(sequences_2_file, index_col=cols)\n",
39+
"sequences_50 = pd.read_csv(sequences_50_file, index_col=cols)"
3840
]
3941
},
4042
{
@@ -344,7 +346,7 @@
344346
" # Plot configuration\n",
345347
" num_rows = len(sample_sizes)\n",
346348
" num_cols = 3\n",
347-
" sequence_cols = ['Sobol', 'Faure', 'Uniform']\n",
349+
" sequence_cols = [\"Sobol\", \"Faure\", \"Uniform\"]\n",
348350
" \n",
349351
" # Create a plot grid based on the number of sample sizes and sequence types\n",
350352
" num_rows = len(sample_sizes)\n",

examples/notebooks/sobol.ipynb

+6-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"metadata": {},
2222
"outputs": [],
2323
"source": [
24-
"output_dir = Path(\"/Users/anthony/CLionProjects/Option_pricer/examples/output\")\n",
24+
"output_path = \"/Users/anthony/CLionProjects/Option_pricer/examples/output\"\n",
25+
"output_dir = Path(output_path)\n",
2526
"sequences_2_file = output_dir / \"sequences_2.csv\"\n",
2627
"sequences_50_file = output_dir / \"sequences_50.csv\""
2728
]
@@ -33,8 +34,9 @@
3334
"metadata": {},
3435
"outputs": [],
3536
"source": [
36-
"sequences_2 = pd.read_csv(sequences_2_file, index_col=[\"Sample\", \"Dimension\"])\n",
37-
"sequences_50 = pd.read_csv(sequences_50_file, index_col=[\"Sample\", \"Dimension\"])"
37+
"cols = [\"Sample\", \"Dimension\"]\n",
38+
"sequences_2 = pd.read_csv(sequences_2_file, index_col=cols)\n",
39+
"sequences_50 = pd.read_csv(sequences_50_file, index_col=cols)"
3840
]
3941
},
4042
{
@@ -344,7 +346,7 @@
344346
" # Plot configuration\n",
345347
" num_rows = len(sample_sizes)\n",
346348
" num_cols = 3\n",
347-
" sequence_cols = ['Sobol', 'Faure', 'Uniform']\n",
349+
" sequence_cols = [\"Sobol\", \"Faure\", \"Uniform\"]\n",
348350
" \n",
349351
" # Create a plot grid based on the number of sample sizes and sequence types\n",
350352
" num_rows = len(sample_sizes)\n",

include/market_data/interface_market_data.h

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "market_data_observer.h"
88

99
namespace OptionPricer {
10+
1011
// Interface injection for production and mock object for unit test
1112
class IMarketData {
1213
public:
@@ -19,6 +20,7 @@ namespace OptionPricer {
1920
[[nodiscard]] virtual double getR() const = 0;
2021
virtual void setR(const double& r) = 0;
2122
};
23+
2224
}
2325

2426
#endif //INTERFACE_MARKET_DATA_H

include/market_data/market_data.h

+2-11
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,10 @@
1414
#include "interface_market_data.h"
1515

1616
namespace OptionPricer {
17+
1718
// Declare MarketData as Singleton
1819
class MarketData final: public IMarketData {
1920
public:
20-
/** @brief MarketData Singleton class
21-
*
22-
* This class serves as a centralized location where all MarketData object will be stored
23-
* and updated and acces by all MarketDataObserver subclasses instances.
24-
* Specifically, only 1 instance of the MarketData object will be created when our program
25-
* will execute be stored as a shared_ptr that all our Options will own the adress of it.
26-
*
27-
* This MarketData data will notify all the Option when StockData used for those Options
28-
* will change.
29-
*
30-
*/
3121
static std::shared_ptr<MarketData> getInstance();
3222
~MarketData() override;
3323

@@ -67,6 +57,7 @@ namespace OptionPricer {
6757
std::unordered_map<std::string, std::shared_ptr<StockData>> stockDataMap_; // Map ticker symbol to StockData
6858
std::vector<std::weak_ptr<MarketDataObserver>> observers_; // Use weak_ptr to avoid circular references
6959
};
60+
7061
}
7162

7263
#endif //MARKET_DATA_H

include/market_data/market_data_observer.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <string>
55

66
namespace OptionPricer {
7-
// Observer of MarketData
7+
88
class MarketDataObserver {
99
public:
1010
explicit MarketDataObserver(const std::string& id);
@@ -16,6 +16,7 @@ namespace OptionPricer {
1616
protected:
1717
std::string id_;
1818
};
19+
1920
}
2021

2122
#endif //MARKET_DATA_OBSERVER_H

include/market_data/stock_data.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ namespace OptionPricer {
1111
const double& sigma,
1212
const std::optional<double>& c = std::nullopt);
1313

14-
// Prefix guetters with nodiscard C++17
1514
[[nodiscard]] double getPrice() const;
1615
[[nodiscard]] double getSigma() const;
1716
[[nodiscard]] std::optional<double> getCoupon() const;
17+
1818
friend std::ostream& operator<<(std::ostream& os, const StockData& stockData);
1919
bool operator==(const StockData& other) const;
2020
bool operator!=(const StockData& other) const;

include/option/base_factory_option.h

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#ifndef FACTORY_OPTION_H
2+
#define FACTORY_OPTION_H
3+
4+
#include <string>
5+
#include <concepts>
6+
#include "payoff/base_payoff.h"
7+
#include "option/base_option.h"
8+
#include "option/parameter_object.h"
9+
#include "market_data/market_data.h"
10+
11+
namespace OptionPricer {
12+
13+
// Define a concept for an Option type
14+
template <typename T>
15+
concept OptionTypeConcept = std::is_base_of_v<Option, T>;
16+
17+
template<OptionTypeConcept OptionType> class OptionFactory {
18+
public:
19+
virtual ~OptionFactory() = default;
20+
21+
// Non-static create methods as we use virtual methods
22+
[[nodiscard]] std::shared_ptr<OptionType> createCallOption(const ParameterObject& params);
23+
[[nodiscard]] std::shared_ptr<OptionType> createPutOption(const ParameterObject& params);
24+
25+
protected:
26+
// Template method pattern
27+
std::shared_ptr<OptionType> createOption(const ParameterObject& params, const PayoffType& type);
28+
29+
// Can be overiden to add extra parameters
30+
virtual std::string invalidParams(const std::string& option_type) const;
31+
32+
// To be overidden in concrete factories
33+
virtual std::unique_ptr<Payoff> createSpecificPayoff(const ParameterObject& params,
34+
const PayoffType& type) = 0;
35+
virtual std::shared_ptr<OptionType> createSpecificOption(const ParameterObject& params,
36+
std::unique_ptr<Payoff> payoff,
37+
const std::shared_ptr<IMarketData>& marketData) = 0;
38+
virtual std::string getType(const PayoffType& type) const = 0;
39+
};
40+
41+
42+
template <OptionTypeConcept OptionType>
43+
std::shared_ptr<OptionType> OptionFactory<OptionType>::createCallOption(const ParameterObject &params) {
44+
return createOption(params, PayoffType::Call);
45+
}
46+
47+
template <OptionTypeConcept OptionType>
48+
std::shared_ptr<OptionType> OptionFactory<OptionType>::createPutOption(const ParameterObject &params) {
49+
return createOption(params, PayoffType::Put);
50+
}
51+
52+
template <OptionTypeConcept OptionType>
53+
std::shared_ptr<OptionType> OptionFactory<OptionType>::createOption(const ParameterObject &params,
54+
const PayoffType& type) {
55+
auto marketData = MarketData::getInstance();
56+
std::shared_ptr<OptionType> option = nullptr;
57+
58+
try {
59+
auto payoff = createSpecificPayoff(params, type);
60+
option = createSpecificOption(params, std::move(payoff), marketData);
61+
} catch (const std::invalid_argument& e) {
62+
const std::string err = std::string(e.what()) + "\n" + invalidParams(getType(type));
63+
throw std::invalid_argument(err);
64+
}
65+
66+
option->initialize();
67+
return option;
68+
}
69+
70+
template <OptionTypeConcept OptionType>
71+
std::string OptionFactory<OptionType>::invalidParams(const std::string &option_type) const {
72+
return "Invalid parameters for " + option_type + "\n"
73+
"Expected parameters:\n"
74+
" - ticker (string) for ticker symbol\n"
75+
" - T (double) for maturity\n"
76+
" - K (double) for strike\n";
77+
}
78+
79+
}
80+
81+
#endif //FACTORY_OPTION_H

include/option/base_option.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "market_data/interface_market_data.h"
77

88
namespace OptionPricer {
9+
910
// Option asbtract base class where *this must be managed by a shared_ptr
1011
class Option : public MarketDataObserver, public std::enable_shared_from_this<Option> {
1112
public:
@@ -45,11 +46,12 @@ namespace OptionPricer {
4546
virtual double calc_price() const = 0; // Force all subclasses to deifne this method
4647

4748
void initialize();
48-
[[nodiscard]] std::string getType() const;
49-
[[nodiscard]] double getT() const;
49+
std::string getType() const;
50+
[[nodiscard]] const Payoff& getPayoff() const;
51+
double getT() const;
5052

51-
double payoff() const;
5253
double payoff(const double& S) const;
54+
double payoff(const double& S, const double& extremeS) const;
5355

5456
protected:
5557
Option(const std::string& ticker, std::unique_ptr<Payoff> payoff, const double& T,
@@ -59,6 +61,7 @@ namespace OptionPricer {
5961
std::unique_ptr<Payoff> payoff_; // Unique ptr to Payoff functor
6062
std::shared_ptr<IMarketData> marketData_; // Shared ptr to IMarketData interface
6163
};
64+
6265
};
6366

6467
#endif //BASE_OPTION_H

0 commit comments

Comments
 (0)