# backtrader **Repository Path**: yunjinqi/backtrader ## Basic Information - **Project Name**: backtrader - **Description**: 量化交易框架backtrader最新版本 - **Primary Language**: Python - **License**: GPL-3.0 - **Default Branch**: development - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 111 - **Forks**: 61 - **Created**: 2019-12-10 - **Last Updated**: 2026-07-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
# 🚀 Backtrader **Professional Python Algorithmic Trading Backtesting Framework** [![Version](https://img.shields.io/badge/Version-1.2.0-blue.svg)](https://github.com/cloudQuant/backtrader) [![Python](https://img.shields.io/badge/Python-3.8%2B-green.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/License-GPLv3-orange.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey.svg)](#) **English** | [**中文**](#-中文文档) [📖 Documentation (EN)](https://backtrader.readthedocs.io/en/latest/) · [📖 中文文档](https://backtrader-zh.readthedocs.io/zh-cn/latest/) · [🌐 GitHub Pages](https://cloudquant.github.io/backtrader/) [🐛 Report Bug](https://github.com/cloudQuant/backtrader/issues) · [💬 Discussions](https://github.com/cloudQuant/backtrader/discussions)
--- ## Installation I have published the pybind11-based Python wheel to PyPI: https://pypi.org/project/back-trader-cpp/ You can install it directly: ```bash pip install back-trader-cpp ``` It currently supports Python 3.8-3.14 and covers macOS, Windows, Linux, and other systems. ## C++ and pybind11 Performance Highlights - 117 strategy benchmark cases, with the C++ version reaching 117/117 success and 0 metric mismatches; - C++ total-time median speedup: 128.82x; - C++ run-time median speedup: 235.78x; - pybind11 total-time median speedup: 43.39x; - pybind11 run-time median speedup: 57.60x. --- ## 📋 Table of Contents - [Installation](#installation) - [C++ and pybind11 Performance Highlights](#c-and-pybind11-performance-highlights) - [Performance Snapshot](#-performance-snapshot) - [Introduction](#-introduction) - [Key Features](#-key-features) - [Quick Installation](#-quick-installation) - [5-Minute Quickstart](#-5-minute-quickstart) - [Core Concepts](#-core-concepts) - [Built-in Components](#-built-in-components) - [Advanced Topics](#-advanced-topics) - [Project Architecture](#-project-architecture) - [Testing](#-testing) - [Repository Maintenance Notes](#-repository-maintenance-notes) - [API Documentation](#-api-documentation) - [FAQ](#-faq) - [Contributing](#-contributing) - [License](#-license) - [中文文档](#-中文文档) --- ## ⚡ Performance Snapshot The active `dev` branch carries the optimization work originally developed on the `development` branch. Running the **full 1,271-strategy regression suite** (`tests/functional/strategies`, `-n 8`) against the installed engine, `dev` completes in **about half the time** of `master`. ### 📊 Benchmark Results (full strategy suite) | Metric | Master Branch | Dev Branch | Improvement | | --- | --- | --- | --- | | **Total Execution Time** | 438.96s (7m18s) | 236.36s (3m56s) | **-46.2%** | | **Speedup** | 1.00x | **1.86x** | ✓ | | **Strategies Tested** | 1,271 | 1,271 | ✓ | | **Test Pass Rate** | 100% (1271 passed) | 100% (1271 passed) | ✓ | > *Benchmark: `pytest tests/functional/strategies -n 8` on identical hardware > (macOS, Python 3.11, 8 parallel xdist workers). Master measured via > `--use-installed-backtrader` against the master build.* An earlier internal benchmark on a smaller 119-strategy sample showed a comparable ~45% reduction (553.12s → 305.36s). ### 📈 Performance by Strategy Type | Strategy Category | Avg Speedup | Example | | --- | --- | --- | | Simple MA Cross | 40-45% | `test_03_two_ma`: 2.6s → 1.5s | | Multi-Indicator | 45-50% | `test_09_dual_thrust`: 59.2s → 26.9s | | Multi-Data | 42-48% | `test_02_multi_extend_data`: 23.5s → 12.6s | | Complex Strategies | 38-42% | `test_08_kelter_strategy`: 36.9s → 11.3s | --- ## 🎯 Introduction Backtrader is a powerful and flexible Python framework for backtesting trading strategies. This project is based on [backtrader](https://www.backtrader.com/) with extensive optimizations and feature enhancements, supporting **low-frequency, mid-frequency, and high-frequency** strategy development, backtesting, and live trading. ### Why Choose Backtrader? | Comparison | Backtrader | Other Frameworks | | --- | --- | --- | | Learning Curve | ⭐⭐ Gentle | ⭐⭐⭐⭐ Steep | | Development Efficiency | ⭐⭐⭐⭐⭐ Very High | ⭐⭐⭐ Average | | Built-in Indicators | 50+ | 10-30 | | Data Source Support | 20+ | 5-10 | | Community Activity | ⭐⭐⭐⭐ Active | ⭐⭐ Average | | Documentation | ⭐⭐⭐⭐⭐ Complete | ⭐⭐⭐ Average | ### Project Branches - **`master`**: Stable release branch - **`dev`**: Active development branch carrying performance optimizations and new features - **`development`**: Integration/release-candidate branch used by CI/CD before promotion --- ## ✨ Key Features ### 🚀 High-Performance Multi-Frequency Backtesting Engine ```text Three backtesting modes supported: ├── runonce (Vectorized) - Batch computation, optimal performance ├── runnext (Event-driven) - Bar-by-bar, suitable for complex logic └── Tick-level backtesting - Tick data support with tick+bar mixed mode Trading frequency spectrum: ├── Low-frequency - Daily/weekly bars, position trading ├── Mid-frequency - Minute/hour bars, intraday trading └── High-frequency - Tick-level data, market microstructure ``` ### 📊 Rich Visualization - **Plotly Interactive Charts**: Supports 100k+ data points with zoom, pan, hover - **Bokeh Real-time Charts**: Real-time data updates and multi-tab support - **Matplotlib Static Charts**: Classic plotting for papers and reports ### 📈 Professional Reports One-click generation of professional reports including: - Equity curves and drawdown charts - Sharpe ratio, Calmar ratio, SQN rating - Detailed trade statistics and P&L analysis - Export to HTML, PDF, JSON formats ### 🔧 50+ Built-in Technical Indicators Covering moving averages, momentum, volatility, trend indicators, and more. ### 🔄 Tick-Level & Mixed-Frequency Trading - **Tick-level backtesting**: Process individual tick data for high-frequency strategy research - **Tick + Bar mixed mode**: Combine tick and bar data in the same strategy - **Seamless live trading**: Same strategy code works for backtesting and live trading - **Full spectrum coverage**: Low-frequency (daily), mid-frequency (minute), and high-frequency (tick) — all unified ### 📝 TradeLogger - Real-time Trade Logging Comprehensive observer for real-time logging during backtests: - **Real-time file writing**: Logs are appended on every bar (not just at the end) - **`current_position.json`**: Updated after each bar with the latest holdings - **Strategy indicators**: Optionally log strategy-calculated indicators in data files - **Configurable format**: Tab-separated `.log` (default) or standard `.csv` - **MySQL persistence**: Order/trade/position logs saved to MySQL (`bt_order`, `bt_trade`, `bt_position`) ```python cerebro.addobserver( bt.observers.TradeLogger, log_dir='logs', log_indicators=True, file_format='log', # 'log' or 'csv' # mysql_enabled=True, # optional MySQL persistence # mysql_database='backtrder_web', ) ``` ### 📦 Modular Architecture Strategies, indicators, analyzers, and data sources can be independently extended. ### 🌍 20+ Data Source Support CSV, Pandas, Yahoo Finance, Interactive Brokers, CCXT cryptocurrency, CTP futures, and more. --- ## 📥 Quick Installation ### Requirements - **Python**: 3.8+ (3.11 recommended for ~15% performance boost) - **OS**: Windows / macOS / Linux - **RAM**: 4GB+ recommended ### From GitHub (Primary) > **Note**: The pure-Python `cloudQuant/backtrader` package is installed from source. > For the pybind11 wheel, use `pip install back-trader-cpp`. ```bash git clone https://github.com/cloudQuant/backtrader.git cd backtrader pip install -r requirements.txt pip install -U . ``` ### From Gitee (Mirror) ```bash git clone https://gitee.com/yunjinqi/backtrader.git cd backtrader pip install -r requirements.txt pip install -U . ``` ### Verify Installation ```python import backtrader as bt print(f"Backtrader version: {bt.__version__}") # Output: Backtrader version: 1.2.0 ``` ### Run Tests ```bash pytest tests -n 4 ``` --- ## 🎓 5-Minute Quickstart ### Step 1: Understand the Workflow ```text ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Prepare │ -> │ Write │ -> │ Run │ │ Data │ │ Strategy │ │ Backtest │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ v v v CSV/Pandas/API Extend Strategy cerebro.run() Implement next() ``` ### Step 2: Write Your First Strategy ```python import backtrader as bt class SmaCrossStrategy(bt.Strategy): """Moving Average Crossover Strategy: - Buy when fast SMA crosses above slow SMA - Sell when fast SMA crosses below slow SMA """ params = ( ('fast_period', 10), ('slow_period', 30), ) def __init__(self): self.fast_sma = bt.indicators.SMA(self.data.close, period=self.params.fast_period) self.slow_sma = bt.indicators.SMA(self.data.close, period=self.params.slow_period) self.crossover = bt.indicators.CrossOver(self.fast_sma, self.slow_sma) def next(self): if not self.position: if self.crossover > 0: self.buy() elif self.crossover < 0: self.close() ``` ### Step 3: Prepare Data ```python # Option 1: Load from CSV file data = bt.feeds.GenericCSVData( dataname='your_data.csv', datetime=0, open=1, high=2, low=3, close=4, volume=5, openinterest=-1, dtformat='%Y-%m-%d', ) # Option 2: Load from Pandas DataFrame import pandas as pd df = pd.read_csv('your_data.csv', parse_dates=['date'], index_col='date') data = bt.feeds.PandasData(dataname=df) # Option 3: Download from Yahoo Finance from datetime import datetime data = bt.feeds.YahooFinanceData( dataname='AAPL', fromdate=datetime(2020, 1, 1), todate=datetime(2023, 12, 31), ) ``` ### Step 4: Run Backtest ```python cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(SmaCrossStrategy) cerebro.broker.setcash(100000) cerebro.broker.setcommission(commission=0.0003) cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe') cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown') print(f'Starting: {cerebro.broker.getvalue():,.2f}') results = cerebro.run() print(f'Final: {cerebro.broker.getvalue():,.2f}') strat = results[0] print(f"Sharpe: {strat.analyzers.sharpe.get_analysis().get('sharperatio', 'N/A')}") print(f"Max DD: {strat.analyzers.drawdown.get_analysis()['max']['drawdown']:.2f}%") ``` ### Step 5: Visualize Results ```python # Plotly interactive charts (recommended) cerebro.plot(backend='plotly', style='candle') # Save to HTML from backtrader.plot import PlotlyPlot plotter = PlotlyPlot(style='candle') figs = plotter.plot(results[0]) figs[0].write_html('backtest_chart.html') ``` --- ## 📚 Core Concepts ### 1. Cerebro - The Engine ```python cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(Strategy) cerebro.addanalyzer(Analyzer) cerebro.broker.setcash(100000) results = cerebro.run() cerebro.plot() ``` ### 2. Strategy ```python class MyStrategy(bt.Strategy): params = (('period', 20),) def __init__(self): self.sma = bt.indicators.SMA(period=self.params.period) def next(self): if self.data.close[0] > self.sma[0]: self.buy() def notify_order(self, order): if order.status == order.Completed: print(f'Order executed at {order.executed.price}') ``` ### 3. Lines - Data Structure ```python self.data.close[0] # Current bar self.data.close[-1] # Previous bar self.data.open[0] # Current open self.data.high[0] # Current high self.data.volume[0] # Current volume ``` ### 4. Order Types ```python self.buy() # Market buy self.sell(price=100, exectype=bt.Order.Limit) # Limit sell self.buy_bracket(price=100, stopprice=95, limitprice=110) # Bracket order self.order_target_percent(target=0.5) # Target 50% position ``` --- ## 📦 Built-in Components ### Technical Indicators (50+) | Category | Indicators | | --- | --- | | **Moving Averages** | SMA, EMA, WMA, DEMA, TEMA, KAMA, HMA, ZLEMA | | **Momentum** | RSI, ROC, Momentum, Williams %R, Ultimate Oscillator | | **Volatility** | ATR, Bollinger Bands, Standard Deviation | | **Trend** | ADX, Aroon, Parabolic SAR, Ichimoku, DPO | | **Oscillators** | MACD, Stochastic, CCI, TSI, TRIX | ### Analyzers (17+) | Analyzer | Purpose | | --- | --- | | `SharpeRatio` | Risk-adjusted returns | | `DrawDown` | Maximum drawdown | | `TradeAnalyzer` | Trade statistics | | `Returns` | Return analysis | | `SQN` | System Quality Number | ### Data Sources (20+) | Data Source | Description | | --- | --- | | `GenericCSVData` | Generic CSV files | | `PandasData` | Pandas DataFrame | | `YahooFinanceData` | Yahoo Finance | | `IBData` | Interactive Brokers | | `CCXTFeed` | Cryptocurrency | --- ## 🔬 Advanced Topics ### Parameter Optimization ```python cerebro.optstrategy( SmaCrossStrategy, fast_period=range(5, 20, 5), slow_period=range(20, 60, 10), ) results = cerebro.run(maxcpus=4) ``` ### Multiple Data Sources ```python cerebro.adddata(data1) cerebro.adddata(data2) # In strategy price1 = self.datas[0].close[0] price2 = self.datas[1].close[0] ``` ### Custom Indicators ```python class MyIndicator(bt.Indicator): lines = ('myline',) params = (('period', 20),) def __init__(self): self.lines.myline = bt.indicators.SMA(self.data, period=self.params.period) ``` ### Professional Reports ```python cerebro.add_report_analyzers(riskfree_rate=0.02) cerebro.run() cerebro.generate_report('report.html', user='Trader', memo='Strategy Report') ``` ### Logging Backtrader uses a single logging entry point and is **silent by default** — it emits nothing until you opt in, and it never touches the root logger or a host application's logging setup. ```python import backtrader as bt # Opt in: console + optional rotating file. Idempotent. bt.configure_logging(level="INFO", log_file="run.log") logger = bt.get_logger(__name__) # -> "backtrader." logger.info("strategy started") bt.set_level("DEBUG") # raise verbosity at runtime bt.reset_logging() # back to the silent default (tests) ``` | Level | When | | --- | --- | | `CRITICAL` | engine cannot continue | | `ERROR` | recoverable failure (order rejected, data load failed) | | `WARNING` | degraded / auto-corrected behavior | | `INFO` | milestones (start/stop, fills) | | `DEBUG` | per-bar diagnostics | Framework code routes through `backtrader.utils.log_message.get_logger` rather than the stdlib `logging` directly. See `docs/LOGGING_GUIDELINES.md` for the full conventions (hot-path guard, exception-logging rules, print-vs-logging). --- ## 🏗 Project Architecture ```text backtrader/ ├── backtrader/ # Core codebase │ ├── cerebro.py # Main engine │ ├── strategy.py # Strategy base │ ├── indicator.py # Indicator base │ ├── analyzer.py # Analyzer base │ ├── feed.py # Data feed base │ ├── broker.py # Broker base │ ├── indicators/ # 52 technical indicators │ ├── analyzers/ # 17 analyzers │ ├── feeds/ # 21 data sources │ ├── plot/ # Visualization │ └── reports/ # Report generation ├── examples/ # Example code ├── tests/ # Test cases (3,200+ tests) ├── scripts/ # Install, test, benchmark, and maintenance helpers └── docs/ # Documentation ``` --- ## 🧪 Testing The repository ships with **3,200+ tests** covering unit, functional, integration, and performance suites. The functional strategy directory alone contains **1,271 inlined regression tests** spanning 22 strategy categories (trend following, mean reversion, asset allocation, machine learning, options, pairs trading, etc.). ### Test Tiers (Fast / Slow / Full) The strategy regression suite is large (~10 min for the full run), so tests are split into tiers by measured per-file duration. The fastest ~35% of strategy tests stay in the fast loop; the slowest ~65% are auto-tagged `slow` (no test files are edited — the split is applied dynamically from a committed durations file in `conftest.py`). ```bash # Fast dev loop (~3.5 min): all non-strategy tests + the fastest ~35% of # strategy tests. Best for "did my change break anything" iteration. make test-fast # == pytest tests -m "not slow" -n 8 -q # Slow tier (~7 min): only the slowest ~65% of strategy tests that test-fast skips make test-slow # == pytest tests -m slow -n 8 -q # Strategy regression only (all 1,271 strategy tests, ~4 min on `dev`) make test-strategies # == pytest tests/functional/strategies -n 8 -q # Full suite — everything in parallel (~10 min) make test-all # == pytest tests -n 8 -q ``` Tune how many strategy tests stay in the fast loop with `BT_SLOW_PERCENTILE` (default `35`, i.e. keep the fastest 35%): ```bash # Stricter sub-3-minute loop — keep only the fastest ~25% of strategy tests BT_SLOW_PERCENTILE=25 make test-fast # Broader coverage — keep the fastest ~50% BT_SLOW_PERCENTILE=50 make test-fast ``` Refresh the duration data after adding/removing strategy tests: ```bash python scripts/refresh_strategy_durations.py ``` ### Run All Tests Directly ```bash pytest tests -n 8 # Wrapper scripts live under scripts/ bash scripts/run_tests.sh -n 8 scripts\run_tests.bat -n 8 ``` ### Helper Scripts Root-level install and test wrappers have been consolidated under `scripts/`. Use these paths from the repository root: ```bash bash scripts/install_unix.sh scripts\install_win.bat bash scripts/run_tests.sh scripts\run_tests.bat ``` `mypy-report.txt` is a CI-generated temporary file. It is intentionally not tracked; the GitHub Actions mypy gate recreates it during each lint job. ### Run a Specific Category ```bash # Run only the strategies suite (1,271 tests, ~4 minutes on `dev`, ~7 on `master`) pytest tests/functional/strategies -n 8 # Run a single strategy file pytest tests/functional/strategies/others/test_0019_pattern_detection.py # Run only the slow / fast tier explicitly pytest tests -m slow -n 8 pytest tests -m "not slow" -n 8 ``` ### Choosing Which `backtrader` to Test Against When you run pytest from the repository root, `import backtrader` resolves to the local repo copy by default (the `backtrader/` directory next to `conftest.py`). This is what you want during development. If you also have an older or release version installed via `pip install backtrader`, you can switch the test suite to that copy on demand: ```bash # Default — uses the local repo copy (development) pytest tests/functional/strategies -n 8 # Switch to the installed (site-packages) copy via env var BACKTRADER_USE_INSTALLED=1 pytest tests/functional/strategies -n 8 # Or via CLI flag pytest tests/functional/strategies -n 8 --use-installed-backtrader ``` The active `backtrader.__file__` is printed in the pytest session header so you can confirm which copy each run picked up. The switch works under `pytest-xdist` parallel mode as well. ### Test Data Test fixtures live under `tests/datas/`. The MT5-formatted daily CSVs live in `tests/datas/mt5_1d_data/` and cover the symbols referenced by the inlined regression suite (XAUUSD, XAGUSD, IVV, IEF, GLD, IWM, etc.). --- ## Repository Maintenance Notes - The canonical changelog is [`CHANGELOG.md`](CHANGELOG.md). Historical `ChangeLog.md` and version-specific root changelog files were consolidated. - Generated reports such as `mypy-report.txt` are ignored and should not be committed. - Legacy local workflow metadata under `.windsurf/workflows` and obsolete `.kiro/steering` files are not part of the tracked project guidance. - Helper entrypoints are kept in `scripts/`; avoid reintroducing duplicate root-level install or test scripts. --- ## 📖 API Documentation ### Online Documentation - **ReadTheDocs (EN)**: - **ReadTheDocs (ZH)**: - **GitHub Pages**: ### Build Local Documentation ```bash cd docs pip install -r requirements.txt make html make serve ``` ### Quick API Reference ```python import backtrader as bt # Cerebro cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(Strategy) cerebro.broker.setcash(100000) results = cerebro.run() cerebro.plot() # Strategy methods self.buy(size=100) self.sell(size=100) self.close() self.order_target_percent(target=0.5) # Common indicators bt.indicators.SMA(data, period=20) bt.indicators.RSI(data, period=14) bt.indicators.MACD(data) bt.indicators.BollingerBands(data) ``` --- ## ❓ FAQ ### Q1: How to set slippage? ```python cerebro.broker.set_slippage_fixed(0.01) # Fixed slippage cerebro.broker.set_slippage_perc(0.001) # Percentage slippage ``` ### Q2: How to limit trade size? ```python class FixedSizer(bt.Sizer): params = (('stake', 100),) def _getsizing(self, comminfo, cash, data, isbuy): return self.params.stake cerebro.addsizer(FixedSizer, stake=100) ``` ### Q3: How to get all transactions? ```python cerebro.addanalyzer(bt.analyzers.Transactions, _name='txn') results = cerebro.run() transactions = results[0].analyzers.txn.get_analysis() ``` ### Q4: Backtest too slow? ```python cerebro.run(runonce=True) # Use vectorized mode (default) cerebro.run(maxcpus=4) # Use multiprocessing for optimization ``` --- ## 🤝 Contributing We welcome contributions to improve code quality, fix bugs, and enhance performance. ### 🐛 Reporting Indicator Discrepancies If you find that the `dev` branch produces different results than `master` for the same strategy, this likely indicates an indicator calculation bug. Please help us fix it. ### 📝 Pull Request Guidelines #### 1. Create a Test Case Add a new test case that: - ✅ Passes on **both** `master` and `dev` branches - ✅ Demonstrates the bug or validates the fix - ✅ Includes clear assertions and expected values ```python # Example: tests/functional/strategies//test_NNNN_your_indicator.py import backtrader as bt class TestYourIndicator(bt.Strategy): def __init__(self): self.indicator = bt.indicators.YourIndicator(self.data) def next(self): # Add assertions to validate correctness pass def test_your_indicator(): cerebro = bt.Cerebro() # ... setup and run assert result == expected_value ``` #### 2. Run Code Quality Checks ```bash # Option 1: Run the full optimization script (recommended) bash scripts/optimize_code.sh # Option 2: Run tests manually pytest tests -n 4 ``` Both must pass without errors. #### 3. Verify All Tests Pass ```bash pytest tests -n 4 -v ``` Expected output: all 3,200+ tests pass. #### 4. (Optional) Test Against the Installed Package If you want to validate that the installed wheel still works (for example, before publishing a release), see [Testing → Choosing Which backtrader to Test Against](#choosing-which-backtrader-to-test-against). #### 5. Submit Your PR 1. Fork the repository 2. Create a feature branch: `git checkout -b fix/indicator-name` 3. Commit your changes: `git commit -m "fix: correct calculation in YourIndicator"` 4. Push to your fork: `git push origin fix/indicator-name` 5. Open a Pull Request with: - Clear description of the issue - Reference to the test case - Explanation of the fix ### 🎯 Contribution Areas We especially welcome contributions in: - 🐛 **Bug Fixes**: Indicator calculation errors, edge cases - ✅ **Test Coverage**: Additional test cases for existing indicators - 📊 **Performance**: Further optimization opportunities - 📚 **Documentation**: Improved examples and tutorials - 🔧 **Features**: New indicators, analyzers, or data feeds ### 💡 Best Practices - Write clear, self-documenting code - Add docstrings to all public methods - Follow existing code style (enforced by `ruff` and `black`) - Keep changes focused and atomic - Update documentation when adding features --- ## ⚠️ Important Disclaimer ### Risk Warning **THIS SOFTWARE IS PROVIDED FOR EDUCATIONAL AND RESEARCH PURPOSES ONLY.** - ⚠️ **Trading Risk**: Algorithmic trading involves substantial risk of loss. Past performance does not guarantee future results. - 🐛 **Software Status**: This project is under active development and may contain bugs or calculation errors. - 💰 **Financial Liability**: **You are solely responsible for any financial losses** incurred from using this software. - 🔍 **Verification Required**: Always verify backtest results against known benchmarks before live trading. - 📊 **No Warranty**: This software is provided "AS IS" without warranty of any kind, express or implied. **By using this software, you acknowledge and accept all risks associated with algorithmic trading.** --- ## 📄 License This project is licensed under [GPLv3](LICENSE). --- ## 📞 Contact - **GitHub**: - **Gitee**: - **Author Blog**: - **ReadTheDocs (EN)**: - **ReadTheDocs (ZH)**: - **GitHub Pages**: ---
**If this project helps you, please give us a ⭐ Star!**
--- # 📖 中文文档 [**English**](#-backtrader) | **中文** --- ## ⚡ 性能概览 当前活跃的 `dev` 分支承接了原 `development` 分支上的优化工作。在**完整的 1,271 个策略 回归套件**(`tests/functional/strategies`,`-n 8`)上,`dev` 分支的总执行时间相比 `master` 分支**几乎缩短一半**。 ### 📊 基准测试结果(完整策略套件) | 指标 | Master 分支 | Dev 分支 | 提升幅度 | | --- | --- | --- | --- | | **总执行时间** | 438.96 秒(7分18秒) | 236.36 秒(3分56秒) | **-46.2%** | | **加速比** | 1.00x | **1.86x** | ✓ | | **测试策略数** | 1,271 | 1,271 | ✓ | | **测试通过率** | 100%(1271 passed) | 100%(1271 passed) | ✓ | > *基准测试:在相同硬件上运行 `pytest tests/functional/strategies -n 8`(macOS, > Python 3.11,8 个并行 xdist 进程)。Master 通过 `--use-installed-backtrader` > 指向 master 构建版本测得。* 更早期在 119 个策略小样本上的内部基准也得到了相近的约 45% 降幅(553.12 秒 → 305.36 秒)。 ### 🔧 核心优化项 1. **移除元编程开销** - 消除动态元类属性拦截机制 - 采用显式描述符参数系统 - 结果:属性访问开销降低约 40% 2. **经纪商性能增强** - 移除 `BackBroker` 和 `CommInfoBase` 的全局 `__getattribute__` 重载 - 在热路径(`BackBroker.next()`、`_get_value()`)实现本地参数缓存 - 缓存高频访问参数(`mult`、`cash`、`stocklike`) - 结果:经纪商操作速度提升 42.5% 3. **指标计算优化** - 优化布林带 `once()` 方法,使用更快的 NaN 检查 - 减少冗余数组边界检查 - 缓存数学函数和常量 - 结果:指标计算速度提升 15-20% 4. **减少内置函数调用** - 最小化热路径中的 `isinstance()`、`hasattr()`、`len()` 调用 - 在适当场景使用类型恒等检查 - 结果:Python 层面开销降低约 10% ### 📈 不同策略类型的性能提升 | 策略类别 | 平均加速 | 示例 | | --- | --- | --- | | 简单均线交叉 | 40-45% | `test_03_two_ma`: 2.6 秒 → 1.5 秒 | | 多指标策略 | 45-50% | `test_09_dual_thrust`: 59.2 秒 → 26.9 秒 | | 多数据源 | 42-48% | `test_02_multi_extend_data`: 23.5 秒 → 12.6 秒 | | 复杂策略 | 38-42% | `test_08_kelter_strategy`: 36.9 秒 → 11.3 秒 | --- ## 🎯 项目简介 Backtrader 是一个功能强大、灵活易用的 Python 量化交易回测框架。本项目基于 [backtrader](https://www.backtrader.com/) 进行了大量优化和功能扩展,支持 **低频、中频、高频** 全频段交易策略的研发、回测与实盘交易。 ### 为什么选择 Backtrader? | 对比项 | Backtrader | 其他框架 | | --- | --- | --- | | 学习曲线 | ⭐⭐ 平缓 | ⭐⭐⭐⭐ 陡峭 | | 策略开发效率 | ⭐⭐⭐⭐⭐ 极高 | ⭐⭐⭐ 一般 | | 内置指标数量 | 50+ | 10-30 | | 数据源支持 | 20+ | 5-10 | ### 项目分支 - **`master`**:稳定发布分支 - **`dev`**:活跃开发分支,承载性能优化与新特性 - **`development`**:集成 / 候选发布分支,用于 CI/CD 验证后再晋级 --- ## ✨ 核心特性 - 🚀 **高性能多频段回测引擎**:支持向量化、事件驱动和 Tick 级别三种模式 - 🔄 **Tick 级别回测与混合交易**:支持 Tick 数据回测、Tick + Bar 混合模式,打通低频、中频、高频全频段交易 - 📊 **丰富的可视化**:Plotly 交互图表、Bokeh 实时图表 - 📈 **专业回测报告**:一键生成 HTML/PDF/JSON 格式报告 - 🔧 **50+ 内置技术指标**:均线、动量、波动率、趋势等 - 📝 **TradeLogger 实时日志**:回测过程中实时记录订单、交易、持仓、行情数据,支持 MySQL 持久化 - 📦 **模块化架构**:策略、指标、分析器可独立扩展 - 🌍 **20+ 数据源支持**:CSV、Pandas、Yahoo、IB、CCXT、CTP 期货等 - 🔗 **回测与实盘无缝衔接**:同一套策略代码可直接用于回测和实盘交易 --- ## 📥 快速安装 > **注意**:纯 Python 版 `cloudQuant/backtrader` 从源码安装。pybind11 wheel 可使用 > `pip install back-trader-cpp` 直接安装。 ```bash # 从 GitHub 克隆 git clone https://github.com/cloudQuant/backtrader.git cd backtrader pip install -r requirements.txt pip install -U . # 或从 Gitee 镜像克隆 git clone https://gitee.com/yunjinqi/backtrader.git cd backtrader pip install -r requirements.txt pip install -U . # 验证安装 python -c "import backtrader as bt; print(bt.__version__)" ``` --- ## 🎓 5 分钟入门 ```python import backtrader as bt # 定义策略 class SmaCrossStrategy(bt.Strategy): params = (('fast', 10), ('slow', 30)) def __init__(self): fast_sma = bt.indicators.SMA(period=self.params.fast) slow_sma = bt.indicators.SMA(period=self.params.slow) self.crossover = bt.indicators.CrossOver(fast_sma, slow_sma) def next(self): if not self.position and self.crossover > 0: self.buy() elif self.position and self.crossover < 0: self.close() # 创建引擎 cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(SmaCrossStrategy) cerebro.broker.setcash(100000) # 运行回测 results = cerebro.run() cerebro.plot(backend='plotly') ``` --- ## 📝 日志 Backtrader 提供**统一的日志入口**,且**默认完全静默**——不主动调用就没有任何 输出,也不会修改 root logger 或干扰宿主程序的日志配置。 ```python import backtrader as bt # 开启日志:控制台 + 可选滚动文件,幂等 bt.configure_logging(level="INFO", log_file="run.log") logger = bt.get_logger(__name__) # -> "backtrader.<模块名>" logger.info("strategy started") bt.set_level("DEBUG") # 运行时调高日志级别 bt.reset_logging() # 还原到默认静默状态(测试用) ``` | 级别 | 使用场景 | | --- | --- | | `CRITICAL` | 引擎无法继续 | | `ERROR` | 可恢复的失败(订单被拒、数据加载失败) | | `WARNING` | 降级 / 自动修正行为 | | `INFO` | 里程碑事件(启动/结束、成交) | | `DEBUG` | 每根 bar 的诊断信息 | 框架内部统一通过 `backtrader.utils.log_message.get_logger` 获取 logger,而非 直接 `import logging`。完整规范(热路径守护、异常日志写法、print 取舍)见 `docs/LOGGING_GUIDELINES.md`。 --- ## 🧪 测试 仓库自带 **3,200+ 个测试**,覆盖单元、功能、集成和性能四个层级。仅 `tests/functional/strategies/` 这一目录就有 **1,271 个内联回归测试**,分布在 22 个策略类别下(趋势跟踪、均值回归、资产配置、机器学习、期权、配对交易等)。 ### 分级测试(快速 / 慢速 / 全量) 策略回归套件很大(全量约 10 分钟),因此按单测文件的实测耗时做了分级:最快的 ~35% 策略测试留在快速档,其余最慢的 ~65% 自动标记为 `slow`(**不改任何测试文件** ——拆分由 `conftest.py` 读取已提交的耗时数据动态完成)。 ```bash # 快速开发回路(约 3.5 分钟):全部非策略测试 + 最快 ~35% 的策略测试。 # 最适合「改完代码看有没有引入 bug」的日常迭代。 make test-fast # 等价于 pytest tests -m "not slow" -n 8 -q # 慢速档(约 7 分钟):test-fast 跳过的那最慢 ~65% 策略测试 make test-slow # 等价于 pytest tests -m slow -n 8 -q # 只跑策略回归(全部 1,271 个策略测试,`dev` 约 4 分钟) make test-strategies # 等价于 pytest tests/functional/strategies -n 8 -q # 全量 —— 所有测试并行(约 10 分钟) make test-all # 等价于 pytest tests -n 8 -q ``` 用环境变量 `BT_SLOW_PERCENTILE` 调节快速档里保留多少策略测试(默认 `35`,即保留 最快 35%): ```bash # 更严格、压进 3 分钟内 —— 只保留最快 ~25% 的策略测试 BT_SLOW_PERCENTILE=25 make test-fast # 覆盖更全 —— 保留最快 ~50% BT_SLOW_PERCENTILE=50 make test-fast ``` 增删策略测试后刷新耗时数据: ```bash python scripts/refresh_strategy_durations.py ``` ### 直接运行全部测试 ```bash pytest tests -n 8 # 封装脚本统一放在 scripts/ 下 bash scripts/run_tests.sh -n 8 scripts\run_tests.bat -n 8 ``` ### 辅助脚本 根目录安装和测试封装脚本已统一整理到 `scripts/`。从仓库根目录使用: ```bash bash scripts/install_unix.sh scripts\install_win.bat bash scripts/run_tests.sh scripts\run_tests.bat ``` `mypy-report.txt` 是 CI 在 mypy 门禁中临时生成的报告文件,不需要提交到仓库; GitHub Actions 每次 lint job 都会重新生成它。 ### 只运行某一类 ```bash # 只跑策略套件(1,271 个测试,`dev` 约 4 分钟,`master` 约 7 分钟) pytest tests/functional/strategies -n 8 # 跑单个策略文件 pytest tests/functional/strategies/others/test_0019_pattern_detection.py # 显式只跑慢速 / 快速档 pytest tests -m slow -n 8 pytest tests -m "not slow" -n 8 ``` ### 选择测试目标:本地代码 vs 已安装包 从仓库根目录运行 pytest 时,`import backtrader` 默认解析到本地仓库副本(与 `conftest.py` 同级的 `backtrader/` 目录)。开发期间这是你想要的行为。 如果你额外用 `pip install backtrader` 装过其他版本(比如稳定版或旧版本),可以 临时把测试切到已安装的那一份: ```bash # 默认 —— 使用本地仓库代码(开发常用) pytest tests/functional/strategies -n 8 # 通过环境变量切到 site-packages 安装的副本 BACKTRADER_USE_INSTALLED=1 pytest tests/functional/strategies -n 8 # 或通过命令行参数 pytest tests/functional/strategies -n 8 --use-installed-backtrader ``` 每次启动 pytest 都会在 session header 中打印当前生效的 `backtrader.__file__`, 方便确认本次跑的到底是哪一份。该开关在 `pytest-xdist` 并行模式下同样生效。 ### 测试数据 测试夹具放在 `tests/datas/` 下。MT5 格式的日线 CSV 在 `tests/datas/mt5_1d_data/`,覆盖了内联回归套件引用的所有标的(XAUUSD、 XAGUSD、IVV、IEF、GLD、IWM 等)。 --- ## 仓库维护说明 - 唯一的变更日志文件是 [`CHANGELOG.md`](CHANGELOG.md)。历史上的 `ChangeLog.md` 和版本专用根目录 changelog 已合并。 - `mypy-report.txt` 等生成报告已加入忽略规则,不应提交。 - `.windsurf/workflows` 和过期的 `.kiro/steering` 不再作为跟踪的项目指导文件。 - 安装、测试等辅助入口统一放在 `scripts/`,不要重新引入根目录重复脚本。 --- ## 🤝 贡献指南 我们欢迎所有有助于提升代码质量、修复 bug 和增强性能的贡献。 ### 🐛 报告指标差异 如果您发现 `dev` 分支与 `master` 分支在相同策略下产生不同结果,这很可能表明 存在指标计算 bug。请帮助我们修复。 ### 📝 Pull Request 提交规范 #### 1. 创建测试用例 添加一个新的测试用例,要求: - ✅ 在 **master** 和 **dev** 分支上都能通过 - ✅ 能够演示 bug 或验证修复 - ✅ 包含清晰的断言和预期值 #### 2. 运行代码质量检查 ```bash # 方式 1:运行完整优化脚本(推荐) bash scripts/optimize_code.sh # 方式 2:手动运行测试 pytest tests -n 4 ``` 两个命令都必须无错误通过。 #### 3. 验证所有测试通过 ```bash pytest tests -n 4 -v ``` 预期输出:3,200+ 个测试全部通过。 #### 4. 提交 PR 1. Fork 本仓库 2. 创建功能分支:`git checkout -b fix/indicator-name` 3. 提交更改:`git commit -m "fix: 修正 YourIndicator 的计算"` 4. 推送到您的 fork:`git push origin fix/indicator-name` 5. 创建 Pull Request,包含: - 问题的清晰描述 - 测试用例的引用 - 修复方案的说明 ### 🎯 贡献方向 我们特别欢迎以下方面的贡献: - 🐛 **Bug 修复**:指标计算错误、边界情况处理 - ✅ **测试覆盖**:为现有指标添加更多测试用例 - 📊 **性能优化**:进一步的优化机会 - 📚 **文档完善**:改进示例和教程 - 🔧 **功能扩展**:新指标、分析器或数据源 ### 💡 最佳实践 - 编写清晰、自文档化的代码 - 为所有公共方法添加文档字符串 - 遵循现有代码风格(由 `ruff` 和 `black` 强制执行) - 保持更改集中和原子化 - 添加功能时更新文档 --- ## ❓ 常见问题 ### Q1:如何设置滑点? ```python cerebro.broker.set_slippage_fixed(0.01) # 固定滑点 cerebro.broker.set_slippage_perc(0.001) # 百分比滑点 ``` ### Q2:如何限制单笔交易数量? ```python class FixedSizer(bt.Sizer): params = (('stake', 100),) def _getsizing(self, comminfo, cash, data, isbuy): return self.params.stake cerebro.addsizer(FixedSizer, stake=100) ``` ### Q3:如何获取所有交易记录? ```python cerebro.addanalyzer(bt.analyzers.Transactions, _name='txn') results = cerebro.run() transactions = results[0].analyzers.txn.get_analysis() ``` ### Q4:回测速度慢怎么办? ```python cerebro.run(runonce=True) # 使用向量化模式(默认) cerebro.run(maxcpus=4) # 参数优化时使用多进程 ``` --- ## ⚠️ 重要声明 ### 风险警示 **本软件仅供教育和研究目的使用。** - ⚠️ **交易风险**:算法交易存在重大亏损风险。历史业绩不代表未来表现。 - 🐛 **软件状态**:本项目正在积极开发中,可能包含 bug 或计算错误。 - 💰 **财务责任**:**使用本软件产生的任何财务损失由您自行承担**。 - 🔍 **验证要求**:实盘交易前,务必对照已知基准验证回测结果。 - 📊 **无担保**:本软件按"原样"提供,不提供任何明示或暗示的担保。 **使用本软件即表示您承认并接受算法交易相关的所有风险。** --- ## 📞 联系方式 - **GitHub**: - **Gitee**: - **作者博客**: - **在线文档 (EN)**: - **在线文档 (ZH)**: - **GitHub Pages**: ---
**如果本项目对您有帮助,请点个 ⭐ Star 支持我们!** Made with ❤️ by CloudQuant