start_backtest
Run a backtest of an indicator rule on one stock or ETF, on daily bars.
No setting has to be settled before it runs: what the request leaves open (the stock or fund, the
history, the entry and exit levels, the costs) runs with sensible defaults, which the result names in
one short line; a change is a new run. `question` titles its report. The call waits for the run while it
is likely to finish inside it, then answers with the result; the run's card in the chat shows the result
or, for a longer run, how far it is, and fills in by itself, with the next steps as choices. A run
started here needs no `show_report_card`.
Every account runs it within a daily allowance; a refused call does not count, and get_started and
every run's answer give today's count.
A run takes about 30 seconds to 3 minutes. The call returns
`{task_id, status, kind, dashboard_url}` at once.
`get_backtest_progress(task_id)` reports progress; when the run has
finished, its answer carries `result`: the summary in words and, for
a run of a year or longer, a few rounded figures (the run's return
next to simply holding the same stock over the same dates, Sharpe,
worst drop, trades), and `report_url`, the full report.
`list_indicators()` lists the indicators, their settings and the
columns each one computes. An indicator is written
`{"id": "rsi", "params": {"length": 14}}`.
Args:
ticker: Stock or ETF symbol (uppercase).
entry_indicator / entry_conditions: The entry signal (required).
exit_indicator / exit_conditions: Optional.
confirmation_indicator / confirmation_conditions: Optional, a filter that
must also hold on the day the entry fires. The common use is a trend
filter: Larry Connors' two-day RSI pullback buys only while the close is
above its 200-day average, written as confirmation_indicator
{"id": "sma", "params": {"length": 200}} and confirmation_conditions
[{"column": "close", "operator": ">", "value": "SMA_200"}].
timeframe: '1d' (daily bars, the only timeframe this connector runs).
duration: The history tested, a span back from today: '60d', '6m',
'1y', '2y', '3y', '5y', '10y' or 'max' (the whole history held, up to 30 years).
There is no start date: 'since 2010' is '10y' or 'max', and the
figures carry the years the run covered.
direction: 'long' | 'short' | 'both'.
position_sizing: 'fixed' | 'percent_equity' (the default, as in
the QuanterLab UI).
risk_per_trade: Share of the account each trade uses. 1.0, the
default, is the whole account, as in the QuanterLab UI; a
smaller share leaves the rest in cash and scales the result
down with it. Sizing across several positions (Kelly, GARCH,
fixed) is handled in QuanterLab's portfolio and paper-trading
tools.
stop_loss_pct / take_profit_pct / max_holding_days: Optional exits.
spread_bps / commission_per_trade: Trading costs (default a 10
basis point spread and no commission).
oos_pct: Share of the history held back, 0-100 (default 0). The
run tests only the earlier part, and its result and report say
the held-back part was never tested; the same run again with
`oos_pct` 0 tests the whole history.
Conditions are lists of `{"column": ..., "operator": ..., "value": ...}`;
every condition in a list has to hold.
operator: ">", ">=", "<", "<=", "==", "!=", "crosses_above" or
"crosses_below".
column: a column the strategy's indicators compute, as
`list_indicators()` names it ("RSI_14"; "MACD_12_26_9",
"MACDh_12_26_9" and "MACDs_12_26_9" for the MACD line,
histogram and signal line), or a price field ("close").
value: a number, or another column the strategy computes
(SMA_50 against SMA_200 needs an sma of each length among
the strategy's indicators).
Entry and exit usually mirror each other: RSI below 30 in, above 70
out; MACD crossing above 0 in, crossing below 0 out. An exit identical
to its entry closes on the entry bar or never, and the run makes no
trades. A golden cross is entry_indicator sma 50 and exit_indicator
sma 200, with entry SMA_50 crosses_above SMA_200 and exit SMA_50
crosses_below SMA_200; a 200-day trend rule is sma 200 in both lanes,
with close crosses_above SMA_200 in and crosses_below out.
Example, long-only MACD momentum on PLTR over three years:
start_backtest(
ticker="PLTR",
entry_indicator={"id": "macd",
"params": {"fast": 12, "slow": 26, "signal": 9}},
entry_conditions=[{"column": "MACD_12_26_9",
"operator": "crosses_above",
"value": 0}],
exit_indicator={"id": "macd",
"params": {"fast": 12, "slow": 26, "signal": 9}},
exit_conditions=[{"column": "MACD_12_26_9",
"operator": "crosses_below",
"value": 0}],
timeframe="1d", duration="3y", direction="long",
)
question: Optional. One sentence restating what the run should answer
("does the 2-day RSI pullback beat holding SPY?"), not the person's
message: the title of the report the finished run becomes, and kept
only as that.
`report_url` is the run written up as a QuanterLab report (the answer
against simply holding the stock and SPY, the charts, the numbers,
what the test cannot tell), and the run's card shows its link, which
opens without a login. A run can also be kept in the user's library with
`save_workflow_result` (the result) and `save_trading_config` (the
settings), when the user wants to keep it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ticker | Yes | ||
| oos_pct | No | ||
| duration | No | 2y | |
| question | No | ||
| direction | No | long | |
| timeframe | No | 1d | |
| spread_bps | No | ||
| stop_loss_pct | No | ||
| exit_indicator | No | ||
| risk_per_trade | No | ||
| entry_indicator | Yes | ||
| exit_conditions | No | ||
| position_sizing | No | percent_equity | |
| take_profit_pct | No | ||
| entry_conditions | Yes | ||
| max_holding_days | No | ||
| commission_per_trade | No | ||
| confirmation_indicator | No | ||
| confirmation_conditions | No |