Claude
Skills
Sign in
Back

polars-backtest

Included with Lifetime
$97 forever

Help users backtest trading strategies with polars-backtest library. Use when user asks about backtesting, portfolio simulation, trading strategy analysis, or working with polars-backtest.

General

What this skill does


# Polars Backtest Usage Skill

Help users use polars-backtest to backtest their trading strategies efficiently.

## Installation

```bash
pip install polars-backtest
# or
uv add polars-backtest
```

## Data Format

**Long format**: one row per (date, symbol) pair.

```python
import polars as pl
import polars_backtest as pl_bt

df = pl.DataFrame({
    "date": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"],
    "symbol": ["2330", "2317", "2330", "2317"],
    "close": [100.0, 50.0, 102.0, 51.0],
    "weight": [0.6, 0.4, 0.6, 0.4],
})
```

## Basic Usage

```python
# DataFrame namespace
result = df.bt.backtest(trade_at_price="close", position="weight")

# Function API
result = pl_bt.backtest(df, trade_at_price="close", position="weight")

# With report (includes trades, stats)
report = df.bt.backtest_with_report(position="weight", resample="M")
```

## Complete Parameter Reference

### Column Mapping Parameters

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `trade_at_price` | `"close"` | str \| Expr | Price column for trade execution. Use adjusted close for accurate returns. |
| `position` | `"weight"` | str \| Expr | Position weight column. Can be float weights or boolean signals (True=buy). Null values are filled with 0. |
| `date` | `"date"` | str \| Expr | Date column. Must be sortable. |
| `symbol` | `"symbol"` | str \| Expr | Stock symbol/ticker column. |
| `open` | `"open"` | str \| Expr | Open price column. Required when `touched_exit=True`. |
| `high` | `"high"` | str \| Expr | High price column. Required when `touched_exit=True`. |
| `low` | `"low"` | str \| Expr | Low price column. Required when `touched_exit=True`. |
| `factor` | `"factor"` | str | Adjustment factor column. Used to calculate raw price: `raw_price = adj_price / factor`. If column doesn't exist, defaults to 1.0. Useful for dividend/split adjusted prices. |

### Rebalancing Parameters

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `resample` | `"D"` | str \| None | Rebalance frequency. Options: `"D"` (daily), `"W"` (weekly), `"W-FRI"` (weekly on Friday), `"M"` (monthly), `"Q"` (quarterly), `"Y"` (yearly), `None` (only when position changes). |
| `resample_offset` | `None` | str \| None | Delay rebalance execution. Examples: `"1d"` (1 day delay), `"2d"`, `"1W"`. Useful for simulating delayed signal execution. |

### Cost Parameters

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `fee_ratio` | `0.001425` | float | Transaction fee rate (both buy and sell). Taiwan stock default is 0.1425%. |
| `tax_ratio` | `0.003` | float | Transaction tax rate (sell only). Taiwan stock default is 0.3%. |

### Risk Management Parameters

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `stop_loss` | `1.0` | float | Stop loss threshold. Exit when loss reaches this ratio. `1.0` = disabled (100% loss). Example: `-0.1` exits at 10% loss. |
| `take_profit` | `inf` | float | Take profit threshold. Exit when profit reaches this ratio. `inf` = disabled. Example: `0.2` exits at 20% profit. |
| `trail_stop` | `inf` | float | Trailing stop threshold. Exit when price drops this much from peak. `inf` = disabled. Example: `0.05` exits when 5% below peak. |
| `position_limit` | `1.0` | float | Maximum weight per single stock. `1.0` = no limit. Example: `0.1` caps each stock at 10% of portfolio. |
| `touched_exit` | `False` | bool | Use intraday OHLC for stop detection. When True, checks if stop/take profit was touched during the day using high/low prices, not just close. Requires open/high/low columns. |
| `stop_trading_next_period` | `True` | bool | When stop is triggered, skip trading in the next period. Prevents immediate re-entry after stop. |

### Calculation Mode Parameters

