1919
2020namespace lfmc {
2121
22- template <StochasticProcess P, NumericalScheme<P> S, Payoff PO , RandomGenerator RNG = PseudoRandom>
22+ template <StochasticProcess P = GeometricBrownianMotion, NumericalScheme<P> S = EulerMaruyama<P>,
23+ RandomGenerator RNG = PseudoRandom, Payoff PO = EuropeanCall>
2324class Manager {
2425 private:
2526 P process_;
@@ -31,59 +32,26 @@ class Manager {
3132 std::vector<std::unique_ptr<EstimatorInterface>> simulators_;
3233
3334 public:
34- explicit Manager (P process, S scheme, PO payoff, RNG randomGenerator, State state ) noexcept
35+ explicit Manager (P process, S scheme, PO payoff, State state, RNG randomGenerator ) noexcept
3536 : process_(std::move(process)), scheme_(std::move(scheme)), payoff_(std::move(payoff)),
36- randomGenerator_(std::move(randomGenerator)), state_(state ) {}
37+ state_(state), randomGenerator_(std::move(randomGenerator)) {}
3738 explicit Manager (P process, S scheme, PO payoff, State state) noexcept
3839 : process_(std::move(process)), scheme_(std::move(scheme)), payoff_(std::move(payoff)),
39- randomGenerator_( ), state_(state ) {}
40+ state_(state ), randomGenerator_( ) {}
4041
41- // TODO better way to do this without passing in all the same parameters to each
42- // simulator?
43- // Maybe a factory pattern or something? Or maybe pass in a config struct?
44- double simulate (size_t numSimulations = 1000 ) {
45- simulators_.clear ();
46- simulators_.reserve (numSimulations);
42+ // TODO better configuration for number of simulations
43+ double simulate (const ManagerConfig& config) {
44+ size_t numSimulations =
45+ config.numNoVarianceReductionSimulations + config.numAntitheticVariatesSimulations ;
4746
4847 // Create simulators
49- for (size_t i{}; i < numSimulations ; ++i) {
48+ for (size_t i{}; i < config. numNoVarianceReductionSimulations ; ++i) {
5049 simulators_.push_back (
51- std::make_unique<Estimator<P, S>>(process_, scheme_, payoff_ , state_));
50+ std::make_unique<Estimator<P, S, RNG >>(process_, scheme_, state_));
5251 }
53-
54- // Run simulations
55- std::vector<Path> results;
56- results.reserve (numSimulations);
57- for (auto & simulator : simulators_) {
58- std::vector<Path> paths = simulator->sample ();
59- for (const auto & path : paths) {
60- results.push_back (path);
61- }
62- }
63-
64- // Payoffs
65- std::vector<double > payoffs;
66- payoffs.reserve (results.size ());
67- for (const auto & path : results) {
68- payoffs.push_back (payoff_ (path));
69- }
70-
71- double mean = std::accumulate (payoffs.begin (), payoffs.end (), 0.0 ) /
72- static_cast <double >(numSimulations);
73-
74- return mean;
75- }
76-
77- // TODO temporary simulate with antithetic variates for now, but will need to be redesigned to
78- // support more variance reduction techniques and passing changing a simulator's type
79- std::pair<double , double > simulateWithAntithetic (size_t numSimulations = 1000 ) {
80- simulators_.clear ();
81- simulators_.reserve (numSimulations);
82-
83- // Create simulators with antithetic variates
84- for (size_t i{}; i < numSimulations; ++i) {
52+ for (size_t i{}; i < config.numAntitheticVariatesSimulations ; ++i) {
8553 simulators_.push_back (std::make_unique<AntitheticVariates>(
86- std::make_unique<Estimator<P, S>>(process_, scheme_, state_)));
54+ std::make_unique<Estimator<P, S, RNG >>(process_, scheme_, state_)));
8755 }
8856
8957 // Run simulations
@@ -103,29 +71,24 @@ class Manager {
10371 payoffs.push_back (payoff_ (path));
10472 }
10573
106- // Calculate mean and standard error
10774 double mean = std::accumulate (payoffs.begin (), payoffs.end (), 0.0 ) /
108- static_cast <double >(payoffs.size ());
109-
110- if (results.size () < 2 )
111- return {mean, 0.0 };
112-
113- double variance = 0.0 ;
114- for (const auto & r : payoffs)
115- variance += (r - mean) * (r - mean);
116- variance /= static_cast <double >(results.size () - 1 );
117- double stdError = std::sqrt (variance / static_cast <double >(results.size ()));
75+ static_cast <double >(numSimulations);
11876
119- return { mean, stdError} ;
77+ return mean;
12078 }
12179
122- std::pair<double , double > simulateWithError (size_t numSimulations = 1000 ) {
123- simulators_. clear ();
124- simulators_. reserve (numSimulations) ;
80+ std::pair<double , double > simulateWithError (const ManagerConfig& config ) {
81+ size_t numSimulations =
82+ config. numNoVarianceReductionSimulations + config. numAntitheticVariatesSimulations ;
12583
12684 // Create simulators
127- for (size_t i{}; i < numSimulations; ++i) {
128- simulators_.push_back (std::make_unique<Estimator<P, S>>(process_, scheme_, state_));
85+ for (size_t i{}; i < config.numNoVarianceReductionSimulations ; ++i) {
86+ simulators_.push_back (
87+ std::make_unique<Estimator<P, S, RNG >>(process_, scheme_, state_));
88+ }
89+ for (size_t i{}; i < config.numAntitheticVariatesSimulations ; ++i) {
90+ simulators_.push_back (std::make_unique<AntitheticVariates>(
91+ std::make_unique<Estimator<P, S, RNG >>(process_, scheme_, state_)));
12992 }
13093
13194 // Run simulations
0 commit comments