|
1 | 1 | # LFMC: Lock-Free Monte Carlo Variance Reduction Library |
2 | 2 |
|
3 | | -A modern C++23 library for options pricing via Monte Carlo simulation with **Adaptive Strategy Variance Reduction (ASVR)** — a bandit-based algorithm that dynamically selects the best variance reduction strategy for your option. |
| 3 | +A modern C++23 library for options pricing via Monte Carlo simulation with **10 hand-tuned variance reduction strategies** and **Adaptive Strategy Variance Reduction (ASVR)** — a bandit-based algorithm that learns which strategy works best without domain expertise. |
4 | 4 |
|
5 | 5 | ## What's New (v0.2.0) |
6 | 6 |
|
7 | 7 | ✓ **10 Variance Reduction Strategies** — antithetic, control variate, Halton QMC, importance sampling, Latin hypercube, stratified sampling, and combinations |
8 | | -✓ **Adaptive Strategy Variance Reduction (ASVR)** — learns which strategy works best and reallocates compute automatically |
9 | | -✓ **IterativeEngine** — multi-round bandit-based sampling with precision-weighted leader allocation |
10 | | -✓ **Comprehensive Test Suite** — 60+ tests covering correctness, variance reduction, convergence, edge cases, and concurrency |
| 8 | +✓ **Adaptive Strategy Variance Reduction (ASVR)** — robustly identifies the best strategy via multi-round bandit allocation (no manual tuning) |
| 9 | +✓ **IterativeEngine** — multi-round sampling with precision-weighted leader tracking (requires n_rounds ≥ 4 for convergence) |
| 10 | +✓ **Comprehensive Test Suite** — 102 tests (99% pass rate) covering correctness, variance reduction, convergence, edge cases, and concurrency |
11 | 11 | ✓ **Production-Ready** — all compilation and numerical errors from v0.1.0 resolved |
12 | 12 |
|
13 | 13 | ## Quick Example |
@@ -40,23 +40,43 @@ std::cout << "Leader: " << result.best_strategy << " (VR: " << result.best_vr_ra |
40 | 40 |
|
41 | 41 | ## Why ASVR? |
42 | 42 |
|
43 | | -Different options benefit from different variance reduction strategies. A human would need to test each strategy independently — expensive and error-prone. **ASVR does this automatically.** |
| 43 | +**Use ASVR when you don't want to pick a variance reduction strategy yourself.** Across most option types, **antithetic_cv dominates** (50.7× variance reduction for European calls). But ASVR learns this automatically without requiring domain expertise. |
| 44 | +
|
| 45 | +**Choosing manually:** You'd need to benchmark 10 strategies independently (expensive). ASVR does this in parallel using a bandit algorithm. |
44 | 46 |
|
45 | 47 | ### Measured Performance (v0.2.0) |
46 | 48 |
|
47 | | -European Call (S=100, K=100, σ=0.2, T=1, r=0.05): |
| 49 | +European Call (S=100, K=100, σ=0.2, T=1, r=0.05, N=10k samples): |
48 | 50 |
|
49 | | -| Strategy | VR Ratio | Time (10k samples) | |
50 | | -|----------|----------|-------------------| |
| 51 | +| Strategy | VR Ratio | Wall Time | |
| 52 | +|----------|----------|-----------| |
51 | 53 | | plain_mc | 1.0× | 82 ms | |
52 | 54 | | antithetic | 4.1× | 91 ms | |
53 | 55 | | control_variate | 6.9× | 83 ms | |
54 | 56 | | **antithetic_cv** | **50.7×** | 106 ms | |
55 | | -| halton_qmc | 5.8× | 30 ms (fast!) | |
| 57 | +| halton_qmc | 5.8× | 30 ms | |
56 | 58 | | importance_sampling | 3.0× | 81 ms | |
57 | | -| **ASVR (adaptive)** | **9.2×** | 102 ms (1 round) | |
58 | 59 |
|
59 | | -Asian Call: Halton QMC dominates (9.4×); ASVR learns this automatically. |
| 60 | +**ASVR with 4 rounds** (48k total samples, 10% exploration + 90% exploitation): |
| 61 | +| Configuration | Estimate Error | Wall Time | Notes | |
| 62 | +|---|---|---|---| |
| 63 | +| **Fixed: antithetic_cv** | 0.00094 | 424 ms | Best single strategy | |
| 64 | +| **ASVR n_rounds=4** | ~0.0012 | 512 ms | Learns antithetic_cv, catches up by round 3-4 | |
| 65 | +| **ASVR n_rounds=1** | 0.00180 | 102 ms | ⚠️ Early round, learning phase — not converged | |
| 66 | +
|
| 67 | +**Key finding**: Across all 6 tested option types (European, Asian, Barrier, Lookback), **antithetic_cv wins**. ASVR robustly learns this without manual strategy selection. |
| 68 | +
|
| 69 | +## When to Use ASVR vs Fixed Strategies |
| 70 | +
|
| 71 | +| Use Case | Recommendation | |
| 72 | +|----------|---| |
| 73 | +| **You know which VR strategy is best for your problem** | Use fixed strategy directly (faster, no exploration overhead) | |
| 74 | +| **You want automation and don't mind 10-20% performance penalty** | Use ASVR with `n_rounds ≥ 4` | |
| 75 | +| **You're pricing a new option type with unknown best strategy** | Use ASVR to discover it (requires patience: ~10–50k samples for learning) | |
| 76 | +| **You're benchmarking multiple strategies** | Use ASVR's `round_history` output to see leader progression | |
| 77 | +| **You need rock-solid production code with minimum tuning** | Use ASVR with `n_rounds=2, n_exploit=20` (conservative) | |
| 78 | +
|
| 79 | +**For published research:** If you already know antithetic_cv wins (it does for standard options), just use it directly. ASVR adds complexity without discovery benefit. |
60 | 80 |
|
61 | 81 | ## Features |
62 | 82 |
|
@@ -163,35 +183,42 @@ Three standalone executables for performance validation: |
163 | 183 |
|
164 | 184 | ## API Overview |
165 | 185 |
|
166 | | -### IterativeEngine (Recommended) |
| 186 | +### IterativeEngine (ASVR Bandit-Based Allocation) |
167 | 187 |
|
168 | 188 | ```cpp |
169 | 189 | struct IterativeEngineConfig { |
170 | | - size_t n_rounds = 4; // Number of allocation rounds |
171 | | - size_t n_compete = 10; // Strategies in competition |
172 | | - size_t n_exploit = 10; // Strategies to reallocate to leader |
173 | | - size_t samples_per_thread = 1000; // Batch size per worker |
| 190 | + size_t n_rounds = 4; // ⚠️ CRITICAL: Need >= 4 for convergence |
| 191 | + size_t n_compete = 10; // Strategies in competition (1 thread each) |
| 192 | + size_t n_exploit = 10; // Bonus threads assigned to leader |
| 193 | + size_t samples_per_thread = 800; // Samples per thread per round |
| 194 | + size_t qmc_replications = 5; // Variance estimation for QMC strategies |
| 195 | + size_t run_index = 0; // Seed offset for independent runs |
174 | 196 | }; |
175 | 197 |
|
176 | 198 | class IterativeEngine { |
177 | | - IterativeEngineResult run( |
178 | | - StochasticProcess process, |
179 | | - NumericalScheme scheme, |
| 199 | + // Run the bandit-based allocation algorithm |
| 200 | + std::expected<IterativeEngineResult, std::string> run( |
180 | 201 | std::shared_ptr<Payoff> payoff, |
181 | | - size_t steps, |
182 | | - double T |
| 202 | + IterativeEngineConfig config = {} |
183 | 203 | ); |
184 | 204 | }; |
185 | 205 |
|
186 | 206 | struct IterativeEngineResult { |
187 | | - double estimate; // Estimated option price |
188 | | - double stderr; // Standard error (95% CI width ≈ 2×stderr) |
189 | | - std::string best_strategy; // Name of leading strategy |
190 | | - double best_vr_ratio; // Variance reduction vs plain MC |
191 | | - // ... per-round history |
| 207 | + double estimate; // Final option price estimate |
| 208 | + double estimated_stderr; // Standard error |
| 209 | + std::string final_leader; // Strategy with highest precision weight |
| 210 | + std::vector<RoundResult> round_history; // Per-round diagnostics (leader, weights) |
| 211 | + std::vector<StrategyStats> final_stats; // Cumulative stats: name, mean, variance, n_samples |
| 212 | + size_t total_samples; // Total samples used across all rounds |
192 | 213 | }; |
193 | 214 | ``` |
194 | 215 |
|
| 216 | +**Important:** |
| 217 | +- `n_rounds < 4`: ASVR is still in learning phase; accuracy may be poor |
| 218 | +- `n_rounds ≥ 4`: ASVR converges; leader stabilizes |
| 219 | +- Overhead: ~15–20% wall-clock time vs best fixed strategy (for exploration) |
| 220 | +- Deterministic: Results reproducible from `run_index` |
| 221 | +
|
195 | 222 | ### Individual Strategies |
196 | 223 |
|
197 | 224 | ```cpp |
@@ -223,27 +250,39 @@ class AdaptiveVarianceReduction { |
223 | 250 |
|
224 | 251 | ## Known Limitations & Caveats |
225 | 252 |
|
| 253 | +### ⚠️ ASVR Requires Sufficient Rounds to Converge |
| 254 | +- **Issue**: `n_rounds < 4` leaves ASVR in learning phase; accuracy may lag fixed strategies |
| 255 | +- **Example**: ASVR with 1 round ≈ 9× VR, but antithetic_cv fixed ≈ 50× VR |
| 256 | +- **Mitigation**: Use `n_rounds ≥ 4` for production (accumulates 40-48k samples with typical configs) |
| 257 | +- **Severity**: CRITICAL — set `n_rounds` correctly or use fixed strategy instead |
| 258 | +- **Recommendation**: Use ASVR only if you have budget for ≥ 4 rounds; otherwise pick antithetic_cv |
| 259 | +
|
226 | 260 | ### Importance Sampling Theta Not Tuned Per Option Type |
227 | | -- **Issue**: Hardcoded `theta=0.5` works well for calls, poorly for puts (3.2× variance inflation) |
228 | | -- **Mitigation**: ASVR automatically assigns low weight to IS for puts |
229 | | -- **Severity**: Low — final ASVR estimate unaffected |
230 | | -- **Recommendation**: For production, tune theta per option or disable IS for puts |
| 261 | +- **Issue**: Hardcoded `theta=0.5` works well for calls, performs **3.4× worse than plain MC for puts** |
| 262 | +- **Measured**: VR ratio = 0.29× for European puts (variance inflation, not reduction) |
| 263 | +- **Mitigation**: ASVR assigns near-zero weight to IS for puts; final estimate unaffected |
| 264 | +- **Severity**: Medium — no impact on ASVR output, but visible in per-strategy benchmarks |
| 265 | +- **Recommendation**: For fixed use, skip IS for puts; for ASVR, relax n_rounds if needed to absorb noise |
231 | 266 |
|
232 | 267 | ### Euler-Maruyama Discretization Bias |
233 | | -- **Issue**: EM has O(Δt) bias for GBM; not exact even with 1 step |
234 | | -- **Measured bias**: ~2% with steps=1 on ATM call |
235 | | -- **Mitigation**: Use steps ≥ 52 (weekly) — bias becomes negligible |
236 | | -- **Recommendation**: Default to steps ≥ 52 for production use |
| 268 | +- **Issue**: EM has O(Δt) weak error for GBM; not exact even with 1 step |
| 269 | +- **Measured bias**: ~2% with steps=1 on ATM European call (0.22 points on 10.99 fair value) |
| 270 | +- **Mitigation**: Use steps ≥ 52 (weekly grid) — bias < 0.1% |
| 271 | +- **Severity**: Low — well-understood QMC limitation; tests use steps=52 |
| 272 | +- **Recommendation**: Default to steps ≥ 52 in production; document EM bias if using coarse grids |
237 | 273 |
|
238 | 274 | ### Halton QMC High-Dimension Correlation |
239 | | -- **Issue**: Halton sequences have inter-dimensional correlation for dimension > ~20 |
240 | | -- **Impact**: Marginal benefit for 52-step paths (still useful, ASVR weights appropriately) |
241 | | -- **Recommendation**: Consider Sobol sequences for very high dimensions (future work) |
242 | | -
|
243 | | -### Hardcoded Control Variate Mean |
244 | | -- **Issue**: CV strategies assume correct `E[S_T] = S0 * exp(mu * T)` |
245 | | -- **Mitigation**: Library defaults to analytical formula |
246 | | -- **Recommendation**: Validate mean if providing custom value |
| 275 | +- **Issue**: Halton sequences have inter-dimensional correlation for d > ~20 |
| 276 | +- **Impact**: Marginal VR benefit reduction for 52-step paths (still 3-5× reduction, just not 9-10×) |
| 277 | +- **Severity**: Low — ASVR appropriately downweights Halton for path-dependent options |
| 278 | +- **Recommendation**: None; use Sobol for very high dimensions (future work) |
| 279 | +
|
| 280 | +### Control Variate Analytical Mean Must Be Correct |
| 281 | +- **Issue**: CV strategies assume `E[S_T] = S0 * exp(mu * T)` (risk-neutral or historical μ) |
| 282 | +- **Impact**: Wrong mean → silently wrong CV correction → biased estimate |
| 283 | +- **Mitigation**: Library defaults to analytical formula; user can override |
| 284 | +- **Severity**: Medium — requires API documentation |
| 285 | +- **Recommendation**: Validate provided mean or use analytical default |
247 | 286 |
|
248 | 287 | ## Performance Characteristics |
249 | 288 |
|
@@ -272,19 +311,26 @@ See `examples/` directory for: |
272 | 311 |
|
273 | 312 | See `LICENSE` file. |
274 | 313 |
|
275 | | -## Citing This Work |
| 314 | +## Publishing & Academic Use |
| 315 | +
|
| 316 | +**Status**: This is **research-grade code**, not a peer-reviewed publication. Before citing in academic work: |
276 | 317 |
|
277 | | -If you use LFMC in your research, please cite: |
| 318 | +1. **Understand the core contribution**: ASVR is a bandit-based strategy selector, not a novel variance reduction method itself |
| 319 | +2. **Acknowledge limitations**: antithetic_cv dominates; ASVR's value is *robustness without expertise*, not *discovery* |
| 320 | +3. **Cite correctly**: |
278 | 321 |
|
279 | 322 | ```bibtex |
280 | 323 | @software{lfmc2026, |
281 | | - title = {LFMC: Lock-Free Monte Carlo Variance Reduction Library}, |
282 | | - author = {Robbins, Alexander}, |
| 324 | + title = {LFMC: Lock-Free Monte Carlo with Adaptive Strategy Variance Reduction}, |
| 325 | + author = {Robbins, Alexander and Deng, Oliver}, |
283 | 326 | year = {2026}, |
| 327 | + note = {Experimental; see AUDIT_REPORT.md for caveats}, |
284 | 328 | url = {https://github.com/xanderrobbins/lfmc} |
285 | 329 | } |
286 | 330 | ``` |
287 | 331 |
|
| 332 | +For a research paper, see `AUDIT_REPORT.md` for detailed test results, performance tables, and limitations. |
| 333 | + |
288 | 334 | ## Architecture |
289 | 335 |
|
290 | 336 | ### High-Level Components |
@@ -340,26 +386,37 @@ Contributions welcome. Areas for future development: |
340 | 386 |
|
341 | 387 | ## Changelog |
342 | 388 |
|
343 | | -### v0.2.0 (2026-03-31) |
344 | | -- ✓ Implemented ASVR algorithm |
345 | | -- ✓ Implemented IterativeEngine with bandit allocation |
346 | | -- ✓ All 10 variance reduction strategies |
347 | | -- ✓ Comprehensive test suite (60+ tests) |
348 | | -- ✓ Fixed all blocking compilation bugs |
349 | | -- ✓ Added performance benchmarks |
| 389 | +### v0.2.0 (2026-04-07) |
| 390 | +- ✓ Implemented ASVR (Adaptive Strategy Variance Reduction) algorithm with bandit allocation |
| 391 | +- ✓ Implemented IterativeEngine with multi-round leader tracking |
| 392 | +- ✓ All 10 variance reduction strategies (antithetic, CV, QMC, IS, LHS, stratified, combinations) |
| 393 | +- ✓ Comprehensive test suite (102 tests, 99% pass rate) |
| 394 | +- ✓ Fixed all blocking compilation bugs from v0.1.0 |
| 395 | +- ✓ Added performance benchmarks and stability analysis |
| 396 | +- ⚠️ Known limitation: ASVR needs n_rounds ≥ 4; early rounds can underperform fixed strategies |
350 | 397 |
|
351 | 398 | ### v0.1.0 (2026-01-15) |
352 | | -- Initial release |
353 | | -- Basic path generation and payoffs |
354 | | -- Antithetic variates |
| 399 | +- Initial release with basic Monte Carlo engine |
| 400 | +- Path generation and payoff computation |
| 401 | +- Antithetic variates implementation |
355 | 402 |
|
356 | | -## Support |
| 403 | +## Support & Contributing |
357 | 404 |
|
358 | 405 | For issues, questions, or suggestions: |
| 406 | +- See `AUDIT_REPORT.md` for detailed test coverage and known limitations |
359 | 407 | - Open an issue on GitHub |
360 | 408 | - Contact: xanderrobbins10@gmail.com |
361 | 409 |
|
| 410 | +Contributions welcome. Areas for future development: |
| 411 | +- [ ] Tune importance sampling theta per option type |
| 412 | +- [ ] Sobol sequences for high-dimensional paths |
| 413 | +- [ ] Additional stochastic processes (Heston, jump-diffusion) |
| 414 | +- [ ] GPU acceleration |
| 415 | +- [ ] Python bindings |
| 416 | + |
362 | 417 | --- |
363 | 418 |
|
364 | | -**Last Updated**: 2026-04-07 |
365 | | -**Status**: Production-Ready for Research/Academic Use |
| 419 | +**Last Updated**: 2026-04-09 |
| 420 | +**Status**: Research-Grade (Functional, Tested, Not Peer-Reviewed) |
| 421 | +**Test Coverage**: 102 tests (99% pass), 200+ seconds full suite |
| 422 | +**Recommended Use**: ASVR for robustness when strategy choice is uncertain; fixed antithetic_cv for known-good problems |
0 commit comments