From 0b93aed93b805fff13c42cccae4e674683859234 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2026 10:05:52 +0000 Subject: [PATCH] bench: publish results from run 32469701489 [skip ci] --- benchmarks/vs_vectorbt/results/latest.json | 2332 ++++++++++++++++++++ 1 file changed, 2332 insertions(+) create mode 100644 benchmarks/vs_vectorbt/results/latest.json diff --git a/benchmarks/vs_vectorbt/results/latest.json b/benchmarks/vs_vectorbt/results/latest.json new file mode 100644 index 0000000..c9a65aa --- /dev/null +++ b/benchmarks/vs_vectorbt/results/latest.json @@ -0,0 +1,2332 @@ +{ + "repo": "manifoldbt/manifoldbt", + "run_id": "32469701489", + "run_url": "https://github.com/manifoldbt/manifoldbt/actions/runs/32469701489", + "commit": "4ad1c0d284672c696852363f60b3ac9d69d58202", + "run_started_at": "", + "conclusion": "success", + "synced_at": "2026-08-21T10:05:52.079029+00:00", + "backtests": { + "schema_version": 2, + "generated_at": "2026-08-21T10:05:43.084880+00:00", + "environment": { + "os": "Linux", + "os_release": "6.17.0-1022-azure", + "arch": "x86_64", + "cpu": "AMD EPYC 7763 64-Core Processor", + "logical_cores": 4, + "ram_gb": 16.8, + "python": "3.12.14", + "versions": { + "manifoldbt": "0.18.0", + "vectorbt": "0.28.4", + "raptorbt": "0.9.0", + "numpy": "2.4.3", + "numba": "0.64.0", + "pandas": "2.3.3" + }, + "runner": "GitHub Actions 1000000197", + "ci": true, + "run_url": "https://github.com/manifoldbt/manifoldbt/actions/runs/32469701489", + "commit": "4ad1c0d284672c696852363f60b3ac9d69d58202", + "pinned_cores": null, + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ] + }, + "reference": "manifoldbt", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "reps": 3, + "results": [ + { + "workload": "sma_cross", + "title": "SMA 30/150 crossover, long-only, no cost", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.8917489796876906e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": 0.06675521397166725, + "final_equity": 106675.52139716671, + "round_trips": 450, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 0.0, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": 0.06675521397166521, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross_metrics" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.005537009999983411, + 0.0034673119999979463, + 0.003467593000010538 + ], + "min_s": 0.0034673119999979463, + "median_s": 0.003467593000010538, + "max_s": 0.005537009999983411, + "iqr_s": 0.0020696979999854648, + "iqr_over_median": 0.5968687790000657 + }, + "vectorbt": { + "samples_s": [ + 0.19351422500000126, + 0.18271989799998778, + 0.19122307099999603 + ], + "min_s": 0.18271989799998778, + "median_s": 0.19122307099999603, + "max_s": 0.19351422500000126, + "iqr_s": 0.010794327000013482, + "iqr_over_median": 0.056448873786854446 + }, + "raptorbt": { + "samples_s": [ + 0.010924152000001186, + 0.010284125999987737, + 0.008664464000020189 + ], + "min_s": 0.008664464000020189, + "median_s": 0.010284125999987737, + "max_s": 0.010924152000001186, + "iqr_s": 0.002259687999980997, + "iqr_over_median": 0.21972581821573284 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 52.69785297662743, + "min": 34.94922801305778, + "max": 55.14576566494825 + }, + "raptorbt": { + "median_of_ratios": 2.498696934730765, + "min": 1.9729334063030255, + "max": 2.966022671162511 + } + }, + "noisy": true, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.0044810534202495, + "raptorbt": null + } + }, + { + "workload": "sma_cross_metrics", + "title": "SMA 30/150 crossover, with a performance summary", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.8917489796876906e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 2.806945912450058e-15, + "advisory_ratio_rel": { + "sharpe": 0.00034240713210042254, + "sortino": 0.0003424071320978874, + "volatility": 0.0003424071321000681 + } + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0, + "max_drawdown": -0.07910540917093023, + "sharpe": 2.1149665518057725, + "sortino": 4.02133680320316, + "volatility": 0.17066118340286904 + }, + "vectorbt": { + "total_return": 0.06675521397166725, + "final_equity": 106675.52139716671, + "round_trips": 450, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.07910540917093001, + "sharpe": 2.1142426200536755, + "sortino": 4.019960340111955, + "volatility": 0.17060276779841885 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 0.0, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 5.263023585843841e-16, + "ratio_basis": "native" + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0, + "max_drawdown": -0.07910540917093023, + "sharpe": 2.1149665518057725, + "sortino": 4.02133680320316, + "volatility": 0.17066118340286904 + }, + "raptorbt": { + "total_return": 0.06675521397166521, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.07910540917093027, + "sharpe": 0.9692748979846307, + "sortino": 1.3742016523326603, + "volatility": null + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.0037913239999909365, + 0.004846565999997665, + 0.004997146999983215 + ], + "min_s": 0.0037913239999909365, + "median_s": 0.004846565999997665, + "max_s": 0.004997146999983215, + "iqr_s": 0.0012058229999922787, + "iqr_over_median": 0.24879945924451655 + }, + "vectorbt": { + "samples_s": [ + 0.7089734399999941, + 0.883146049000004, + 0.8806502850000015 + ], + "min_s": 0.7089734399999941, + "median_s": 0.8806502850000015, + "max_s": 0.883146049000004, + "iqr_s": 0.17417260900000997, + "iqr_over_median": 0.19777726978196533 + }, + "raptorbt": { + "samples_s": [ + 0.010798098999998729, + 0.008434272999977566, + 0.008686154000002944 + ], + "min_s": 0.008434272999977566, + "median_s": 0.008686154000002944, + "max_s": 0.010798098999998729, + "iqr_s": 0.002363826000021163, + "iqr_over_median": 0.2721372427912701 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 182.22098884043456, + "min": 176.23061418904817, + "max": 186.9989059235478 + }, + "raptorbt": { + "median_of_ratios": 1.7402575349188742, + "min": 1.73822262983901, + "max": 2.8481076795400613 + } + }, + "noisy": true, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.00292393819919, + "raptorbt": null + } + }, + { + "workload": "sma_cross", + "title": "SMA 30/150 crossover, long-only, no cost", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 4.220055416226387e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.20294254717538118, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": 9069, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": 0.20294254717537696, + "final_equity": 120294.2547175377, + "round_trips": 4534, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 0.0, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.20294254717538118, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": 9069, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": 0.20294254717538115, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross_metrics" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.040898603000016465, + 0.037210861999994904, + 0.03915208899996969 + ], + "min_s": 0.037210861999994904, + "median_s": 0.03915208899996969, + "max_s": 0.040898603000016465, + "iqr_s": 0.0036877410000215605, + "iqr_over_median": 0.09419014653405633 + }, + "vectorbt": { + "samples_s": [ + 2.27948490899999, + 2.1148386590000428, + 2.2453365049999547 + ], + "min_s": 2.1148386590000428, + "median_s": 2.2453365049999547, + "max_s": 2.27948490899999, + "iqr_s": 0.16464624999994726, + "iqr_over_median": 0.07332809564771699 + }, + "raptorbt": { + "samples_s": [ + 0.08628283799998826, + 0.08157931599998847, + 0.08160842299997739 + ], + "min_s": 0.08157931599998847, + "median_s": 0.08160842299997739, + "max_s": 0.08628283799998826, + "iqr_s": 0.0047035219999997935, + "iqr_over_median": 0.05763525169455972 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 56.83390669639237, + "min": 55.73503107182102, + "max": 57.34908563887084 + }, + "raptorbt": { + "median_of_ratios": 2.1096769002098563, + "min": 2.0843951136308605, + "max": 2.192352222316152 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.000051196446245, + "raptorbt": null + } + }, + { + "workload": "sma_cross_metrics", + "title": "SMA 30/150 crossover, with a performance summary", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 4.220055416226387e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 1.464735645642113e-15, + "advisory_ratio_rel": { + "sharpe": 0.0003424071321271261, + "sortino": 0.00034240713212705575, + "volatility": 0.0003424071321024856 + } + }, + "metrics": { + "manifoldbt": { + "total_return": 0.20294254717538118, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": 9069, + "total_fees": 0.0, + "max_drawdown": -0.15159363779099633, + "sharpe": 0.6860158229410881, + "sortino": 1.3522858253366064, + "volatility": 0.16128875607357201 + }, + "vectorbt": { + "total_return": 0.20294254717537696, + "final_equity": 120294.2547175377, + "round_trips": 4534, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.1515936377909961, + "sharpe": 0.6857810066333395, + "sortino": 1.351822951516634, + "volatility": 0.16123354855661204 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 0.0, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 0.0, + "ratio_basis": "native" + }, + "metrics": { + "manifoldbt": { + "total_return": 0.20294254717538118, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": 9069, + "total_fees": 0.0, + "max_drawdown": -0.15159363779099633, + "sharpe": 0.6860158229410881, + "sortino": 1.3522858253366064, + "volatility": 0.16128875607357201 + }, + "raptorbt": { + "total_return": 0.20294254717538115, + "final_equity": 120294.25471753812, + "round_trips": 4534, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.15159363779099633, + "sharpe": 0.3005175738027932, + "sortino": 0.42543548791233987, + "volatility": null + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.03872782299998789, + 0.03877754100000175, + 0.03930562599998666 + ], + "min_s": 0.03872782299998789, + "median_s": 0.03877754100000175, + "max_s": 0.03930562599998666, + "iqr_s": 0.0005778029999987666, + "iqr_over_median": 0.01490045487924932 + }, + "vectorbt": { + "samples_s": [ + 8.535374160000032, + 8.612469403999967, + 8.576112231000025 + ], + "min_s": 8.535374160000032, + "median_s": 8.576112231000025, + "max_s": 8.612469403999967, + "iqr_s": 0.07709524399993484, + "iqr_over_median": 0.008989533010221006 + }, + "raptorbt": { + "samples_s": [ + 0.09173978100000113, + 0.09118693499999608, + 0.09250017899995555 + ], + "min_s": 0.09118693499999608, + "median_s": 0.09173978100000113, + "max_s": 0.09250017899995555, + "iqr_s": 0.001313243999959468, + "iqr_over_median": 0.014314880476545413 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 220.39385379350398, + "min": 218.19045016616542, + "max": 222.09942100247096 + }, + "raptorbt": { + "median_of_ratios": 2.3533572267742775, + "min": 2.3515399029554755, + "max": 2.36883392593562 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9998462213575717, + "raptorbt": null + } + }, + { + "workload": "sma_cross", + "title": "SMA 30/150 crossover, long-only, no cost", + "bars": 10000000, + "data_digest": "f4e6a3a8823f3768", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.2369127944111823e-14, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.3001352494374474, + "final_equity": 130013.52494374473, + "round_trips": 46127, + "fills": 92254, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": 0.30013524943743497, + "final_equity": 130013.5249437435, + "round_trips": 46127, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.4551915228366853e-16, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.3001352494374474, + "final_equity": 130013.52494374473, + "round_trips": 46127, + "fills": 92254, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": 0.3001352494374475, + "final_equity": 130013.52494374475, + "round_trips": 46127, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross_metrics" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.3300694689999659, + 0.3271346489999587, + 0.3248609849999866 + ], + "min_s": 0.3248609849999866, + "median_s": 0.3271346489999587, + "max_s": 0.3300694689999659, + "iqr_s": 0.0052084839999793076, + "iqr_over_median": 0.01592152960837837 + }, + "vectorbt": { + "samples_s": [ + 26.11685646799998, + 26.689765413000032, + 25.575436800000034 + ], + "min_s": 25.575436800000034, + "median_s": 26.11685646799998, + "max_s": 26.689765413000032, + "iqr_s": 1.1143286129999979, + "iqr_over_median": 0.04266702672909137 + }, + "raptorbt": { + "samples_s": [ + 0.9127483780000034, + 0.9094320230000221, + 0.9151434049999807 + ], + "min_s": 0.9094320230000221, + "median_s": 0.9127483780000034, + "max_s": 0.9151434049999807, + "iqr_s": 0.005711381999958576, + "iqr_over_median": 0.006257345548477715 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 79.12533245540101, + "min": 78.72732639778546, + "max": 81.58648279719034 + }, + "raptorbt": { + "median_of_ratios": 2.7799929655269775, + "min": 2.7653220419489863, + "max": 2.81703081396499 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": 1.089540802062376, + "vectorbt": 0.9997185748706885, + "raptorbt": 1.0046308712079222 + } + }, + { + "workload": "sma_cross_metrics", + "title": "SMA 30/150 crossover, with a performance summary", + "bars": 10000000, + "data_digest": "f4e6a3a8823f3768", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.2369127944111823e-14, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 1.1043826616631323e-14, + "advisory_ratio_rel": { + "sharpe": 0.0003424071321157821, + "sortino": 0.0003424071321161821, + "volatility": 0.0003424071321037301 + } + }, + "metrics": { + "manifoldbt": { + "total_return": 0.3001352494374474, + "final_equity": 130013.52494374473, + "round_trips": 46127, + "fills": 92254, + "total_fees": 0.0, + "max_drawdown": -0.6232787775126734, + "sharpe": 0.16657583326366043, + "sortino": 0.3242480879539277, + "volatility": 0.15596640368660572 + }, + "vectorbt": { + "total_return": 0.30013524943743497, + "final_equity": 130013.5249437435, + "round_trips": 46127, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.6232787775126802, + "sharpe": 0.16651881603341911, + "sortino": 0.324137101098728, + "volatility": 0.15591301795726933 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.4551915228366853e-16, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0, + "max_drawdown_rel": 0.0, + "ratio_basis": "native" + }, + "metrics": { + "manifoldbt": { + "total_return": 0.3001352494374474, + "final_equity": 130013.52494374473, + "round_trips": 46127, + "fills": 92254, + "total_fees": 0.0, + "max_drawdown": -0.6232787775126734, + "sharpe": 0.16657583326366043, + "sortino": 0.3242480879539277, + "volatility": 0.15596640368660572 + }, + "raptorbt": { + "total_return": 0.3001352494374475, + "final_equity": 130013.52494374475, + "round_trips": 46127, + "fills": null, + "total_fees": 0.0, + "max_drawdown": -0.6232787775126734, + "sharpe": 0.07064081213793068, + "sortino": 0.09993197026250207, + "volatility": null + } + }, + "note": "" + } + }, + "status": "exact", + "paired_with": [ + "sma_cross" + ], + "timings": { + "manifoldbt": { + "samples_s": [ + 0.3267744110000308, + 0.3292607250000401, + 0.32930117199998676 + ], + "min_s": 0.3267744110000308, + "median_s": 0.3292607250000401, + "max_s": 0.32930117199998676, + "iqr_s": 0.002526760999955968, + "iqr_over_median": 0.007674043115697022 + }, + "vectorbt": { + "samples_s": [ + 102.39089105199997, + 102.30543432800005, + 102.38272362500004 + ], + "min_s": 102.30543432800005, + "median_s": 102.38272362500004, + "max_s": 102.39089105199997, + "iqr_s": 0.08545672399992554, + "iqr_over_median": 0.000834679142869164 + }, + "raptorbt": { + "samples_s": [ + 0.9094987490000221, + 0.907195602999991, + 0.9145779780000112 + ], + "min_s": 0.907195602999991, + "median_s": 0.9094987490000221, + "max_s": 0.9145779780000112, + "iqr_s": 0.007382375000020147, + "iqr_over_median": 0.008116971032821033 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 310.90907755713715, + "min": 310.7125343540065, + "max": 313.3381550245999 + }, + "raptorbt": { + "median_of_ratios": 2.7773298602169807, + "min": 2.7552499709762848, + "max": 2.783261841760114 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": 1.096072469096488, + "vectorbt": 0.9998077074773046, + "raptorbt": 0.9995341621609296 + } + }, + { + "workload": "ema_rsi_fees", + "title": "EMA 12/26 crossover + RSI(14) filter, 5 bps taker fee", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.3096723705530167e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 4.7748471843078734e-17 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.01570110342278974, + "final_equity": 98429.88965772103, + "round_trips": 3176, + "fills": 6352, + "total_fees": 1542.3890014306103 + }, + "vectorbt": { + "total_return": -0.01570110342278846, + "final_equity": 98429.88965772116, + "round_trips": 3176, + "fills": null, + "total_fees": 1542.3890014306055 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "Two blockers, either one sufficient. Sizing: raptorbt has no fixed-quantity mode. `position_sizes` is a fraction of equity (measured: 0.5 buys exactly half the equity of the bar before the entry), `lot_size` rounds a computed size down to a multiple, and `alloted_capital` fixes the notional, not the quantity. Reproducing `units=5` would mean feeding a fraction derived from an equity curve that does not exist until the run is over. Indicator: `raptorbt.ema` seeds on a simple mean of the first `period` bars and emits from bar `period-1`, while manifoldbt seeds on the first observation and emits from bar 0 (measured: 11 leading NaN for span 12, and ema[11] equal to sma(12)[11] to the last bit). The two are the same recursion with a different warmup, so the signal differs early and the round-trip count with it. Its `sma` and `rsi` do match, which is why the other three workloads run." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.005095844000038596, + 0.005219965999913256, + 0.005213433999983863 + ], + "min_s": 0.005095844000038596, + "median_s": 0.005213433999983863, + "max_s": 0.005219965999913256, + "iqr_s": 0.0001241219998746601, + "iqr_over_median": 0.023808108029188497 + }, + "vectorbt": { + "samples_s": [ + 0.18830249500001628, + 0.19562824599995565, + 0.19789374000004045 + ], + "min_s": 0.18830249500001628, + "median_s": 0.19562824599995565, + "max_s": 0.19789374000004045, + "iqr_s": 0.009591245000024173, + "iqr_over_median": 0.04902791491585703 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 37.47691958208282, + "min": 36.952170238843664, + "max": 37.95842433234083 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.0140515211494157 + } + }, + { + "workload": "ema_rsi_fees", + "title": "EMA 12/26 crossover + RSI(14) filter, 5 bps taker fee", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 8.294591680169105e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 2.1100277081131935e-15 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.1532708157041739, + "final_equity": 84672.91842958261, + "round_trips": 31389, + "fills": 62779, + "total_fees": 15206.83039822937 + }, + "vectorbt": { + "total_return": -0.15327081570418216, + "final_equity": 84672.91842958178, + "round_trips": 31389, + "fills": null, + "total_fees": 15206.830398229158 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "Two blockers, either one sufficient. Sizing: raptorbt has no fixed-quantity mode. `position_sizes` is a fraction of equity (measured: 0.5 buys exactly half the equity of the bar before the entry), `lot_size` rounds a computed size down to a multiple, and `alloted_capital` fixes the notional, not the quantity. Reproducing `units=5` would mean feeding a fraction derived from an equity curve that does not exist until the run is over. Indicator: `raptorbt.ema` seeds on a simple mean of the first `period` bars and emits from bar `period-1`, while manifoldbt seeds on the first observation and emits from bar 0 (measured: 11 leading NaN for span 12, and ema[11] equal to sma(12)[11] to the last bit). The two are the same recursion with a different warmup, so the signal differs early and the round-trip count with it. Its `sma` and `rsi` do match, which is why the other three workloads run." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.0565764800001034, + 0.054403803000013795, + 0.06076183199991192 + ], + "min_s": 0.054403803000013795, + "median_s": 0.0565764800001034, + "max_s": 0.06076183199991192, + "iqr_s": 0.006358028999898124, + "iqr_over_median": 0.11237936683028892 + }, + "vectorbt": { + "samples_s": [ + 2.353663034999954, + 2.191344812000011, + 2.35987258800003 + ], + "min_s": 2.191344812000011, + "median_s": 2.353663034999954, + "max_s": 2.35987258800003, + "iqr_s": 0.168527776000019, + "iqr_over_median": 0.07160233792770693 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 40.279257904074385, + "min": 38.83807499424064, + "max": 41.6014399445786 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9992931905126997 + } + }, + { + "workload": "sma_cross_costs", + "title": "SMA 30/150 with a 5 bps fee and 2 bps of slippage", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 8.731149137020111e-16, + "round_trips_delta": 0, + "total_fees_vs_capital": 1.4210854715202004e-18 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.002745042655159957, + "final_equity": 99725.49573448401, + "round_trips": 450, + "fills": 900, + "total_fees": 218.42799507745576 + }, + "vectorbt": { + "total_return": -0.0027450426551607985, + "final_equity": 99725.49573448392, + "round_trips": 450, + "fills": null, + "total_fees": 218.4279950774559 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "Same blocker as the other fixed-quantity workload: raptorbt has no units sizing, and a cost model on top of a fraction of equity compares policy rather than arithmetic. See `ema_rsi_fees` for the measurements behind that." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.003779056999974273, + 0.0034193320000213134, + 0.003719514999943385 + ], + "min_s": 0.0034193320000213134, + "median_s": 0.003719514999943385, + "max_s": 0.003779056999974273, + "iqr_s": 0.0003597249999529595, + "iqr_over_median": 0.09671287787747458 + }, + "vectorbt": { + "samples_s": [ + 0.19228143999998792, + 0.18719415100008518, + 0.18235436499992375 + ], + "min_s": 0.18235436499992375, + "median_s": 0.18719415100008518, + "max_s": 0.19228143999998792, + "iqr_s": 0.009927075000064178, + "iqr_over_median": 0.053030903727647245 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 50.88079909916599, + "min": 49.02638247263403, + "max": 54.74582491519348 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9789438852919963 + } + }, + { + "workload": "sma_cross_costs", + "title": "SMA 30/150 with a 5 bps fee and 2 bps of slippage", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.6007106751203538e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 6.821210263296961e-17 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.02986364258908214, + "final_equity": 97013.63574109178, + "round_trips": 4534, + "fills": 9069, + "total_fees": 2195.9426086254202 + }, + "vectorbt": { + "total_return": -0.02986364258908383, + "final_equity": 97013.63574109162, + "round_trips": 4534, + "fills": null, + "total_fees": 2195.9426086254134 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "Same blocker as the other fixed-quantity workload: raptorbt has no units sizing, and a cost model on top of a fraction of equity compares policy rather than arithmetic. See `ema_rsi_fees` for the measurements behind that." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.036115827000003264, + 0.03778386999999839, + 0.03732817499997054 + ], + "min_s": 0.036115827000003264, + "median_s": 0.03732817499997054, + "max_s": 0.03778386999999839, + "iqr_s": 0.001668042999995123, + "iqr_over_median": 0.04468589744868157 + }, + "vectorbt": { + "samples_s": [ + 2.1256517289999692, + 2.2554999769999995, + 2.400851978999981 + ], + "min_s": 2.1256517289999692, + "median_s": 2.2554999769999995, + "max_s": 2.400851978999981, + "iqr_s": 0.2752002500000117, + "iqr_over_median": 0.12201296954391934 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 59.69478449402075, + "min": 58.85651542742679, + "max": 64.31742186704481 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9982300680510515 + } + }, + { + "workload": "sma_cross_costs", + "title": "SMA 30/150 with a 5 bps fee and 2 bps of slippage", + "bars": 10000000, + "data_digest": "f4e6a3a8823f3768", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 8.149072527885436e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 3.1650415621697903e-15 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.30242917768507427, + "final_equity": 69757.08223149258, + "round_trips": 46127, + "fills": 92254, + "total_fees": 21749.94829446186 + }, + "vectorbt": { + "total_return": -0.30242917768506616, + "final_equity": 69757.08223149339, + "round_trips": 46127, + "fills": null, + "total_fees": 21749.948294462178 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "Same blocker as the other fixed-quantity workload: raptorbt has no units sizing, and a cost model on top of a fraction of equity compares policy rather than arithmetic. See `ema_rsi_fees` for the measurements behind that." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.3375339529999337, + 0.33710847699990154, + 0.3290621699999292 + ], + "min_s": 0.3290621699999292, + "median_s": 0.33710847699990154, + "max_s": 0.3375339529999337, + "iqr_s": 0.008471783000004507, + "iqr_over_median": 0.025130732621734046 + }, + "vectorbt": { + "samples_s": [ + 26.07725812900003, + 26.612695970000004, + 25.853003193000063 + ], + "min_s": 25.853003193000063, + "median_s": 26.07725812900003, + "max_s": 26.612695970000004, + "iqr_s": 0.7596927769999411, + "iqr_over_median": 0.029132387049353975 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 78.56571052517408, + "min": 77.25817772473144, + "max": 78.94401293862384 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": 1.09593998074749, + "vectorbt": 0.9999623480945702 + } + }, + { + "workload": "multi_asset", + "title": "Five assets in one book, SMA 30/150, 5 bps fee", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.4551915228366853e-16, + "round_trips_delta": 0, + "total_fees_vs_capital": 5.115907697472722e-18 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.004784214364567441, + "final_equity": 99521.57856354325, + "round_trips": 2350, + "fills": 4700, + "total_fees": 464.09434549765643 + }, + "vectorbt": { + "total_return": -0.004784214364567548, + "final_equity": 99521.57856354324, + "round_trips": 2350, + "fills": null, + "total_fees": 464.09434549765695 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "No multi-instrument portfolio on the entry point this harness drives: `run_single_backtest` is one instrument, and `run_multi_backtest` broadcasts over strategies rather than over assets. 0.9.0 does add `run_portfolio_backtest`, but its allocation model is a different one and would need its own parity work before any timing from it could be published. The units blocker applies here too." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.02365792600005534, + 0.013531434000014997, + 0.013489414999980909 + ], + "min_s": 0.013489414999980909, + "median_s": 0.013531434000014997, + "max_s": 0.02365792600005534, + "iqr_s": 0.010168511000074432, + "iqr_over_median": 0.7514732732734137 + }, + "vectorbt": { + "samples_s": [ + 0.23366813300003741, + 0.22534788600000866, + 0.22799710300000697 + ], + "min_s": 0.22534788600000866, + "median_s": 0.22799710300000697, + "max_s": 0.23366813300003741, + "iqr_s": 0.008320247000028758, + "iqr_over_median": 0.036492775085955824 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 16.653658880482208, + "min": 9.876949188170206, + "max": 16.901926658815793 + } + }, + "noisy": true, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9897918660129811 + } + }, + { + "workload": "multi_asset", + "title": "Five assets in one book, SMA 30/150, 5 bps fee", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.0186340659856795e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 2.7284841053187848e-17 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.0447197098443024, + "final_equity": 95528.02901556976, + "round_trips": 22902, + "fills": 45806, + "total_fees": 4561.765315438204 + }, + "vectorbt": { + "total_return": -0.044719709844301396, + "final_equity": 95528.02901556986, + "round_trips": 22902, + "fills": null, + "total_fees": 4561.7653154382015 + } + }, + "note": "" + } + }, + "status": "exact", + "unsupported": { + "raptorbt": "No multi-instrument portfolio on the entry point this harness drives: `run_single_backtest` is one instrument, and `run_multi_backtest` broadcasts over strategies rather than over assets. 0.9.0 does add `run_portfolio_backtest`, but its allocation model is a different one and would need its own parity work before any timing from it could be published. The units blocker applies here too." + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.14756072700004097, + 0.14756938100003936, + 0.14718733600000178 + ], + "min_s": 0.14718733600000178, + "median_s": 0.14756072700004097, + "max_s": 0.14756938100003936, + "iqr_s": 0.0003820450000375786, + "iqr_over_median": 0.0025890696515575755 + }, + "vectorbt": { + "samples_s": [ + 2.480043374000047, + 2.6639006220000283, + 2.544444344999988 + ], + "min_s": 2.480043374000047, + "median_s": 2.544444344999988, + "max_s": 2.6639006220000283, + "iqr_s": 0.18385724799998115, + "iqr_over_median": 0.07225830989829805 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 17.287114599315508, + "min": 16.80693382595871, + "max": 18.051851975982185 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.0002096224759203 + } + }, + { + "workload": "bracket_sl_tp", + "title": "SMA 10/50 entry with a 15 bps stop / 30 bps target bracket", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.01145740341532248, + "round_trips_delta": 94, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.05756525685928504, + "final_equity": 94243.4743140715, + "round_trips": 2309, + "fills": 4618, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": -0.06902266027460748, + "final_equity": 93097.73397253925, + "round_trips": 2215, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Re-entry on the exit bar. When a bracket fires intrabar and the entry condition still holds at that bar's close, manifoldbt books two orders on that bar (the stop or target exit, then a fresh entry at the close); vectorbt processes one order per bar and re-enters on the next bar instead. Neither is wrong, and on controlled bars the bracket fills themselves match exactly (see the cross-engine parity suite shipped with the library). The harness counts the affected round-trips so the size of the divergence is measured, not asserted." + }, + "raptorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.009248235144781793, + "round_trips_delta": 925, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.05756525685928504, + "final_equity": 94243.4743140715, + "round_trips": 2309, + "fills": 4618, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": -0.06681349200406679, + "final_equity": 93318.65079959332, + "round_trips": 1384, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Same fork in the road, taken further: raptorbt does not re-arm at all. Once a bracket closes a position, the entry level being still true is not enough to open another one; it waits for the level to go false and true again. So on the same bars the three engines book a different number of round-trips from the same signal, manifoldbt re-entering on the exit bar, vectorbt on the next bar, raptorbt not until the next crossing. The count of affected round-trips is measured rather than asserted, and it is the same population for both challengers." + } + }, + "status": "documented", + "divergence_scale": { + "raptorbt": { + "round_trips": 1384, + "final_equity": 93318.65079959332 + }, + "manifoldbt": { + "reentries_on_exit_bar": 925, + "round_trips": 2309, + "share_of_round_trips": 0.40060632308358596, + "sl_exits": 632, + "tp_exits": 388 + } + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.009862469999916357, + 0.009430810000026213, + 0.009603874000049473 + ], + "min_s": 0.009430810000026213, + "median_s": 0.009603874000049473, + "max_s": 0.009862469999916357, + "iqr_s": 0.0004316599998901438, + "iqr_over_median": 0.04494644555810709 + }, + "vectorbt": { + "samples_s": [ + 0.19352732699996977, + 0.18383552800003145, + 0.18376027700003306 + ], + "min_s": 0.18376027700003306, + "median_s": 0.18383552800003145, + "max_s": 0.19352732699996977, + "iqr_s": 0.009767049999936717, + "iqr_over_median": 0.053129284128011676 + }, + "raptorbt": { + "samples_s": [ + 0.007940225999959694, + 0.008047938000004251, + 0.01084256700005426 + ], + "min_s": 0.007940225999959694, + "median_s": 0.008047938000004251, + "max_s": 0.01084256700005426, + "iqr_s": 0.002902341000094566, + "iqr_over_median": 0.3606316301260066 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 19.49307938549504, + "min": 19.133974164913706, + "max": 19.62260235028457 + }, + "raptorbt": { + "median_of_ratios": 0.8533665719044156, + "min": 0.8050950725352811, + "max": 1.1289784726453518 + } + }, + "noisy": true, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 0.9801770211106439, + "raptorbt": null + } + }, + { + "workload": "bracket_sl_tp", + "title": "SMA 10/50 entry with a 15 bps stop / 30 bps target bracket", + "bars": 1000000, + "data_digest": "0ef03e7a3c4d011c", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.010543837599986582, + "round_trips_delta": 1092, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.45070441471402267, + "final_equity": 54929.558528597736, + "round_trips": 23075, + "fills": 46151, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": -0.46124825231400923, + "final_equity": 53875.17476859908, + "round_trips": 21983, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Re-entry on the exit bar. When a bracket fires intrabar and the entry condition still holds at that bar's close, manifoldbt books two orders on that bar (the stop or target exit, then a fresh entry at the close); vectorbt processes one order per bar and re-enters on the next bar instead. Neither is wrong, and on controlled bars the bracket fills themselves match exactly (see the cross-engine parity suite shipped with the library). The harness counts the affected round-trips so the size of the divergence is measured, not asserted." + }, + "raptorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.10072796246195154, + "round_trips_delta": 9330, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.45070441471402267, + "final_equity": 54929.558528597736, + "round_trips": 23075, + "fills": 46151, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": -0.3499764522520711, + "final_equity": 65002.35477479289, + "round_trips": 13745, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Same fork in the road, taken further: raptorbt does not re-arm at all. Once a bracket closes a position, the entry level being still true is not enough to open another one; it waits for the level to go false and true again. So on the same bars the three engines book a different number of round-trips from the same signal, manifoldbt re-entering on the exit bar, vectorbt on the next bar, raptorbt not until the next crossing. The count of affected round-trips is measured rather than asserted, and it is the same population for both challengers." + } + }, + "status": "documented", + "divergence_scale": { + "raptorbt": { + "round_trips": 13745, + "final_equity": 65002.35477479289 + }, + "manifoldbt": { + "reentries_on_exit_bar": 9330, + "round_trips": 23075, + "share_of_round_trips": 0.40433369447453954, + "sl_exits": 6363, + "tp_exits": 3906 + } + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.09000605500000347, + 0.10142546300005506, + 0.0990195209999456 + ], + "min_s": 0.09000605500000347, + "median_s": 0.0990195209999456, + "max_s": 0.10142546300005506, + "iqr_s": 0.01141940800005159, + "iqr_over_median": 0.11532481559931868 + }, + "vectorbt": { + "samples_s": [ + 2.123934636999934, + 2.41483274899997, + 2.1098326069999302 + ], + "min_s": 2.1098326069999302, + "median_s": 2.123934636999934, + "max_s": 2.41483274899997, + "iqr_s": 0.3050001420000399, + "iqr_over_median": 0.14360147279807717 + }, + "raptorbt": { + "samples_s": [ + 0.08824071600008665, + 0.08014500499996302, + 0.089690150000024 + ], + "min_s": 0.08014500499996302, + "median_s": 0.08824071600008665, + "max_s": 0.089690150000024, + "iqr_s": 0.009545145000060984, + "iqr_over_median": 0.10817166306823271 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 23.597686144558295, + "min": 21.30723907461731, + "max": 23.808939861567694 + }, + "raptorbt": { + "median_of_ratios": 0.9057825072701905, + "min": 0.7901862375518021, + "max": 0.9803864417797585 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": 1.0002105716995484, + "raptorbt": null + } + }, + { + "workload": "bracket_sl_tp", + "title": "SMA 10/50 entry with a 15 bps stop / 30 bps target bracket", + "bars": 10000000, + "data_digest": "f4e6a3a8823f3768", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.0008838890600401106, + "round_trips_delta": 10171, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.9948342253853452, + "final_equity": 516.5774614654839, + "round_trips": 231082, + "fills": 462164, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": -0.9957181144453853, + "final_equity": 428.18855546147284, + "round_trips": 220911, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Re-entry on the exit bar. When a bracket fires intrabar and the entry condition still holds at that bar's close, manifoldbt books two orders on that bar (the stop or target exit, then a fresh entry at the close); vectorbt processes one order per bar and re-enters on the next bar instead. Neither is wrong, and on controlled bars the bracket fills themselves match exactly (see the cross-engine parity suite shipped with the library). The harness counts the affected round-trips so the size of the divergence is measured, not asserted." + }, + "raptorbt": { + "status": "documented", + "expected": "documented", + "publishable": false, + "diffs": { + "final_equity_vs_capital": 0.022352514553554532, + "round_trips_delta": 93295, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": -0.9948342253853452, + "final_equity": 516.5774614654839, + "round_trips": 231082, + "fills": 462164, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": -0.9724817108317907, + "final_equity": 2751.828916820937, + "round_trips": 137787, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "Same fork in the road, taken further: raptorbt does not re-arm at all. Once a bracket closes a position, the entry level being still true is not enough to open another one; it waits for the level to go false and true again. So on the same bars the three engines book a different number of round-trips from the same signal, manifoldbt re-entering on the exit bar, vectorbt on the next bar, raptorbt not until the next crossing. The count of affected round-trips is measured rather than asserted, and it is the same population for both challengers." + } + }, + "status": "documented", + "divergence_scale": { + "raptorbt": { + "round_trips": 137787, + "final_equity": 2751.828916820937 + }, + "manifoldbt": { + "reentries_on_exit_bar": 93295, + "round_trips": 231082, + "share_of_round_trips": 0.4037311430574428, + "sl_exits": 63245, + "tp_exits": 39487 + } + }, + "timings": { + "manifoldbt": { + "samples_s": [ + 0.933703575000095, + 0.9369593230001101, + 0.9298959029999878 + ], + "min_s": 0.9298959029999878, + "median_s": 0.933703575000095, + "max_s": 0.9369593230001101, + "iqr_s": 0.007063420000122278, + "iqr_over_median": 0.00756494907939231 + }, + "vectorbt": { + "samples_s": [ + 26.240877660000024, + 26.76315124000007, + 25.984967522000034 + ], + "min_s": 25.984967522000034, + "median_s": 26.240877660000024, + "max_s": 26.76315124000007, + "iqr_s": 0.7781837180000366, + "iqr_over_median": 0.029655399795802253 + }, + "raptorbt": { + "samples_s": [ + 0.9158754299999146, + 0.9041454129999238, + 0.9164052200001152 + ], + "min_s": 0.9041454129999238, + "median_s": 0.9158754299999146, + "max_s": 0.9164052200001152, + "iqr_s": 0.012259807000191358, + "iqr_over_median": 0.013385889170749456 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 28.10407752802848, + "min": 27.94395312224574, + "max": 28.56383471835834 + }, + "raptorbt": { + "median_of_ratios": 0.98090599042616, + "min": 0.9649782982092356, + "max": 0.9854922653639514 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": 1.0283661956933539, + "vectorbt": 0.999759505464551, + "raptorbt": 1.0013060601374422 + } + } + ], + "cold_start": { + "workload": "sma_cross", + "bars": 20000, + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "samples_s": { + "manifoldbt": [ + 0.5525029860000359, + 0.4318835090000448, + 0.43821266099985223 + ], + "vectorbt": [ + 8.499870310000006, + 7.85704349599996, + 7.8574503709999135 + ], + "raptorbt": [ + 0.4242792439999903, + 0.4106652389998544, + 0.41995794600006775 + ], + "baseline": [ + 0.37013325799989616, + 0.3766939629999797, + 0.37386452200007625 + ] + }, + "median_s": { + "manifoldbt": 0.43821266099985223, + "vectorbt": 7.8574503709999135, + "raptorbt": 0.41995794600006775, + "baseline": 0.37386452200007625 + }, + "engine_share_s": { + "manifoldbt": 0.06434813899977598, + "vectorbt": 7.483585848999837, + "raptorbt": 0.0460934239999915 + }, + "ratio": { + "vectorbt": 17.930678572983, + "raptorbt": 0.9583427942083338 + } + }, + "memory": { + "workload": "sma_cross", + "bars": 2000000, + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "manifoldbt": { + "before_mb": 728.408064, + "peak_mb": 728.420352, + "added_mb": 0.012288000000012289, + "added_mb_per_million_bars": 0.0061440000000061445, + "seconds": 0.05989172799991138, + "mode": "memory", + "engine": "mbt", + "workload": "sma_cross", + "bars": 2000000 + }, + "vectorbt": { + "before_mb": 614.621184, + "peak_mb": 862.318592, + "added_mb": 247.697408, + "added_mb_per_million_bars": 123.848704, + "seconds": 4.567739748000122, + "mode": "memory", + "engine": "vbt", + "workload": "sma_cross", + "bars": 2000000 + }, + "raptorbt": { + "before_mb": 254.132224, + "peak_mb": 285.999104, + "added_mb": 31.86687999999998, + "added_mb_per_million_bars": 15.93343999999999, + "seconds": 0.17565568700001677, + "mode": "memory", + "engine": "rbt", + "workload": "sma_cross", + "bars": 2000000 + } + }, + "sweeps": null, + "sweep_reps": null + }, + "sweeps": { + "schema_version": 2, + "generated_at": "2026-08-21T10:04:46.513349+00:00", + "environment": { + "os": "Linux", + "os_release": "6.17.0-1022-azure", + "arch": "x86_64", + "cpu": "AMD EPYC 7763 64-Core Processor", + "logical_cores": 4, + "ram_gb": 16.8, + "python": "3.12.14", + "versions": { + "manifoldbt": "0.18.0", + "vectorbt": "0.28.4", + "raptorbt": "0.9.0", + "numpy": "2.4.3", + "numba": "0.64.0", + "pandas": "2.3.3" + }, + "runner": "GitHub Actions 1000000196", + "ci": true, + "run_url": "https://github.com/manifoldbt/manifoldbt/actions/runs/32469701489", + "commit": "4ad1c0d284672c696852363f60b3ac9d69d58202", + "pinned_cores": null, + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ] + }, + "reference": "manifoldbt", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "reps": 1, + "results": [ + { + "workload": "sma_cross", + "title": "SMA 30/150 crossover, long-only, no cost", + "bars": 100000, + "data_digest": "b7c2ad8cea687ce0", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "parity": { + "vectorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 1.8917489796876906e-15, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0 + }, + "vectorbt": { + "total_return": 0.06675521397166725, + "final_equity": 106675.52139716671, + "round_trips": 450, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + }, + "raptorbt": { + "status": "exact", + "expected": "exact", + "publishable": true, + "diffs": { + "final_equity_vs_capital": 0.0, + "round_trips_delta": 0, + "total_fees_vs_capital": 0.0 + }, + "metrics": { + "manifoldbt": { + "total_return": 0.06675521397166517, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": 900, + "total_fees": 0.0 + }, + "raptorbt": { + "total_return": 0.06675521397166521, + "final_equity": 106675.52139716652, + "round_trips": 450, + "fills": null, + "total_fees": 0.0 + } + }, + "note": "" + } + }, + "status": "exact", + "timings": { + "manifoldbt": { + "samples_s": [ + 0.005660272000000077 + ], + "min_s": 0.005660272000000077, + "median_s": 0.005660272000000077, + "max_s": 0.005660272000000077, + "iqr_s": 0.0, + "iqr_over_median": 0.0 + }, + "vectorbt": { + "samples_s": [ + 0.1845830949999936 + ], + "min_s": 0.1845830949999936, + "median_s": 0.1845830949999936, + "max_s": 0.1845830949999936, + "iqr_s": 0.0, + "iqr_over_median": 0.0 + }, + "raptorbt": { + "samples_s": [ + 0.010396635000006427 + ], + "min_s": 0.010396635000006427, + "median_s": 0.010396635000006427, + "max_s": 0.010396635000006427, + "iqr_s": 0.0, + "iqr_over_median": 0.0 + } + }, + "speedup": { + "vectorbt": { + "median_of_ratios": 32.61028710280903, + "min": 32.61028710280903, + "max": 32.61028710280903 + }, + "raptorbt": { + "median_of_ratios": 1.836773038469933, + "min": 1.836773038469933, + "max": 1.836773038469933 + } + }, + "noisy": false, + "cpu_over_wall": { + "manifoldbt": null, + "vectorbt": null, + "raptorbt": null + } + } + ], + "cold_start": null, + "memory": null, + "sweeps": [ + { + "bars": 20000, + "combos": 5000, + "requested_combos": 5000, + "grid": { + "fast": 50, + "slow": 100 + }, + "data_digest": "ccec9b97c4ca2b6f", + "engines": [ + "manifoldbt", + "vectorbt", + "raptorbt" + ], + "metrics": false, + "tier_before": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + }, + "parity": { + "vectorbt": { + "status": "exact", + "combos_compared": 5000, + "worst_abs_return_delta": 1.2663481374630692e-15, + "worst_component": "return", + "worst_pair": [ + 101, + 118 + ] + }, + "raptorbt": { + "status": "exact", + "combos_compared": 5000, + "worst_abs_return_delta": 1.1102230246251565e-16, + "worst_component": "return", + "worst_pair": [ + 19, + 113 + ] + } + }, + "status": "exact", + "timings": { + "seconds": { + "manifoldbt": 0.45341110100000037, + "vectorbt": 5.086513381000003, + "raptorbt": 6.751059206000008 + }, + "ratio": { + "vectorbt": 11.218325642626908, + "raptorbt": 14.889488129228672 + }, + "reps": 3, + "per_combo_us": 90.68222020000007 + }, + "memory": { + "manifoldbt": 40.9, + "vectorbt": 2532.5, + "raptorbt": 35.7 + }, + "memory_baseline_mb": 2176.0, + "tier_after": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + } + }, + { + "bars": 20000, + "combos": 20000, + "requested_combos": 20000, + "grid": { + "fast": 125, + "slow": 160 + }, + "data_digest": "ccec9b97c4ca2b6f", + "engines": [ + "manifoldbt", + "raptorbt" + ], + "metrics": false, + "tier_before": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + }, + "out_of_scope": { + "vectorbt": { + "status": "out of scope", + "reason": "vectorbt materialises the simulation per combination (measured: 1.57 MB per combination at 20k bars), so this grid would need tens of gigabytes. Running it would measure the swap file.", + "parity_scope": "anchor grid" + } + }, + "parity": { + "raptorbt": { + "status": "exact", + "combos_compared": 20000, + "worst_abs_return_delta": 1.1102230246251565e-16, + "worst_component": "return", + "worst_pair": [ + 11, + 733 + ] + }, + "vectorbt": { + "status": "exact", + "combos_compared": 250, + "worst_abs_return_delta": 2.2707530300536405e-15, + "worst_component": "return", + "worst_pair": [ + 9, + 78 + ], + "checked_at_combos": 250, + "scope": "anchor grid, not this grid" + } + }, + "status": "exact", + "timings": { + "seconds": { + "manifoldbt": 1.8183658750000404, + "raptorbt": 26.471181933999986, + "vectorbt": null + }, + "ratio": { + "raptorbt": 14.557676371923444 + }, + "reps": 3, + "per_combo_us": 90.91829375000202 + }, + "memory": { + "manifoldbt": 73.6, + "vectorbt": null, + "raptorbt": null + }, + "memory_baseline_mb": 613.0, + "tier_after": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + } + }, + { + "bars": 200000, + "combos": 10000, + "requested_combos": 10000, + "grid": { + "fast": 100, + "slow": 100 + }, + "data_digest": "e89a96644ec074e4", + "engines": [ + "manifoldbt", + "raptorbt" + ], + "metrics": false, + "tier_before": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + }, + "out_of_scope": { + "vectorbt": { + "status": "out of scope", + "reason": "vectorbt materialises the simulation per combination (measured: 1.57 MB per combination at 20k bars), so this grid would need tens of gigabytes. Running it would measure the swap file.", + "parity_scope": "anchor grid" + } + }, + "parity": { + "raptorbt": { + "status": "exact", + "combos_compared": 10000, + "worst_abs_return_delta": 1.1796119636642288e-16, + "worst_component": "return", + "worst_pair": [ + 7, + 323 + ] + }, + "vectorbt": { + "status": "exact", + "combos_compared": 250, + "worst_abs_return_delta": 9.196202827022049e-15, + "worst_component": "return", + "worst_pair": [ + 11, + 53 + ], + "checked_at_combos": 250, + "scope": "anchor grid, not this grid" + } + }, + "status": "exact", + "timings": { + "seconds": { + "manifoldbt": 9.671076569000093, + "raptorbt": 150.72750835799997, + "vectorbt": null + }, + "ratio": { + "raptorbt": 15.585390859291264 + }, + "reps": 3, + "per_combo_us": 967.1076569000093 + }, + "memory": { + "manifoldbt": 78.2, + "vectorbt": null, + "raptorbt": null + }, + "memory_baseline_mb": 1726.8, + "tier_after": { + "pro": true, + "budget_used": 0, + "budget_limit": 256 + } + } + ], + "sweep_reps": 3 + } +}