$npx -y skills add marketcalls/vectorbt-backtesting-skills --skill backtestQuick backtest a strategy on a symbol. Creates a complete .py script with data fetch, signals, backtest, stats, and plots.
| 1 | Create a complete VectorBT backtest script for the user. |
| 2 | |
| 3 | ## Arguments |
| 4 | |
| 5 | Parse `$ARGUMENTS` as: strategy symbol exchange interval |
| 6 | |
| 7 | - `$0` = strategy name (e.g., ema-crossover, rsi, donchian, supertrend, macd, sda2, momentum) |
| 8 | - `$1` = symbol (e.g., SBIN, RELIANCE, NIFTY). Default: SBIN |
| 9 | - `$2` = exchange (e.g., NSE, NFO). Default: NSE |
| 10 | - `$3` = interval (e.g., D, 1h, 5m). Default: D |
| 11 | |
| 12 | If no arguments, ask the user which strategy they want. |
| 13 | |
| 14 | ## Instructions |
| 15 | |
| 16 | 1. Read the vectorbt-expert skill rules for reference patterns |
| 17 | 2. Create `backtesting/{strategy_name}/` directory if it doesn't exist (on-demand) |
| 18 | 3. Create a `.py` file in `backtesting/{strategy_name}/` named `{symbol}_{strategy}_backtest.py` |
| 19 | 4. Use the matching template from `rules/assets/{strategy}/backtest.py` as the starting point |
| 20 | 5. The script must: |
| 21 | - Load `.env` from the project root using `find_dotenv()` (walks up from script dir automatically) |
| 22 | - Fetch data via `client.history()` from OpenAlgo |
| 23 | - If user provides a DuckDB path, load data directly via `duckdb.connect(path, read_only=True)` instead of OpenAlgo API. Auto-detect format: Historify (`market_data` table, epoch timestamps) vs custom (`ohlcv` table, date+time). See vectorbt-expert `rules/duckdb-data.md`. |
| 24 | - If `openalgo.ta` is not importable (standalone DuckDB), use inline `exrem()` fallback. |
| 25 | - **Use OpenAlgo ta for ALL indicators by default** (EMA, SMA, RSI, MACD, BBands, ATR, ADX, STDDEV, MOM, and 90+ more) - `from openalgo import ta` |
| 26 | - **Only use TA-Lib if the user explicitly says "talib"/"TA-Lib"** in their request; specialty indicators (Supertrend, Donchian, Ichimoku, HMA, KAMA, ALMA, ZLEMA, VWMA) always come from OpenAlgo ta regardless, since TA-Lib has no equivalent |
| 27 | - Use `ta.exrem()` to clean duplicate signals (always `.fillna(False)` before exrem) |
| 28 | - Run `vbt.Portfolio.from_signals()` with `min_size=1, size_granularity=1` |
| 29 | - **Indian delivery fees**: `fees=0.00111, fixed_fees=20` for delivery equity |
| 30 | - Fetch NIFTY benchmark via OpenAlgo (`symbol="NIFTY", exchange="NSE_INDEX"`) |
| 31 | - Print full `pf.stats()` |
| 32 | - **Print Strategy vs Benchmark comparison table** (Total Return, Sharpe, Sortino, Max DD, Win Rate, Trades, Profit Factor) |
| 33 | - **Explain the backtest report** in plain language for normal traders |
| 34 | - Generate the OpenStatz interactive dashboard tearsheet via `ostz.dashboard(...)` if `openstatz` is available - a self-contained offline HTML file, no server needed (always use OpenStatz, never QuantStats; never the legacy `ostz.reports.html` static report). **Set `strategy_returns.name` (e.g. `"EMA 20/50 Crossover - SBIN"`) and `benchmark.name` before calling `dashboard()`** - that name, not the `title=` argument, is what the tearsheet shows as the strategy header/column/legend (see the openstatz-tearsheet rule) |
| 35 | - Plot equity curve + drawdown using Plotly (`template="plotly_dark"`) |
| 36 | - Export trades to CSV |
| 37 | 5. Never use icons/emojis in code or logger output |
| 38 | 6. For futures symbols (NIFTY, BANKNIFTY), use lot-size-aware sizing: |
| 39 | - NIFTY: `min_size=65, size_granularity=65` (effective 31 Dec 2025) |
| 40 | - BANKNIFTY: `min_size=30, size_granularity=30` |
| 41 | - Use `fees=0.00018, fixed_fees=20` for F&O futures |
| 42 | |
| 43 | ## Available Strategies |
| 44 | |
| 45 | | Strategy | Keyword | Template | |
| 46 | |----------|---------|----------| |
| 47 | | EMA Crossover | `ema-crossover` | `assets/ema_crossover/backtest.py` | |
| 48 | | RSI | `rsi` | `assets/rsi/backtest.py` | |
| 49 | | Donchian Channel | `donchian` | `assets/donchian/backtest.py` | |
| 50 | | Supertrend | `supertrend` | `assets/supertrend/backtest.py` | |
| 51 | | MACD Breakout | `macd` | `assets/macd/backtest.py` | |
| 52 | | SDA2 | `sda2` | `assets/sda2/backtest.py` | |
| 53 | | Momentum | `momentum` | `assets/momentum/backtest.py` | |
| 54 | | Dual Momentum | `dual-momentum` | `assets/dual_momentum/backtest.py` | |
| 55 | | Buy & Hold | `buy-hold` | `assets/buy_hold/backtest.py` | |
| 56 | | RSI Accumulation | `rsi-accumulation` | `assets/rsi_accumulation/backtest.py` | |
| 57 | |
| 58 | ## Benchmark Rules |
| 59 | |
| 60 | - Default: NIFTY 50 via OpenAlgo (`symbol="NIFTY", exchange="NSE_INDEX"`) |
| 61 | - If user specifies a different benchmark, use that instead |
| 62 | - For yfinance: use `^NSEI` for India, `^GSPC` (S&P 500) for US markets |
| 63 | - Always compare: Total Return, Sharpe, Sortino, Max Drawdown |
| 64 | |
| 65 | ## Example Usage |
| 66 | |
| 67 | `/backtest ema-crossover RELIANCE NSE D` |
| 68 | `/backtest rsi SBIN` |
| 69 | `/backtest supertrend NIFTY NFO 5m` |