| Parameter | Default | Description |
|-----------|---------|-------------|
| `finlab_mode` | `False` (backtest) / `True` (backtest_with_report) | Use Finlab-compatible calculation. When True, boolean signals are converted to equal weights. Affects weight normalization behavior. |
| `retain_cost_when_rebalance` | `False` | When rebalancing, retain the cost basis instead of resetting. Affects return calculation for partially sold positions. |

### Benchmark Parameters (backtest_with_report only)

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `benchmark` | `None` | str \| DataFrame \| None | Benchmark for alpha/beta calculation. **str**: symbol value in your data (e.g., `"0050"`), uses that symbol's price. **DataFrame**: must have `date` and `creturn` columns (cumulative return starting at 1.0). |

### Liquidity Metrics Parameters (backtest_with_report only)

| Parameter | Default | Type | Description |
|-----------|---------|------|-------------|
| `limit_up` | `"limit_up"` | str | Column name for limit-up price. Used to calculate `buyHigh` metric (ratio of entries at limit-up). |
| `limit_down` | `"limit_down"` | str | Column name for limit-down price. Used to calculate `sellLow` metric (ratio of exits at limit-down). |
| `trading_value` | `"trading_value"` | str | Column for trading value (e.g., `close * volume`). Used to calculate `capacity` metric. |

## BacktestReport Object

```python
report = df.bt.backtest_with_report(position="weight")

# Properties
report.creturn      # DataFrame with date, creturn columns
report.trades       # DataFrame with trade records (see Trades DataFrame section)
report.stats        # Statistics DataFrame (shortcut for get_stats())
report.fee_ratio    # Fee ratio used
report.tax_ratio    # Tax ratio used
report.stop_loss    # Stop loss threshold (None if disabled)
report.take_profit  # Take profit threshold (None if disabled)
report.trail_stop   # Trail stop threshold (None if disabled)
report.trade_at     # Trade timing (e.g., 'close')
report.resample     # Resample frequency
report.benchmark    # Benchmark DataFrame (can be set after creation)

# Set benchmark after creation
report.benchmark = benchmark_df
```

## Trades DataFrame

The `report.trades` property returns a DataFrame with detailed trade records:

| Column | Type | Description |
|--------|------|-------------|
| `stock_id` | str | Stock symbol/ticker |
| `entry_date` | Date | Trade entry execution date. `null` for pending entry trades. |
| `exit_date` | Date | Trade exit execution date. `null` for open/pending positions. |
| `entry_sig_date` | Date | Date when entry signal was generated. |
| `exit_sig_date` | Date | Date when exit signal was generated. `null` if no exit signal yet. |
| `position` | f64 | Position weight at entry. |
| `period` | i32 | Number of trading days held. |
| `return` | f64 | Trade return ratio (e.g., 0.05 = 5% profit). |
| `entry_price` | f64 | Entry execution price (adjusted price, for return calculation). |
| `exit_price` | f64 | Exit execution price (adjusted price). `null` for open positions. |
| `entry_raw_price` | f64 | Entry raw price (unadjusted = entry_price / factor, for liquidity metrics). |
| `exit_raw_price` | f64 | Exit raw price (unadjusted = exit_price / factor). `null` for open positions. |
| `mae` | f64 | Maximum Adverse Excursion - worst drawdown during trade (negative value). |
| `gmfe` | f64 | Gross Maximum Favorable Excursion - best unrealized gain during trade. |
| `bmfe` | f64 | Before-MAE MFE - MFE at the time when MAE occurred. |
| `mdd` | f64 | Maximum drawdown during the trade. |
| `pdays` | i32 | Number of profitable days during the trade. |

### Pending Trades

Pending trades represent signals that exist but haven't been executed yet (T+1 execution model):

- **Pending entry**: `entry_date = null`, `entry_sig_date = latest signal date`
  - Stock has a buy signal but trade hasn't executed yet
- **Pending exit**: `exit_date = null`, `exit_sig_date = latest signal date`
  - Stock has a sell signal but trade hasn't closed yet

```python
# Get pending entry

Related in General