Appearance
book
How do you backtest a portfolio of many names at once? Call book.target with the names and the weights of equity each should hold. The engine makes the trades on the next open, charges the costs book.config sets, and keeps one account, which book.equity() reads. A strategy() trades one symbol an order at a time, and a book trades a list by saying where it should end up.
ameno
indicator("Momentum book, long and short")
array<string> m = request.universe(20, "stablecoin")
array<float> mom = request.each(m, close / close[20] - 1)
// Stating initial_capital on a universe book also caps each fill at 1% of
// the bar's dollar volume and charges impact under it: see volume_cap.
book.config(fee_bps = 10, slippage_bps = 5, initial_capital = 100000)
// Weights of equity: above-average momentum long, below short,
// scaled so the absolute weights sum to 1.
book.target(m, cs.scale(cs.demean(mom)), reason = "20-day momentum")
plot(book.equity(), "Equity")A book's calls do nothing inside a request.* expression, where they read na and the run warns. The Strategy Tester, the terminal's backtest report, reads a book as it reads a strategy: each name's stretch from flat to flat is a trade, and its report adds turnover, costs and what each name held. See the book.
book.config
AmenoScript only
ameno
book.config(fee_bps, slippage_bps, funding, fill, initial_capital, funding_venue, accounting, volume_cap, impact_bps, venue, unlisted, daily) → voidSets the book's costs, fills and capital. Call it before the first book.target, since capital stops changing once anything has traded.
A negative cost, a fill other than "open" or "close", or a capital of 0 or less stops the script with an error.
One default depends on the rest of the call. A book that trades a request.universe list and states its initial_capital caps each fill at 1% of the bar's dollar volume, and charges impact_bps on what it takes. Any other book has no cap, and a universe book that states no capital warns that nothing limits its fills. volume_cap = 0 turns the cap off.
| Parameter | Default | Description |
|---|---|---|
fee_bpsseries float | 0 | Paid on the value of every fill, in basis points. |
slippage_bpsseries float | 0 | Also paid on the value of every fill, in basis points. |
fundingseries bool | false | true pays each perpetual's funding on what the book holds: a long pays a positive rate and a short receives it. A name with no funding series pays none, and the run says so. CMC: names never pay. |
fillseries string | "open" | "open" fills each name at its first open after the close that made the target. "close" fills a name at that close when its bar closes then, and any other name waits for its next open. |
initial_capitalseries float | 100000 | The money the book starts with. |
funding_venueseries string | "binance" | The exchange whose funding history funding reads. |
accountingseries string | "book" | The book's own accounting, as this page describes it. Other values are reserved. |
volume_capseries float | The largest share of a bar's dollar volume one fill may take. A fill past it is cut, and the rest stays as drift until the next target. Left out, 0.01 or none, as above. 0 turns the cap off. | |
impact_bpsseries float | 100 | Under the cap, a fill also pays this times the square root of its share of the bar's volume: 10 bps at 1% of volume. |
venueNo effect hereseries string | Reserved. It changes nothing in a backtest. | |
unlistedNo effect hereseries string | "cash" | Reserved. It changes nothing in a backtest. |
dailyarray<string> | Names to mark and fill from their daily bars, whatever the chart's timeframe. Each trades only on the chart bar that closes with its day, at that close, so it needs fill = "close" on the book's own accounting. Set it before the first target. |
book.target
AmenoScript only
ameno
book.target(names, weights, reason) → voidStates what the whole book should hold, as weights of equity, on this bar's close.
A name left out goes to zero, an na weight reads as zero, a name listed twice adds up, and a negative weight is a short. Weights needn't sum to 1. On a bar with no call, nothing trades and each weight drifts with its price. Only fills pay costs, so drift is free. A name stops trading once its last bar is 10 days old, or two chart bars when those are longer: it leaves at its last printed close and pays fee and slippage, and the run says so. A different count of names and weights stops the script.
A name the script didn't get from request.universe makes the run warn that the list was chosen today, since a list of today's survivors flatters any backtest.
| Parameter | Default | Description |
|---|---|---|
namesarray<string> | The symbols, an array<string>. | |
weightsarray<float> | One weight per name, as a fraction of equity. | |
reasonseries string | "" | A note the report shows beside the rebalance. |
See targets.
book.equity
AmenoScript only
ameno
book.equity() → series floatThe book's equity at this bar's close.
book.turnover
AmenoScript only
ameno
book.turnover() → series floatWhat this bar's fills traded, as a fraction of equity.
book.fee
AmenoScript only
ameno
book.fee() → series floatWhat this bar's fills paid in fees, slippage and impact, as a fraction of equity.
book.funding
AmenoScript only
ameno
book.funding() → series floatWhat the book paid in funding on this bar, as a fraction of equity. A receipt reads negative.
book.weights
AmenoScript only
ameno
book.weights(names) → array<float>Each name's weight of equity at this bar's close, and 0 for a name the book doesn't hold.
| Parameter | Description |
|---|---|
namesarray<string> | The symbols to read, in the order you want them back. |