Metadata-Version: 2.4
Name: chidoribt
Version: 0.2.4
Summary: Multi-asset unified portfolio backtesting framework
License: MIT
Project-URL: Repository, https://github.com/MioQuant/chidoribt
Project-URL: Bug Tracker, https://github.com/MioQuant/chidoribt/issues
Keywords: backtesting,finance,trading,portfolio,quantitative
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.23.0
Requires-Dist: pandas>=1.5.0
Provides-Extra: numba
Requires-Dist: numba>=0.56; extra == "numba"
Provides-Extra: tsdb
Requires-Dist: mini-tsdb>=0.1.0; extra == "tsdb"
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9; extra == "postgres"
Provides-Extra: full
Requires-Dist: numba>=0.56; extra == "full"
Requires-Dist: mini-tsdb>=0.1.0; extra == "full"
Requires-Dist: psycopg2-binary>=2.9; extra == "full"
Dynamic: license-file

# ChidoriBT ⚡

**超高速多資產回測框架 / High-Performance Multi-Asset Backtesting Framework**

<p align="center">
  <img src="https://tse2.mm.bing.net/th/id/OIP.tzQLNs50GB5WLS5qufp1gAAAAA?cb=thfc1falcon&rs=1&pid=ImgDetMain&o=7&rm=3" alt="Chidori — 千鳥" width="200"/>
</p>

---

## 專案名稱由來

> **千鳥（Chidori）** — 精準、迅速，如閃電貫穿黑暗。

「千鳥」是忍術中以**極致速度**與**精準集中**著稱的雷遁之術。ChidoriBT 的設計哲學正是如此：

- **快**：Numba JIT 機器碼，單次回測比 multibacktesting Broker 快 **300 ～ 900 倍**；參數掃描比 vectorbt 快 **636 倍**
- **省**：參數掃描記憶體僅需 vectorbt 的 **1/24**（7.5 MB vs 175 MB，240 組合）
- **準**：JIT 與純 Python 事件驅動路徑結果差距 **< 0.5%**

---

## 效能基準（Benchmark）

> 測試規模：**100 支台股 × 726 個交易日**（2023–2025）  
> 策略：子母線型態（ChildParentStrategy）+ 止損 / 止盈  
> 計時範圍：含訊號計算，不含 DB 載入與 PanelData 建構

### 單次回測速度

| 路徑 | 說明 | 均值 | vs Broker |
|------|------|:----:|:---------:|
| **A** PatternBacktester | 純 Python 事件迴圈 | ~33 ms | **~880×** |
| **B** Numba 固定倉位 | JIT machine code | ~28 ms | **>900×** |
| **D** NumPy + Numba rebalance | 向量化等權再平衡 | ~70 ms | **~415×** |
| **G** ChidoriBT JIT | `fast=True`，端到端 | ~110 ms | **~265×** |
| **H** ChidoriBT 事件驅動 | `fast=False`，含完整 order log | ~104 ms | **~280×** |
| **E** Broker（基準）¹ | multibacktesting 事件迴圈 | ~29 s | 1× |

