2424
2525using namespace lfmc ;
2626
27- static constexpr double S0 = 100.0 ;
28- static constexpr double MU = 0.05 ;
29- static constexpr double SIGMA = 0.2 ;
30- static constexpr double K = 100.0 ;
31- static constexpr double T = 1.0 ;
32- static constexpr size_t STEPS = 52 ;
27+ static constexpr double S0 = 100.0 ;
28+ static constexpr double MU = 0.05 ;
29+ static constexpr double SIGMA = 0.2 ;
30+ static constexpr double K = 100.0 ;
31+ static constexpr double T = 1.0 ;
32+ static constexpr size_t STEPS = 52 ;
3333static const double CONTROL_MEAN = S0 * std::exp (MU * T);
3434
3535static GeometricBrownianMotion GBM {MU , SIGMA , S0 };
@@ -43,8 +43,8 @@ struct BenchResult {
4343 double std_error_of_mean;
4444};
4545
46- BenchResult bench_fixed (const std::string& name, SamplerFn sampler,
47- double ref_mean, size_t N, size_t RUNS ) {
46+ BenchResult bench_fixed (const std::string& name, SamplerFn sampler, double ref_mean, size_t N,
47+ size_t RUNS ) {
4848 std::vector<double > errors;
4949 errors.reserve (RUNS );
5050 double sum_est = 0.0 ;
@@ -60,13 +60,15 @@ BenchResult bench_fixed(const std::string& name, SamplerFn sampler,
6060 // std error of the MSE estimate (rough)
6161 double mean_err2 = mse;
6262 double sq_sum = 0.0 ;
63- for (double e2 : errors) { double d = e2 - mean_err2; sq_sum += d*d; }
64- double sem = std::sqrt (sq_sum / static_cast <double >(RUNS * (RUNS -1 )));
63+ for (double e2 : errors) {
64+ double d = e2 - mean_err2;
65+ sq_sum += d * d;
66+ }
67+ double sem = std::sqrt (sq_sum / static_cast <double >(RUNS * (RUNS - 1 )));
6568 return {name, mse, sum_est / RUNS , sem};
6669}
6770
68- BenchResult bench_asvr (std::shared_ptr<Payoff> payoff, double ref_mean,
69- size_t N, size_t RUNS ) {
71+ BenchResult bench_asvr (std::shared_ptr<Payoff> payoff, double ref_mean, size_t N, size_t RUNS ) {
7072 std::vector<double > errors;
7173 errors.reserve (RUNS );
7274 double sum_est = 0.0 ;
@@ -83,20 +85,23 @@ BenchResult bench_asvr(std::shared_ptr<Payoff> payoff, double ref_mean,
8385 double mse = std::accumulate (errors.begin (), errors.end (), 0.0 ) / static_cast <double >(RUNS );
8486 double mean_err2 = mse;
8587 double sq_sum = 0.0 ;
86- for (double e2 : errors) { double d = e2 - mean_err2; sq_sum += d*d; }
87- double sem = std::sqrt (sq_sum / static_cast <double >(RUNS * (RUNS -1 )));
88+ for (double e2 : errors) {
89+ double d = e2 - mean_err2;
90+ sq_sum += d * d;
91+ }
92+ double sem = std::sqrt (sq_sum / static_cast <double >(RUNS * (RUNS - 1 )));
8893 return {" ASVR" , mse, sum_est / RUNS , sem};
8994}
9095
91- void run_option_bench (const std::string& opt_name, std::shared_ptr<Payoff> payoff,
92- size_t N, size_t RUNS ) {
96+ void run_option_bench (const std::string& opt_name, std::shared_ptr<Payoff> payoff, size_t N,
97+ size_t RUNS ) {
9398 printf (" \n === %-35s (N=%zu, runs=%zu) ===\n " , opt_name.c_str (), N, RUNS );
9499
95100 // Reference from 500k plain MC samples
96101 auto plain_ref_fn = make_plain_mc_sampler (GBM , EULER , payoff, STEPS , T);
97102 auto ref_samples = plain_ref_fn (500'000 , detail::make_seed (0 , 99 ));
98- double ref_mean = std::accumulate (ref_samples.begin (), ref_samples.end (), 0.0 )
99- / static_cast <double >(ref_samples.size ());
103+ double ref_mean = std::accumulate (ref_samples.begin (), ref_samples.end (), 0.0 ) /
104+ static_cast <double >(ref_samples.size ());
100105 printf (" Reference mean: %.6f\n " , ref_mean);
101106
102107 auto strategies = build_all_strategies (GBM , EULER , payoff, CONTROL_MEAN , STEPS , T);
@@ -111,47 +116,49 @@ void run_option_bench(const std::string& opt_name, std::shared_ptr<Payoff> payof
111116 results.push_back (bench_asvr (payoff, ref_mean, N, RUNS ));
112117
113118 // Sort by MSE ascending
114- std::sort (results.begin (), results.end (),
115- [](const BenchResult& a, const BenchResult& b) {
116- return a.mean_sq_error < b.mean_sq_error ;
117- });
119+ std::sort (results.begin (), results.end (), [](const BenchResult& a, const BenchResult& b) {
120+ return a.mean_sq_error < b.mean_sq_error ;
121+ });
118122
119123 double plain_mse = 0.0 ;
120- for (auto & r : results) if (r.name == " plain_mc" ) plain_mse = r.mean_sq_error ;
124+ for (auto & r : results)
125+ if (r.name == " plain_mc" )
126+ plain_mse = r.mean_sq_error ;
121127
122128 printf (" %-28s %12s %8s %8s\n " , " Strategy" , " MSE" , " vs PlainMC" , " vs ASVR" );
123- printf (" %-28s %12s %8s %8s\n " ,
124- std::string (28 ,' -' ).c_str (), std::string (12 ,' -' ).c_str (),
125- std::string (8 ,' -' ).c_str (), std::string (8 ,' -' ).c_str ());
129+ printf (" %-28s %12s %8s %8s\n " , std::string (28 , ' -' ).c_str (), std::string (12 , ' -' ).c_str (),
130+ std::string (8 , ' -' ).c_str (), std::string (8 , ' -' ).c_str ());
126131
127132 double asvr_mse = 0.0 ;
128- for (auto & r : results) if (r.name == " ASVR" ) asvr_mse = r.mean_sq_error ;
133+ for (auto & r : results)
134+ if (r.name == " ASVR" )
135+ asvr_mse = r.mean_sq_error ;
129136
130137 for (auto & r : results) {
131138 double vs_plain = plain_mse / r.mean_sq_error ;
132- double vs_asvr = asvr_mse / r.mean_sq_error ;
133- printf (" %-28s %12.6f %8.3fx %8.3fx\n " ,
134- r. name . c_str (), r. mean_sq_error , vs_plain, vs_asvr);
139+ double vs_asvr = asvr_mse / r.mean_sq_error ;
140+ printf (" %-28s %12.6f %8.3fx %8.3fx\n " , r. name . c_str (), r. mean_sq_error , vs_plain,
141+ vs_asvr);
135142 }
136143}
137144
138145int main () {
139- const size_t N = 10'000 ; // sample budget per trial
140- const size_t RUNS = 200 ; // trials for MSE estimate
146+ const size_t N = 10'000 ; // sample budget per trial
147+ const size_t RUNS = 200 ; // trials for MSE estimate
141148
142149 printf (" ASVR vs Fixed Strategy Benchmark\n " );
143150 printf (" =================================\n " );
144151 printf (" Budget N=%zu per trial, %zu independent runs\n " , N, RUNS );
145152 printf (" Strategies compared: all 10 fixed + ASVR (adaptive)\n " );
146153
147- run_option_bench (" European Call" , std::make_shared<EuropeanCall>(K), N, RUNS );
148- run_option_bench (" European Put" , std::make_shared<EuropeanPut>(K), N, RUNS );
149- run_option_bench (" Asian Call" , std::make_shared<AsianCall>(K), N, RUNS );
150- run_option_bench (" Asian Put" , std::make_shared<AsianPut>(K), N, RUNS );
151- run_option_bench (" Up-And-Out Call B=130" , std::make_shared<UpAndOutCall>(K, 130.0 ), N, RUNS );
152- run_option_bench (" Down-And-In Put B=70" , std::make_shared<DownAndInPut>(K, 70.0 ), N, RUNS );
153- run_option_bench (" Lookback Call" , std::make_shared<LookbackCall>(), N, RUNS );
154- run_option_bench (" Lookback Put" , std::make_shared<LookbackPut>(), N, RUNS );
154+ run_option_bench (" European Call" , std::make_shared<EuropeanCall>(K), N, RUNS );
155+ run_option_bench (" European Put" , std::make_shared<EuropeanPut>(K), N, RUNS );
156+ run_option_bench (" Asian Call" , std::make_shared<AsianCall>(K), N, RUNS );
157+ run_option_bench (" Asian Put" , std::make_shared<AsianPut>(K), N, RUNS );
158+ run_option_bench (" Up-And-Out Call B=130" , std::make_shared<UpAndOutCall>(K, 130.0 ), N, RUNS );
159+ run_option_bench (" Down-And-In Put B=70" , std::make_shared<DownAndInPut>(K, 70.0 ), N, RUNS );
160+ run_option_bench (" Lookback Call" , std::make_shared<LookbackCall>(), N, RUNS );
161+ run_option_bench (" Lookback Put" , std::make_shared<LookbackPut>(), N, RUNS );
155162
156163 printf (" \n Done.\n " );
157164 return 0 ;
0 commit comments