Skip to main content
Turn a signal into a strategy and see what it would have made after it paid to trade. Declare strategy() in place of indicator(), say on each closed bar what position you want, and the engine fills it, charges what the venue would have charged, and keeps the account.
The chart shows each fill as an arrow on the price and the equity curve in a pane of its own, beside buy-and-hold. Report in the legend opens the Strategy report.

Targets

strategy.target(fraction) is the position you want as a fraction of equity: 1 fully long, −1 fully short, 0 flat. strategy.targetUsd(usd) takes a notional instead. Both are held to leverage times equity. Nothing makes a strategy trade both ways: one that only ever asks for 0 to 1 is long only, and one that asks for −1 to 0 is short only.
  • A target applies on closed bars only. By default it fills at the next bar’s open, so a script never trades on a close it hasn’t seen. fill: 'close' fills at the signal bar’s own close, the shortcut many testers take.
  • The same target again holds the position as it is: calling strategy.target(1) every bar doesn’t trade as equity moves. A new value trades to it.
  • An order under $10 is not sent, as the venue would refuse it.
strategy.position, strategy.equity, strategy.cash and strategy.costs read the account back in a handler.

What it pays

Each cost is charged on its own and listed in the report, so you can see what took the edge.
  • Fees: every fill is a taker fill at the venue’s base tier (Hyperliquid’s taker rate, twice it on HIP-3, Lighter’s). fees: { takerBps } sets your own.
  • Slippage: what a market order of the fill’s size paid against the order book at the signal bar’s close, the book the next open trades into. The archive records what $10k, $100k and $1M cost on each bar it holds (Hyperliquid and HIP-3); sizes between are interpolated, smaller ones run down to half the spread, and larger ones carry the last stretch on (the report counts them). On a bar the archive has no reading for, a fill costs fallbackBps (2). The report says how many fills the book priced and from when. slippage: { bps } uses a flat cost throughout.
  • Funding: every hour a position is open it pays or collects that hour’s rate on its notional, as the venue settles it, from 2025-03-01. A 4h or 1d bar charges each hour inside it. Funding needs a time chart of 1m or longer; on other charts pass funding: false.
  • Liquidation: with leverage above 1, a position whose equity at the bar’s worst price falls below maintenance margin is closed where it would have been (half the initial margin at the market’s highest leverage). An account never goes below zero; the report says what the venue’s backstop took.
A backtest is one path through history. A strategy tuned until it looks good on that path has learned the path. Check it on a stretch it was not tuned on, and score its forecast with ml.score (see statistics and machine learning), before you trust it.

History

from: '2025-03-01' loads the chart’s history back to that date before the run, so the report covers more than the bars on screen. The run takes longer on more history; the legend says how far it has got.

The Strategy report

The report opens in a panel of its own, from Report in the legend or the legend’s menu.
  • Overview: the net result against buy-and-hold, max drawdown, Sharpe, profit factor, trades, win rate and exposure; the equity curve with its drawdown underneath; what each cost took from the gross; and the forecast’s score when the script declares an ml.score.
  • Trades: every round trip with its costs. Click one to bring it into view on the chart.
  • Assumptions: every rule and source the run used: fills, fees, slippage, where the order book and funding start, leverage and maintenance.
Every fill is simulated in the browser and nothing reaches an exchange. The same bars and settings give the same trades on every run.

Next step

See it on real data in RSI PCA forecast and Funding carry.
Last modified on October 25, 2026