> ¹ 基準引擎（Path E）為作者基於 [`backtesting.py`](https://github.com/kernc/backtesting.py) 改寫的多資產版本 **multibacktesting**，其逐 bar 事件迴圈在大規模資產時效能受限，是 ChidoriBT 的優化起點。

### 參數掃描 vs vectorbt（240 組合，100 股 × 726 日）

> 執行：`python run_speed_benchmark.py --scan --stocks 100 --scan-hold-days "3,5,7,10,15" --scan-stop-loss "0.03,0.05,0.08,0.10" --scan-take-profit "0.08,0.12,0.15,0.20" --scan-trade-size "20000,30000,50000"`

| 引擎 | 均值（240 組合） | 吞吐量 | 峰值記憶體 | 加速比 |
|------|:-----------:|:------:|:----------:|:------:|
| **ChidoriBT** ParamScanner（`prange` 並行） | **22.9 ms** | **10,466 組合/s** | **7.5 MB** | **636×** |
| vectorbt `from_signals` serial | 14.59 s | 16 組合/s | 175.2 MB | 1× |

**技術原因：**

- ChidoriBT 使用 `@njit(parallel=True, cache=True)` 搭配 `prange` 零複製批量掃描，所有組合共享同一份 price matrix，並行計算最終資金曲線
- vectorbt 每個組合均須重建 DataFrame + `Portfolio.from_signals`，物件開銷線性累積
- 記憶體優勢來自 NumPy in-place 操作，無 Pandas 中間物件

---

ChidoriBT is a high-performance Python backtesting library for multi-asset portfolio strategies. It supports vectorized (NumPy/Numba) execution, flexible data ingestion (DataFrame, PostgreSQL, Mini-TSDB), and produces detailed trade/equity analytics.

---

## Installation

**Core（DataFrame 傳入，無額外依賴）：**

```bash
pip install chidoribt
```

**含 Numba JIT 加速（建議）：**

```bash
pip install "chidoribt[numba]"
```

**含 PostgreSQL 資料載入：**

```bash
pip install "chidoribt[postgres]"
```

**含 Mini-TSDB 時序資料庫：**

```bash
pip install "chidoribt[tsdb]"
```

**全功能安裝：**

```bash
pip install "chidoribt[full]"
```

---

## 快速開始

### 方式一：直接傳入 DataFrame（OHLCV 格式，與原版 backtesting.py 欄位相容）

```python
import pandas as pd
from chidoribt import ChidoriBT
from chidoribt.strategies.base import MultiAssetStrategy

# 單資產 OHLCV DataFrame（欄位：Open, High, Low, Close, Volume）
ohlcv_df = pd.read_csv("AAPL.csv", index_col="date", parse_dates=True)

bt = ChidoriBT(data=ohlcv_df, cash=100_000, commission=0.001)
result = bt.run()

print(result["metrics"])
# {'total_return': 0.42, 'sharpe': 1.35, 'max_drawdown': -0.18, ...}
```

### 方式二：多資產 stacked DataFrame

```python
from chidoribt import ChidoriBT
from chidoribt.core import PanelData

# stacked DataFrame 欄位：stock_id, date, Open, High, Low, Close, Volume
panel = PanelData.from_dataframe(stacked_df)

bt = ChidoriBT(data=panel, strategy=MyStrategy, cash=100_000)
result = bt.run()
equity_curve = result["equity_curve"]   # pd.Series，index 為日期
trades_df    = result["trades"]         # pd.DataFrame，每筆交易記錄
```

### 方式三：Mini-TSDB 載入（需 `pip install "chidoribt[tsdb]"`）

```python
from chidoribt.data import StockTSDBLoader
from chidoribt import ChidoriBT
from chidoribt.core import PanelData

loader = StockTSDBLoader("./data/tsdb")
raw_df = loader.load(start_date="2023-01-01", end_date="2025-12-31")

bt = ChidoriBT(
    data=PanelData.from_dataframe(raw_df),
    strategy=MyStrategy,
    cash=100_000,
)
result = bt.run()
```

### 方式四：PostgreSQL 載入（需 `pip install "chidoribt[postgres]"`）

```python
from chidoribt.data import StockPostgresLoader
from chidoribt import ChidoriBT
from chidoribt.core import PanelData

loader = StockPostgresLoader()  # 讀取環境變數 DB_HOST / DB_PORT / DB_NAME
raw_df = loader.load(start_date="2023-01-01", end_date="2025-12-31")

bt = ChidoriBT(
    data=PanelData.from_dataframe(raw_df),
    strategy=MyStrategy,
    cash=100_000,
)
result = bt.run()
```

---

## 參數掃描（ParamScanner）

```python
from chidoribt import PanelData, ParamScanner

panel = PanelData.from_dataframe(stacked_df)

scanner = ParamScanner(panel, mode="fixed")   # "fixed" | "rebalance"
results = scanner.scan(
    hold_days_list   = [3, 5, 7, 10, 15],
    stop_loss_list   = [0.03, 0.05, 0.08, 0.10],
    take_profit_list = [0.08, 0.12, 0.15, 0.20],
    trade_size_list  = [20_000, 30_000, 50_000],
    initial_cash     = 1_000_000,
    max_positions    = 20,
)

# results: list[dict] — 每組合的 final_equity / sharpe / max_drawdown
best = max(results, key=lambda r: r["final_equity"])
print(best)
```

---

## 自訂策略

```python
from chidoribt.strategies.base import MultiAssetStrategy

class MyStrategy(MultiAssetStrategy):
    def init(self):
        pass

    def next(self, i: int, data):
        for asset in self.assets:
            close = data.Close[asset][i]
            ma20  = data.MA_20[asset][i]
            if close > ma20:
                self.buy(asset, size=100)
            elif close < ma20:
                self.sell(asset, size=100)
```

---

## 執行模式

| 模式 | `mode` 參數 | `fast` 參數 | 說明 |
|------|-------------|-------------|------|
| JIT 加速（預設） | `"portfolio"` | `True` | Numba JIT，最快；無中間物件 |
| 事件驅動 | `"portfolio"` | `False` | 純 Python 迴圈，含完整 fills/orders log |
| 等權再平衡 | `"rebalance"` | — | 每日依等權分配再平衡 |

```python
# Numba JIT 加速（預設 fast=True）
result = bt.run(mode="portfolio", fast=True)

# 純 Python 路徑（含完整 audit log，適合嵌入 ML 模型）
result = bt.run(mode="portfolio", fast=False)
fills_df  = result["fills"]   # 每筆成交記錄
orders_df = result["orders"]  # 每筆下單記錄
```

---

## 回傳結果欄位

```python
result = bt.run()

result["equity_curve"]  # pd.Series — 每日資金曲線
result["trades"]        # pd.DataFrame — 每筆已平倉交易
result["fills"]         # pd.DataFrame — 每筆成交（fast=False 時）
result["metrics"]       # dict — 績效指標
```

**`metrics` 常用欄位：**

| 欄位 | 說明 |
|------|------|
| `total_return` | 總報酬率 |
| `sharpe` | 年化 Sharpe ratio |
| `max_drawdown` | 最大回撤 |
| `win_rate` | 勝率 |
| `n_trades` | 總交易筆數 |

---

## Mini-TSDB 資料遷移

若已有 PostgreSQL 歷史資料，可使用遷移腳本一次性搬移：

```bash
# 初次遷移
python migrate_pg_to_tsdb.py --tsdb-dir ./data/tsdb

# 清除舊資料後重新遷移
python migrate_pg_to_tsdb.py --tsdb-dir ./data/tsdb --clean

# 查看 TSDB 內容
python migrate_pg_to_tsdb.py --tsdb-dir ./data/tsdb --list
```

---

## 套件架構

```
chidoribt/
├── __init__.py          # ChidoriBT, PanelData, ParamScanner（公開 API）
├── engine.py            # 主引擎
├── core/                # PanelData, UnifiedPortfolio, ParamScanner
├── strategies/          # MultiAssetStrategy base + 範例策略
├── analytics/           # 績效指標計算
├── data/                # 資料載入子套件
│   ├── _postgres.py     # StockPostgresLoader（psycopg2，optional）
│   └── _tsdb.py         # StockTSDBLoader（mini-tsdb，optional）
├── adapters/            # 內部 adapter 層
└── utils/               # trade_logger 等工具
```

---
