🔎 📈 🐍 💰 Backtest trading strategies in Python.
This report summarizes scanner evidence for kernc/backtesting.py, a Python project with 9,034 GitHub stars. SynthScan examined 8,340 lines of code across 37 source files, recording 101 pattern matches distributed across 14 syntactic categories. The legacy adjusted pattern signal is 20.4 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 71 finding(s).
Are imports declared and package/API names verified? 19 finding(s).
Are wrappers, guards, and repeated structures necessary? 40 finding(s).
Which changes need focused human review? 101 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 101 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | backtesting/_plotting.py | 160 | assert not indicators or indicators[0].df.index.equals(df.index) | CODE |
| HIGH⚡ | backtesting/_plotting.py | 163 | assert equity_data.index.equals(df.index) | CODE |
| HIGH | backtesting/_plotting.py | 221 | assert df.index.equals(results['_equity_curve'].index) | CODE |
| HIGH | backtesting/_plotting.py | 289 | this.labels = this.labels || formatter.doFormat(ticks | CODE |
| HIGH | backtesting/_plotting.py | 291 | .filter(t => t !== undefined)); | CODE |
| HIGH | backtesting/_plotting.py | 361 | assert equity.index.equals(equity_data.index) | STRING |
| HIGH⚡ | backtesting/test/_test.py | 1124 | assert close.s.equals(pd.Series(close, index=index)) | CODE |
| HIGH⚡ | backtesting/test/_test.py | 1130 | assert close.s.equals(pd.Series(close, index=index)) | CODE |
| HIGH | backtesting/test/_test.py | 309 | self.assertTrue(df.equals(EURUSD)) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/lib.py | 261 | # Let's convert closing prices back to pandas Series. | COMMENT |
| LOW | doc/examples/Strategies Library.py | 1 | # --- | COMMENT |
| LOW | doc/examples/Strategies Library.py | 21 | # [basic package usage](https://kernc.github.io/backtesting.py/doc/examples/Quick%20Start%20User%20Guide.html). | COMMENT |
| LOW | doc/examples/Strategies Library.py | 101 | # For other strategies of the sort, and other reusable utilities in general, see | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 1 | # --- | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 21 | # _Backtesting.py_ is a small and lightweight, blazing fast backtesting framework that uses state-of-the-art Python stru | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 41 | # DataFrame should ideally be indexed with a _datetime index_ (convert it with [`pd.to_datetime()`](https://pandas.pydat | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 121 | # [`self.data`](https://kernc.github.io/backtesting.py/doc/backtesting/backtesting.html#backtesting.backtesting.Strategy | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 141 | # self.position.close() | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 161 | from backtesting import Backtest | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 201 | # %% | COMMENT |
| LOW | doc/examples/Quick Start User Guide.py | 221 | # The columns should be self-explanatory. | COMMENT |
| LOW | doc/examples/Parameter Heatmap & Optimization.py | 1 | # -*- coding: utf-8 -*- | COMMENT |
| LOW | doc/examples/Parameter Heatmap & Optimization.py | 21 | # It is assumed you're already familiar with | COMMENT |
| LOW | doc/examples/Parameter Heatmap & Optimization.py | 121 | # It makes the function return a heatmap series along with the usual stats of the best run. | COMMENT |
| LOW | doc/examples/Parameter Heatmap & Optimization.py | 161 | ) | COMMENT |
| LOW | doc/examples/Parameter Heatmap & Optimization.py | 181 | # ## Model-based optimization | COMMENT |
| LOW | doc/examples/Trading with Machine Learning.py | 1 | # --- | COMMENT |
| LOW | doc/examples/Trading with Machine Learning.py | 21 | # [basic framework usage](https://kernc.github.io/backtesting.py/doc/examples/Quick%20Start%20User%20Guide.html) | COMMENT |
| LOW | doc/examples/Trading with Machine Learning.py | 261 | bt.plot() | COMMENT |
| LOW | doc/examples/Trading with Machine Learning.py | 281 | # by increasing the conviction needed and imposing extra domain expertise and discretionary limitations before enterin | COMMENT |
| LOW | doc/examples/Multiple Time Frames.py | 1 | # --- | COMMENT |
| LOW | doc/examples/Multiple Time Frames.py | 21 | # [pandas resampling](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#resampling). | COMMENT |
| LOW | doc/examples/Multiple Time Frames.py | 141 | # In conclusion, to test strategies on multiple time frames, you need to pass in OHLC data in the lowest time frame, the | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/_stats.py | 14 | def compute_drawdown_duration_peaks(dd: pd.Series): | CODE |
| LOW⚡ | backtesting/test/_test.py | 1136 | def test_indicators_picklable(self): | CODE |
| LOW⚡ | backtesting/test/_test.py | 1270 | def test_optimize_datetime_index_with_timezone(self): | CODE |
| LOW⚡ | backtesting/test/_test.py | 1276 | def test_optimize_range_index(self): | CODE |
| LOW⚡ | backtesting/test/_test.py | 1286 | def test_sl_tp_values_in_trades_df(self): | CODE |
| LOW | backtesting/test/_test.py | 100 | def test_data_missing_columns(self): | CODE |
| LOW | backtesting/test/_test.py | 238 | def test_absolute_size_order_warns_on_insufficient_margin(self): | CODE |
| LOW | backtesting/test/_test.py | 393 | def test_compute_stats_bordercase(self): | CODE |
| LOW | backtesting/test/_test.py | 426 | def test_trade_enter_hit_sl_on_same_day(self): | CODE |
| LOW | backtesting/test/_test.py | 444 | def test_stop_price_between_sl_tp(self): | CODE |
| LOW | backtesting/test/_test.py | 453 | def test_position_close_portion(self): | CODE |
| LOW | backtesting/test/_test.py | 468 | def test_close_orders_from_last_strategy_iteration(self): | CODE |
| LOW | backtesting/test/_test.py | 480 | def test_check_adjusted_price_when_placing_order(self): | CODE |
| LOW | backtesting/test/_test.py | 533 | def test_broker_exclusive_orders(self): | CODE |
| LOW | backtesting/test/_test.py | 545 | def test_trade_multiple_close(self): | CODE |
| LOW | backtesting/test/_test.py | 566 | def test_stop_limit_order_price_is_stop_price(self): | CODE |
| LOW | backtesting/test/_test.py | 575 | def test_autoclose_trades_on_finish(self): | CODE |
| LOW | backtesting/test/_test.py | 659 | def test_optimize_invalid_param(self): | CODE |
| LOW | backtesting/test/_test.py | 807 | def test_resample_trades_vectorized(self): | CODE |
| LOW | backtesting/test/_test.py | 1160 | def test_backtest_run_docstring_contains_stats_keys(self): | CODE |
| LOW | backtesting/test/_test.py | 1165 | def test_readme_contains_stats_keys(self): | CODE |
| LOW | backtesting/test/_test.py | 1204 | def test_trade_on_close_closes_trades_on_close(self): | CODE |
| LOW | backtesting/test/_test.py | 1239 | def test_trades_dates_match_prices(self): | CODE |
| LOW | backtesting/test/_test.py | 1259 | def test_stop_entry_and_tp_in_same_bar(self): | CODE |
| LOW | backtesting/test/_test.py | 1297 | def test_sl_value_in_trades_df_when_gapped_through(self): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | doc/examples/Strategies Library.py | 17 | # ====================== | COMMENT |
| MEDIUM | doc/examples/Quick Start User Guide.py | 17 | # ======================= | COMMENT |
| MEDIUM | doc/examples/Parameter Heatmap & Optimization.py | 18 | # ========== | COMMENT |
| MEDIUM | doc/examples/Multiple Time Frames.py | 17 | # ============ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | doc/examples/Strategies Library.py | 20 | # It is, henceforth, assumed you're already familiar with | COMMENT |
| MEDIUM | doc/examples/Quick Start User Guide.py | 21 | # _Backtesting.py_ is a small and lightweight, blazing fast backtesting framework that uses state-of-the-art Python stru | COMMENT |
| MEDIUM | doc/examples/Parameter Heatmap & Optimization.py | 91 | # It's not a robust strategy, but we can optimize it. | COMMENT |
| MEDIUM | doc/examples/Trading with Machine Learning.py | 151 | # Let's backtest a simple strategy that buys the asset for 20% of available equity with 20:1 leverage whenever the forec | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 9 | CODE | |
| LOW | backtesting/lib.py | 14 | CODE | |
| LOW | backtesting/__init__.py | 68 | CODE | |
| LOW | backtesting/__init__.py | 69 | CODE | |
| LOW | backtesting/__init__.py | 71 | CODE | |
| LOW | backtesting/__init__.py | 71 | CODE | |
| LOW | backtesting/_plotting.py | 1 | CODE | |
| LOW | backtesting/_util.py | 1 | CODE | |
| LOW | backtesting/_stats.py | 1 | CODE | |
| LOW | backtesting/test/__init__.py | 3 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | backtesting/backtesting.py | 1231 | except ValueError: | CODE |
| HIGH | backtesting/test/_test.py | 734 | except RuntimeError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 765 | CODE | |
| LOW | backtesting/backtesting.py | 875 | CODE | |
| LOW | backtesting/backtesting.py | 1271 | CODE | |
| LOW | backtesting/backtesting.py | 1386 | CODE | |
| LOW | backtesting/backtesting.py | 1513 | CODE | |
| LOW | backtesting/lib.py | 427 | CODE | |
| LOW | backtesting/_plotting.py | 198 | CODE | |
| LOW | backtesting/_plotting.py | 535 | CODE | |
| LOW | backtesting/_stats.py | 37 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 1195 | CODE | |
| LOW | backtesting/backtesting.py | 1658 | CODE | |
| LOW | backtesting/lib.py | 330 | CODE | |
| LOW | backtesting/_plotting.py | 198 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 145 | except Exception as e: | CODE |
| LOW⚡ | backtesting/_plotting.py | 152 | except Exception: | CODE |
| LOW | backtesting/_util.py | 304 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 887 | # Check if stop condition was hit | COMMENT |
| LOW | backtesting/backtesting.py | 899 | # Check if limit order can be filled. | COMMENT |
| LOW | backtesting/_plotting.py | 495 | # Check if resampling was downsampling; error on upsampling | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | doc/examples/Quick Start User Guide.py | 95 | # Define the two MA lags as *class variables* | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | backtesting/backtesting.py | 1772 | __all__ = [getattr(v, '__name__', k) | CODE |
| LOW | backtesting/lib.py | 640 | __all__ = [getattr(v, '__name__', k) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | doc/examples/Trading with Machine Learning.py | 283 | # Also make sure to familiarize yourself with the full | COMMENT |