VP Script
Errors and refusals
Everything below is refused on purpose, and each refusal names its line. This page is the other half: what to write instead.
Refused when it compiles
These never run at all, so you get a line number rather than a mystery later.
| You wrote | Why, and what instead |
|---|---|
import / export | A script is one self-contained file. Paste what you need, or publish it and let people install it. |
async / await / yield | A script is synchronous: the bars are already in hand, so there is nothing to wait for. |
class / enum / namespace | Not available. Plain functions and object literals are. |
eval / Function | Evaluating text as code. An indicator has no reason to, and refusing it makes the automatic review mean something. |
Date | A script has no clock. Every temporal fact is on the bar: read bars[i].time. |
Intl | Locale-dependent formatting would render differently for different readers. Use toFixed. |
a name starting __vp | Reserved: the loop budget compiles to a variable in your scope, and shadowing it would disable your own guard. |
Date and Intl are refused at compile time as a COURTESY. They are absent from the runtime either way. Reaching for them is a reasonable mistake, and a line number beats a ReferenceError thrown from inside your own code with nothing explaining why a standard global is missing. Why determinism matters.Stopped while it runs
“This indicator took too long”: a loop that will not finish, or one doing far too much per bar. Every loop carries an iteration budget and is stopped rather than freezing the chart. You will not meet it doing anything reasonable over a chart’s worth of bars; if you have, look for a loop inside a loop.
Your indicator draws nothing: usually a series that is entirely null. A foreign timeframe has not arrived yet, a lookback is longer than the chart, or arithmetic turned a gap into NaN. log the series: it prints its length and first values.
Not accepted by the review
Publishing runs your script against a set of deliberately awkward charts. The verdict is shown verbatim, with the fixture or line that caught it. The usual causes:
- It differs between two runs. The same bars are run twice and compared. Something in your script is not a pure function of its inputs.
- It throws on an awkward chart. A single bar, or none at all. Guard your indexing rather than assuming there is a
[i - 1]. - It is over the time budget on the largest test chart.
- Its text reads like an advertisement. Every string your script would draw is checked by the same rules as your title and description, because a link in a label is a link in front of a reader.
- It is an exact copy of an indicator somebody else published.
A rejection is not a dead end: fix it and submit again. That creates a new version, and nobody is moved onto it automatically.
Limits you can hit
Submissions are capped per day, and a captcha is asked for periodically, which is enough that a person iterating never notices, and a loop does. Plots, labels, boxes and alerts each have a ceiling; a script that wants a thousand labels is usually one that should be drawing a plot instead.