pinescript-core
/pinescript-core
Use when writing or reading Pine Script language fundamentals — @version, script types (indicator/strategy/library), type system (series/simple/const), var/varip/input.*, control flow, user-defined functions/types, gotchas (repainting, na handling, max_bars_back).
- Author
- kasperchengh ↗
- Repository
- multicharts-powerlanguage ↗
- Licence
- MIT
- Last repository change
- 12.06.2026
Assessment and security
- Files in this package
- 1
- Scripts
- 0
- HTML comments
- 0
- URLs in SKILL.md
- 0
No signals detected. Repository changed on 12.06.2026, without references to retired models or APIs.
MIT, open: use and modify while retaining author attribution.
What it does and when to use it
Use when writing or reading Pine Script language fundamentals — @version, script types (indicator/strategy/library), type system (series/simple/const), var/varip/input.*, control flow, user-defined functions/types, gotchas (repainting, na handling, max_bars_back).
Original author description
Use when writing or reading Pine Script language fundamentals — @version, script types (indicator/strategy/library), type system (series/simple/const), var/varip/input.*, control flow, user-defined functions/types, gotchas (repainting, na handling, max_bars_back).
How it works
- 1. Versioning
- 2. Script Types
- 3. Type System
- 4. Declarations
- 5. Control Flow
- 6. User-Defined Functions & Types
- 7. Common Gotchas
SKILL.md preview
---
name: pinescript-core
description: Use when writing or reading Pine Script language fundamentals — @version, script types (indicator/strategy/library), type system (series/simple/const), var/varip/input.*, control flow, user-defined functions/types, gotchas (repainting, na handling, max_bars_back).
---
# Pine Script Core — Language Fundamentals
## 1. Versioning
Every Pine Script file must declare its version on the very first line using a compiler annotation:
```pine
//@version=5
indicator("My Indicator")
```
Or for version 6:
```pine
//@version=6
indicator("My Indicator")
```
**Always specify the version.** Omitting it defaults to version 1 behavior, which is almost never what you want. TradingView will warn you about version-less scripts, and many modern features simply won't compile.
### v5 vs v6 key differences
| Area | v5 | v6 |
|---|---|---|
| Type system | Implicit casting in many places | Stricter — explicit casts required more often |
| `request.*()` arguments | `symbol`/`timeframe` must be `simple string` | Accept `series string` — "dynamic requests" |
| `and` / `or` operators | Both operands always evaluated | Lazy (short-circuit) evaluation |
| `bool` values | Can be `na` | Strictly `true`/`false` — never `na` |
| `matrix.*` namespace | Available | Extended with more methods |
| `polyline.*` drawing | Available (added to v5 in 2023) | Available |
| `chart.point` type | Available (added to v5 in 2023) for coordinate-aware drawings | Available |
| `UDT` (user-defined types) | Available — methods attach via the `method` keyword (added to v5 in 2023) | Available |
| `import` libraries | Available; libraries can export methods | Available |
**Version target:** All examples in this skill use `//@version=5`. TradingView may show a deprecation warning recommending v6 — this is non-blocking and the code compiles and runs correctly. v6 introduces syntax changes that may require adjustments; test on v6 separately if needed.
---
## 2. Script Types
Every Pine Script file must declare exactly one script type on the line immediately after the version annotation. There are three types:
### `indicator()`
Used for overlays and studies that display data but place no trades.
```pine
//@version=5
indicator(
title = "My Study",
shorttitle = "MS",
overlay = true, // draw on price chart; false = separate pane
precision = 2,
max_bars_back = 500,
max_lines_count = 50
)
```
- Supports `alertcondition()`.
- Cannot call `strategy.*` order functions — they are not available in indicator context.
- `overlay = true` renders on the main price chart; `overlay = false` opens a sub-pane.
### `strategy()`
Used when you want to backtest or forward-test trading logic. Enables the full `strategy.*` order API.
```pine
//@version=5
strategy(
title = "My Strategy",
shorttitle = "MS",
overlay = true,
initial_capital = 10000,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 10,
commission_type = strategy.commission.percent,
commission_value = 0.1,
slippage = 1,
pyramiding = 0,
calc_on_every_tick = false
)
```
- Cannot use `alertcondition()` — use `alert()` instead.
- Order functions: `strategy.entry()`, `strategy.exit()`, `strategy.close()`, `strategy.order()`.
- `pyramiding` controls how many open entries in the same direction are allowed simultaneously.
- `calc_on_every_tick = true` recalculates intra-bar on live data, which can affect backtest realism.
### `library()`
Used to create reusable packages of functions and types that other scripts can `import`.
```pine
//@version=5
library("MyLib", overlay = false)
// exported function — callers reference it as MyLib.double()
export double(float x) =>
x * 2.0
```
- Can use `plot()` and drawing functions in its global scope (typically to demo its exports); cannot place orders — `strategy.*` order functions are unavailable.
- Functions and types marked `export` are visible to importers.
- Import in another script: `import username/MyLib/1 as MyLib`.
### Key differences at a glance
| Feature | indicator | strategy | library |
|---|---|---|---|
| `strategy.*` orders | No | Yes | No |
| `alertcondition()` | Yes | No | No |
| Backtest tab | No | Yes | No |
| `export` keyword | No | No | Yes |
| Can be imported | No | No | Yes |
---
## 3. Type System
### Fundamental types
Pine Script has six fundamental data types:
| Type | Description | Literal examples |
|---|---|---|
| `int` | Integer number | `1`, `-5`, `0` |
| `float` | Floating-point number | `1.5`, `-0.01`, `3.14` |
| `bool` | Boolean | `true`, `false` |
| `string` | Text | `"hello"`, `"BUY"` |
| `color` | RGBA color | `color.red`, `color.new(color.blue, 50)` |
| `label` / `line` / `box` / `table` | Drawing objects | Created via `label.new()`, etc. |
### Type qualifiers (the "form" system)
Every value in Pine Script has both a type (e.g. `float`) and a qualifier that describes when the value is known. From most-restricted to most-flexible:
| Qualifier | When the value is known | Can be used as |
|---|---|---|
| `const` | Compile time — never changes | Anything |
| `input` | Script load time — set by the user via Inputs dialog | `input`, `simple`, `series` |
| `simple` | Bar 0 (first bar) — fixed for the script's lifetime | `simple`, `series` |
| `series` | Every bar — the most general form | `series` only |
**The hierarchy is one-way.** A `const` value can be passed anywhere a less-restrictive qualifier is expected, but a `series` value cannot be passed where `simple` is required.
```pine
//@version=5
indicator("Qualifier demo")
// This works — literal 14 is const int, which satisfies simple int
length = input.int(14, "Length")
ema_val = ta.ema(close, length) // length is input int → accepted as simple int
// This FAILS — bar index changes every bar, so it is series int
// ta.ema(close, bar_index) // ERROR: "simple int" argument required, got "series int"
plot(ema_val)
```
Common functions that require `simple` (not `series`) arguments include `ta.ema()`, `ta.rsi()`, `ta.rma()`, `ta.atr()`, and most `request.*` functions for their `timeframe` parameter. (`ta.sma()` is more permissive — its `length` accepts `series int`.)
### `na`, `nz`, and `fixnan`
`na` is Pine's "not a value" sentinel — similar to `NaN` in other languages. Every series starts as `na` on bars before it has been assigned.
```pine
//@version=5
indicator("na demo")
var float running_sum = na // explicitly uninitialized
if not na(running_sum)
running_sum := running_sum + close
else
running_sum := close
// nz(x, replacement) — returns replacement if x is na, otherwise x
safe_val = nz(running_sum, 0.0)
// fixnan(x) — replaces na with the last non-na value (forward-fills)
filled = fixnan(running_sum)
plot(safe_val)
```
- `na(x)` — returns `true` if `x` is `na`.
- `nz(x)` — returns `0` (or `0.0` or `""`) if `x` is `na`.
- `nz(x, y)` — returns `y` if `x` is `na`.
- `fixnan(x)` — carries the last known value forward, eliminating gaps.
---
## 4. Declarations
### Variable declaration keywords
Pine Script has three ways a variable can persist — controlled by an optional keyword before the type or name:
#### No keyword — recalculated every bar
```pine
//@version=5
indicator("No keyword")
float my_val = close * 1.05 // recomputed from scratch on every bar
plot(my_val)
```
The variable exists only for the current bar's execution. There is no memory of previous assignments.
#### `var` — persist across bars (analogous to PL `Variables:`)
```pine
//@version=5
indicator("var example")
var float highest_close = na // initialized once on bar 0, then persists
if na(highest_close) or close > highest_close
highest_close := close // := is the reassignment operator
plot(highest_close)
```
- Initialized **once** at the first bar (or when `na` on first eval).
- Retains its value across all subsequent bars.
- Use `:=` (not `=`) to reassign after declaration.
- Equivalent to PL's `Variables:` block — the variable remembers its last value.
#### `varip` — persist across ticks (analogous to PL `IntraBarPersist`)
```pine
//@version=5
indicator("varip example")
varip int tick_count = 0 // increments every real-time tick, not just every closed bar
tick_count += 1
plot(tick_count)
```
- Like `var`, but updates survive intra-bar recalculations in real-time.
- On historical bars `varip` behaves identically to `var`.
- Rarely needed — only useful when you need state that survives intra-bar updates on the realtime bar (indicators always recalculate per tick; strategies need `calc_on_every_tick = true` in `strategy()`).
### Input functions
Inputs appear in the Script Settings dialog and let users configure the script without editing code.
```pine
//@version=5
indicator("Input demo")
// Integer input
length = input.int(14, title = "Length", minval = 1, maxval = 500)
// Float input
threshold = input.float(1.5, title = "Threshold", step = 0.1)
// Boolean toggle
show_ma = input.bool(true, title = "Show MA")
// String dropdown
mode = input.string("EMA", title = "Mode", options = ["SMA", "EMA", "WMA"])
// Source — lets the user pick which series to use (close, open, hl2, etc.)
src = input.source(close, title = "Source")
// Symbol — lets the user type a ticker symbol
sym = input.symbol("NASDAQ:AAPL", title = "Symbol")
// Timeframe — lets the user pick a resolution
tf = input.timeframe("D", title = "Timeframe")
// Color picker
line_col = input.color(color.blue, title = "Line Color")
ma = show_ma ? ta.ema(src, length) : na
plot(ma, color = line_col)
```
| Function | Returns | Notes |
|---|---|---|
| `input.int()` | `input int` | Supports `minval`, `maxval`, `step` |
| `input.float()` | `input float` | Supports `minval`, `maxval`, `step` |
| `input.bool()` | `input bool` | Renders as a checkbox |
| `input.string()` | `input string` | Pass `options = [...]` for a dropdown |
| `input.source()` | `series float` | Returns the selected price series |
| `input.symbol()` | `input string` | Symbol string for use with `request.security()` |
| `input.timeframe()` | `input string` | Timeframe string for use with `request.security()` |
| `input.color()` | `input color` | Renders a color picker |
**Important:** `input.source()` returns a `series float`, not `input float`. This means it cannot be passed to functions that require `simple` or `const` arguments — it carries the full per-bar series.
---
## 5. Control Flow
Pine Script uses **indentation** to delimit blocks — there are no `begin`/`end` keywords and no curly braces. Two or four spaces per level are both accepted; just be consistent.
### `if` / `else if` / `else`
```pine
//@version=5
indicator("if/else demo")
rsi = ta.rsi(close, 14)
// Single-line if (no indented block needed when there is exactly one expression)
signal = if rsi > 70
"overbought"
else if rsi < 30
"oversold"
else
"neutral"
// if block that executes side effects (no value assignment)
var int streak = 0
if close > close[1]
streak := streak + 1
else
streak := 0
plot(streak, "Bull streak")
```
An `if` block can be used as an **expression** (it returns the last evaluated value from the taken branch). When all branches return values of the same type, the result can be assigned directly.
### `for ... to` — index-based loop
```pine
//@version=5
indicator("for...to demo")
// Sum the last N bars of close manually
n = 10
var float manual_sum = 0.0
manual_sum := 0.0
for i = 0 to n - 1 // i goes from 0 to n-1 inclusive
manual_sum += close[i]
manual_avg = manual_sum / n
plot(manual_avg, "Manual avg")
```
- Bounds are **inclusive** on both ends — `for i = 0 to 4` iterates i = 0, 1, 2, 3, 4.
- Optional `by` step: `for i = 0 to 20 by 2` increments by 2.
- `break` exits the loop immediately; `continue` skips to the next iteration.
### `for ... in` — array iteration
```pine
//@version=5
indicator("for...in demo")
var float[] vals = array.new_float(0)
array.push(vals, close)
if array.size(vals) > 20
array.shift(vals)
// Iterate over elements — val is each element's value
float total = 0.0
for val in vals
total += val
avg = array.size(vals) > 0 ? total / array.size(vals) : na
plot(avg, "Iterative avg")
```
`for val in myArray` gives a copy of each element. To modify elements in place you still need `array.set()` with an index loop.
### `while` — condition-based loop
```pine
//@version=5
indicator("while demo")
threshold = ta.sma(high, 50)
var int bars_above = 0
bars_above := 0
int i = 0
while i < 50 and i < bar_index
if high[i] > threshold
bars_above += 1
i += 1
plot(bars_above, "Bars above threshold in last 50")
```
**Warning:** Pine enforces a per-bar execution time limit. Loops with a large iteration count or expensive body can trigger a "Script took too long to execute" runtime error.
### `switch` — multi-branch dispatch
```pine
//@version=5
indicator("switch demo")
mode = input.string("RSI", "Indicator", options = ["RSI", "CCI", "MFI"])
// switch expression — each branch uses => and returns a value
osc = switch mode
"RSI" => ta.rsi(close, 14)
"CCI" => ta.cci(close, 20)
"MFI" => ta.mfi(close, 14)
=> ta.rsi(close, 14) // default branch (bare =>)
plot(osc, "Selected oscillator")
```
Each arm uses `value => expression`. The bare `=>` at the end is the default branch (equivalent to `else`). The entire `switch` block is an expression and can be assigned to a variable.
### Ternary operator `? :`
```pine
//@version=5
indicator("Ternary demo", overlay = true)
// condition ? valueIfTrue : valueIfFalse
trend_color = close > ta.sma(close, 50) ? color.green : color.red
// Ternary chains (right-associative — reads top to bottom)
zone = ta.rsi(close, 14) > 70 ? "OB"
: ta.rsi(close, 14) < 30 ? "OS"
: "Neutral"
barcolor(trend_color)
```
The ternary operator is a single expression — it cannot contain statements or side effects. For more complex branching use `if` blocks.
---
## 6. User-Defined Functions & Types
### Function syntax
Functions are declared using `=>`. A single-expression function fits on one line; a multi-statement function uses an indented block.
```pine
//@version=5
indicator("UDF demo")
// Single-line function
percent_change(current, previous) =>
(current - previous) / previous * 100.0
// Multi-line function — last expression is the implicit return value
zscore(src, length) =>
avg = ta.sma(src, length)
dev = ta.stdev(src, length)
safe = math.max(dev, syminfo.mintick) // avoid division by zero
(src - avg) / safe // returned value
pct = percent_change(close, close[1])
z = zscore(close, 20)
plot(pct, "Pct change")
plot(z, "Z-score", display = display.pane)
```
Functions capture their outer scope — they can read variables declared before them, but they cannot modify `var` variables declared outside (each call has its own local state).
### Tuple returns with destructuring
A function (or built-in) can return multiple values wrapped in square brackets. The caller destructures with `[a, b] = f(...)`.
```pine
//@version=5
indicator("Tuple return demo")
// Function returning two values
minmax(src, len) =>
[ta.lowest(src, len), ta.highest(src, len)]
[lo, hi] = minmax(close, 20)
[bb_mid, bb_upper, bb_lower] = ta.bb(close, 20, 2.0) // built-in tuple
range_pct = (hi - lo) / lo * 100
plot(range_pct, "20-bar range %")
```
### User-Defined Types (UDTs)
The `type` keyword declares a named composite type, similar to a struct or record.
```pine
//@version=5
indicator("UDT demo", overlay = true)
// Declare a type — fields can have default values
type Signal
int bar = 0
float price = na
bool is_long = false
color sig_color = color.gray
// Create an instance with type.new() or using field= syntax
var Signal last_sig = Signal.new()
fast = ta.ema(close, 9)
slow = ta.ema(close, 21)
if ta.crossover(fast, slow)
last_sig := Signal.new(
bar = bar_index,
price = close,
is_long = true,
sig_color = color.green)
if ta.crossunder(fast, slow)
last_sig := Signal.new(
bar = bar_index,
price = close,
is_long = false,
sig_color = color.red)
// Access fields with dot notation
if barstate.islast
label.new(last_sig.bar, last_sig.price,
last_sig.is_long ? "Last BUY" : "Last SELL",
color = last_sig.sig_color,
style = label.style_label_up)
```
### Methods on UDTs
The `method` keyword attaches a function to a type. Inside the method, `this` refers to the instance.
```pine
//@version=5
indicator("Method demo", overlay = false)
type PriceBuffer
float[] data // collection fields cannot have defaults — initialize via .new()
int capacity = 20
// method defined on PriceBuffer
method push(PriceBuffer this, float val) =>
array.push(this.data, val)
if array.size(this.data) > this.capacity
array.shift(this.data)
method average(PriceBuffer this) =>
array.size(this.data) > 0 ? array.avg(this.data) : na
var PriceBuffer buf = PriceBuffer.new(data = array.new_float(0))
buf.push(close) // call the method with dot notation
plot(buf.average(), "Buffer avg")
```
### `export` and `import` for library functions
In a `library()` script, mark public functions with `export`. Callers import the library using a version-qualified path.
```pine
// ---- In a library script titled "MathUtils" ----
//@version=5
library("MathUtils", overlay = false)
export zscore(series float src, simple int len) =>
avg = ta.sma(src, len)
dev = ta.stdev(src, len)
(src - avg) / math.max(dev, 1e-10)
export clamp(series float x, simple float lo, simple float hi) =>
math.max(lo, math.min(hi, x))
```
```pine
// ---- In a consuming script ----
//@version=5
indicator("Library consumer")
import username/MathUtils/1 as MU // version number at the end
z = MU.zscore(close, 20)
plot(z, "Z-score from library")
```
The import path follows the format `<TradingView_username>/<LibraryTitle>/<version>`. Libraries must be published (or in an organization) before they can be imported by other users.
---
## 7. Common Gotchas
### Gotcha 1 — Repainting with `request.security()`
**The problem:** On the live, unconfirmed bar, `request.security()` returns the higher-timeframe bar's current in-progress value — not its final closed value. A signal fired on this value may disappear or change direction once that bar closes.
```pine
//@version=5
indicator("Repainting demo")
// REPAINT-PRONE: uses the current unfinished daily bar
daily_rsi_live = request.security(syminfo.tickerid, "D", ta.rsi(close, 14))
plot(daily_rsi_live, "Daily RSI (repaints)", color = color.red)
// REPAINT-SAFE option 1: request the confirmed (previous) bar's value
daily_rsi_safe = request.security(syminfo.tickerid, "D", ta.rsi(close, 14)[1])
plot(daily_rsi_safe, "Daily RSI (no repaint, lagged)", color = color.green)
// REPAINT-SAFE option 2: guard signal execution on the current bar
if barstate.isconfirmed
if daily_rsi_live > 70
label.new(bar_index, high, "OB confirmed", style = label.style_label_down)
```
**Rule of thumb:** If a signal is derived from a higher-timeframe series and must be stable on historical bars, use `close[1]` with `barmerge.lookahead_off` (the default) or gate it with `barstate.isconfirmed`.
---
### Gotcha 2 — `na` propagation
**The problem:** Almost every arithmetic or comparison operation involving `na` returns `na`. Silent `na` propagation can zero out indicators or make conditions permanently false.
```pine
//@version=5
indicator("na propagation demo")
var float acc = na // starts as na
// BUG: acc stays na forever because na + close == na
acc := acc + close // ← wrong if you wanted a running sum
// FIX: use nz() to substitute a safe default before the operation
var float acc2 = 0.0
acc2 := nz(acc2, 0.0) + close // nz returns 0.0 if acc2 is na, else acc2
// fixnan() forward-fills — replaces na with most recent non-na value
filled = fixnan(acc2)
plot(acc2, "Running sum")
plot(filled,"Forward-filled")
```
---
### Gotcha 3 — Series vs. simple context
**The problem:** Many built-in functions require their `length` (or other configuration) argument to be `simple int` — a value fixed at bar 0. Passing a `series int` (one that changes bar by bar) causes a compile error.
```pine
//@version=5
indicator("Series vs simple demo")
// This COMPILES — input.int() produces input int, which satisfies simple int
length = input.int(14, "Length")
rsi_ok = ta.rsi(close, length) // OK
// This FAILS TO COMPILE — bar_index is a series int (changes every bar)
// rsi_bad = ta.rsi(close, bar_index)
// ERROR: "Argument 'length' of type 'series int' used where 'simple int' is expected"
```
**When you encounter this error:** Check whether the argument that changes each bar can be replaced with an `input.*` value. If it truly must vary, you need a manual implementation or a different algorithm.
---
### Gotcha 4 — `max_bars_back` for large historical offsets
**The problem:** Pine pre-allocates a history buffer for each series. By default the buffer holds 300–500 bars. Referencing `close[500]` or more triggers a runtime error: "Index N is too large. Maximum allowed is M."
```pine
//@version=5
// FIX 1: declare max_bars_back in the indicator() call
indicator("max_bars_back demo", max_bars_back = 1000)
// FIX 2: set it for a specific series at runtime
max_bars_back(close, 1000)
lookback = 750
old_close = close[lookback] // works once max_bars_back is raised
```
**When you hit this error:** Add `max_bars_back = <N>` to the `indicator()` / `strategy()` declaration, or call `max_bars_back(series, N)` for specific series. Set `N` to at least the largest offset you reference.
---
### Gotcha 5 — Strategy vs. indicator restrictions
| Feature | `indicator()` | `strategy()` | `library()` |
|---|---|---|---|
| `strategy.entry/exit/close` | No — compile error | Yes | No — compile error |
| `alertcondition()` | Yes | No — compile error | No |
| `alert()` | Yes | Yes | No |
| Backtest Strategy Tester tab | No | Yes | No |
| `export` functions/types | No | No | Yes |
| Can be `import`-ed | No | No | Yes |
| `plot()`, `plotshape()`, etc. | Yes | Yes (overlay only for price plots) | Yes (global scope only) |
**Tip:** If you intend to backtest, start with `strategy()`. If you only need to display data, use `indicator()`. You cannot do both in a single script — split them into two files that share a library if needed.
---
### Gotcha 6 — Execution model: historical vs. realtime
**Historical bars (replay mode):**
- The script executes exactly once per bar, called at the bar's **close**.
- OHLCV values are final — there is no tick-by-tick variation.
- `barstate.ishistory` is true; `barstate.isrealtime` is false.
**Realtime bar (live market):**
- The script re-executes on **every incoming tick** (every price update).
- `open`, `high`, `low`, `close`, `volume` are all live values that change each tick.
- `barstate.isrealtime` is true; `barstate.isconfirmed` is false until the bar closes.
**Contrast with PowerLanguage:** In MultiCharts, `CalcAtMarketClose` and `CalcOnTick` are explicit per-indicator settings. In Pine, the behavior is always: once per historical bar at close, every tick on the live bar. To suppress intra-bar noise, gate your logic with `if barstate.isconfirmed`.
### Gotcha 7 — History-referencing functions must be called at global scope
Functions that track state across bars — `ta.crossover()`, `ta.crossunder()`, `ta.change()`, `ta.pivothigh()`, `ta.pivotlow()`, `ta.barssince()`, `ta.valuewhen()` — must be called on **every bar** to maintain correct internal state. Calling them inside a conditional block produces incorrect results and a compiler warning.
```pine
// BAD — called inside a conditional scope
if strategy.position_size > 0
if ta.crossunder(macdLine, signalLine) // only runs when in a position
strategy.close("LE")
// GOOD — call at global scope, use the result inside the condition
macdCrossDown = ta.crossunder(macdLine, signalLine) // runs every bar
if strategy.position_size > 0 and macdCrossDown
strategy.close("LE")
```
This applies to any `ta.*` function that uses historical comparison. Extract the call to a variable at the top level, then reference the variable inside your conditions.
Versions
The database has no other skills named pinescript-core.
Database snapshot: 13.11.2026 · package version d9180520bbef (SHA-256 digest of the entire package)
Downloads in the last 30 days: 0 · ranking
Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.
Similar skills
- 100pinescript-v6
Write and debug TradingView Pine Script v6 correctly. Covers the execution model, the v6 type system, overloaded drawing constructors, anti-repainting with request.security, and the API TradingView shipped through 2026. Validate every script before claiming it works. Use when… - 100pinescript
Pine Script v6 patterns: syntax rules, performance, debugging, backtesting, visualization. Use when asked to "write a Pine Script", "create an indicator", "build a strategy", "fix Pine code", or mentions PineScript, TradingView, indicator, strategy, or backtest. - 100pinescript-validation
Diagnose and fix Pine Script v6 errors deterministically — read each validator diagnostic, apply the known fix, re-validate. Covers every diagnostic class the validator emits, what it cannot see, and how to work through an existing codebase of broken .pine files. Use when a Pine… - 100pinescript-visual
Use when adding visual output to Pine Script — plot()/plotshape()/bgcolor()/fill()/hline(), label.*, line.*, box.*, table.*, map.*, matrix.*, log.*, alerts, and drawing object limits. - 100pinescript
Pine Script v6: syntax, performance, error diagnosis, backtesting, visualization. Use when writing or debugging `.pine` files or TradingView Pine indicators/strategies. - 100pinescript-builtins
Use when writing Pine Script logic with built-in namespaces — ta.* (averages, oscillators, crossovers), strategy.* (orders, position info), request.* (multi-timeframe), math.*, str.*, array.*, color.*, bar state, symbol info.