Skip to content
SlashClone
Made by@qtrader

Backtest runner

@qtrader/backtest-runner

Backtest a trading idea on an OHLCV CSV with honest assumptions: next-bar fills, slippage, commission, no look-ahead. Built-in SMA crossover, RSI mean reversion, and buy-and-hold, plus a one-file plug-in format for your own strategies. Writes equity curve and trades CSVs and metrics (CAGR, volatility, Sharpe, Sortino, max drawdown, win rate, exposure). Not financial advice.

SkillTradingv1.0.0 (latest)Tested
Activity
New: be the first to try it
  1. 1# backtest-runner
  2. 2
  3. 3Test a trading idea on historical prices before you risk anything. Give it an OHLCV CSV and a strategy (SMA crossover, RSI mean reversion, buy-and-hold, or your own one-file plug-in) and it writes an equity curve, a trade list, and the metrics people actually compare: CAGR, volatility, Sharpe, Sortino, max drawdown, win rate, and exposure.
  4. 4
  5. 5**Who it is for:** people learning systematic trading who want honest numbers, not a curve that only works because it peeked at tomorrow.
  6. 6
  7. 7Not financial advice. Backtests describe the past under simplified assumptions.
  8. 8
  9. 9## How it stays honest
  10. 11- Decisions use bars up to today only. Strategies get a read-only view where tomorrow reads as `undefined`.
  11. 12- Orders fill at the **next bar's open**, never at the close that produced the signal.
  12. 13- Slippage (default 5 bps per side) and commission (per share and/or bps) are charged on every fill.
  13. 14- Integer shares by default, long only unless you pass `--allow-short`.
  14. 15- A signal on the last bar is never filled. Open trades at the end are reported as open, not counted as wins.
  15. 17## Example
  16. 19```bash
  17. 20node scripts/backtest.mjs --data examples/prices.csv --strategy sma-cross --param fast=10 --param slow=30
  18. 21```
  19. 23```text
  20. 24sma-cross {"fast":10,"slow":30} on examples/prices.csv, 2024-01-02 to 2025-03-24 (320 bars)
  21. 25Total 0.37% | CAGR 0.29% | Vol 11.18% | Sharpe 0.08 | Sortino 0.11 | Max DD -16.60%
  22. 26Trades 5 (+0 open) | Win rate 40.00% | Exposure 42.50% | Buy and hold 9.38%
  23. 27```
  24. 29`examples/prices.csv` is a made-up series (a trend plus cycles plus seeded noise), not real market data. Files written: `out/backtest-equity.csv`, `out/backtest-trades.csv`, `out/backtest-metrics.json`.
  25. 31Your own strategy is one file. See `examples/strategies/donchian-breakout.mjs`:
  26. 33```bash
  27. 34node scripts/backtest.mjs --data data/SPY-1Day.csv --strategy-file strategies/my-idea.mjs --param lookback=50
  28. 35```
  29. 37## Hand check (verify it yourself)
  30. 39**Costs and fills.** Bars (open, close): d0 (100, 100), d1 (101, 104), d2 (105, 103), d3 (102, 106), d4 (107, 108). Capital 10,000, slippage 10 bps, commission $0.01 per share. Signal long on d0's close, flat on d2's close.
  31. 41- Buy on d1 open: 101 x 1.001 = 101.101. Shares = floor(10,000 / (101.101 + 0.01)) = 98. Cash = 10,000 - 98 x 101.101 - 0.98 = 91.122.
  32. 42- Equity d1 = 91.122 + 98 x 104 = 10,283.122. Equity d2 = 91.122 + 98 x 103 = 10,185.122.
  33. 43- Sell on d3 open: 102 x 0.999 = 101.898. Cash = 91.122 + 98 x 101.898 - 0.98 = 10,076.146.
  34. 44- Trade pnl = +76.146 after costs. Exposure = 2 of 5 bars = 40%.
  35. 46**Metrics.** Buy and hold on closes 100, 100, 110, 121, 108.9, 119.79 (open = close), 10,000 capital, fractional, no costs. The signal on bar 0 fills at bar 1's open (100), so equity is 10,000, 10,000, 11,000, 12,100, 10,890, 11,979.
  36. 48- Returns: 0, 0.10, 0.10, -0.10, 0.10. Mean 0.04. Sample variance 0.032 / 4 = 0.008.
  37. 49- Sharpe = 0.04 / sqrt(0.008) x sqrt(252) = 7.0993. Sortino = 0.04 / sqrt(0.01 / 5) x sqrt(252) = 14.1986.
  38. 50- Max drawdown = 10,890 / 12,100 - 1 = -10%. Total return 19.79%. Exposure 5 of 6 bars.
  39. 52**SMA cross.** fast 2, slow 3 on closes 10, 9, 8, 9, 10, 11, 10, 9, 8. On bar 4, SMA2 = 9.5 > SMA3 = 9, so buy on bar 5's open (11). On bar 7, SMA2 = 9.5 < SMA3 = 10, so sell on bar 8's open (8).
  40. 54`node scripts/selftest.mjs` checks all of these, plus Wilder RSI by hand, a short sale, a long-to-short flip, and that strategies cannot see or change future bars.
  41. 56## What it can access
  42. 58- Reads your price CSV from `data/` and strategy files from `strategies/`. Writes results to `out/` and new strategy files to `strategies/`.
  43. 59- Runs only its own scripts with Node. No network, no API keys.
  44. 61## Setup
  45. 63Node 22 or newer. Nothing to install. Get prices from any source as CSV, or use the `alpaca-connector` kit: `node scripts/alpaca.mjs bars --symbol SPY --start 2021-01-01 --out data/SPY-1Day.csv`.