pine-developer
Skill3 starsChanged 32 days agoMITView on GitHub
Specialized in writing production-quality Pine Script v6 code for TradingView. These updates are essential for writing correct, modern Pine Script code: PREFERRED: Use for...in loops for collections: If you must use traditional for loop: Note: for...in allows modifying array/matrix sizes during iteration. Maps cannot be resized during for...in - use map.keys() array instead.
2 other projects use a version of this, 2 of them edited.
Adopted by
Most recently taken up by
- udaydeep1992/pinescript-agents-antigravityedited, first seen Oct 2, 2026
- TradersPost/pinescript-agentsedited, first seen Jul 9, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- TradersPost/pinescript-agents★ 15696% same
- udaydeep1992/pinescript-agents-antigravity★ 012% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository33 other files it gives its agents.
- llms.txtllms.txt
- alpha-zooSkill
- breadth-chart-analystSkill
- canslim-screenerSkill
- factor-mining-pandaaiSkill
- backtesting-bias-avoidanceSkill
- backtest-reviewSkill
- data-quality-auditSkill
- paper-reproSkill
- pine-backtesterSkill
- stats-test-pickerSkill
- vectorbt-backtestSkill
- vectorbt-optimizeSkill
- akquantSkill
- ashare-pre-st-filterSkill
- cninfo-disclosureSkill
- ctp-apiSkill
- ptrade-strategy-writingSkill
- quant-buddySkill
- ssquant-futuresSkill
- tdxquantSkill
- tqsdk-tradingSkill
- wencai-screenerSkill
- defillama-dataSkill
- defillama-flowsSkill
- defillama-yieldsSkill
- perp-funding-basisSkill
- pine-debuggerSkill
- edgar-financialsSkill
- llmquant-equitiesSkill
- llmquant-macroSkill
- llmquant-riskSkill
- openquant-tradingSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 4 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 86
All input functions now support conditional activation:
- Very specific: line 233
Methods: Add behavior directly to types with method syntax
- Very specific: line 234
Unlimited Lookback: Use xloc.bar_time instead of xloc.bar_index (5000 bar limit!)
- Distinctive: line 418
Update file header with accurate project information
- Distinctive: line 419
Never create unnecessary files
- Distinctive: line 571
Write code that is production-ready, efficient, and uses UDT-first architecture with the latest Pine Script v6 features.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!--
Imported from: https://github.com/TradersPost/pinescript-agents
Source Path: skills/pine-developer/SKILL.md
Curated for awesome-quant-skills
-->name: pine-developer description: Writes production-quality Pine Script v6 code following TradingView guidelines. Use when implementing indicators, strategies, or any Pine Script code. allowed-tools: Read, Write, Edit, Glob, Grep, Bash
Pine Script Developer
Specialized in writing production-quality Pine Script v6 code for TradingView.
⚠️ CRITICAL: Pine Script v6 2025 Updates
These updates are essential for writing correct, modern Pine Script code:
December 2025: Updated Line Wrapping Rules
Expressions in parentheses now support flexible indentation:
// ✅ NOW VALID - Any indentation inside parentheses
plot(series,
title="My Plot", // Can use any indentation
color=color.blue)
// ✅ Also valid
longCondition = (ta.crossover(ema50, ema200) and
rsi < 30 and
volume > ta.sma(volume, 20))
// ⚠️ STILL REQUIRED outside parentheses - non-multiple-of-4 indentation
longCondition = ta.crossover(ema50, ema200) and
rsi < 30 // Must NOT be multiple of 4 spacesMarch 2025: BREAKING CHANGE - For Loop Dynamic Boundaries
for loops now evaluate to_num before every iteration, not just once.
PREFERRED: Use for...in loops for collections:
// ✅ BEST: Use for...in for arrays (safe, clean, preferred)
for element in myArray
// Process element directly
// ✅ BEST: Use for...in with index when needed
for [index, element] in myArray
// Have both index and value
// ✅ for...in works with arrays, matrices, and maps
for [key, value] in myMap
// Iterate key-value pairsIf you must use traditional for loop:
// ⚠️ BREAKING: This creates infinite loop!
var arr = array.new<int>()
for i = 0 to array.size(arr) // Re-evaluated each iteration
array.push(arr, i) // Array grows, loop never ends!
// ✅ FALLBACK: Cache the boundary if using traditional for
size = array.size(arr)
for i = 0 to size
array.push(arr, i)Note: for...in allows modifying array/matrix sizes during iteration. Maps cannot be resized during for...in - use map.keys() array instead.
February 2025: Scope Limit Removed
- Previously limited to 550 total scopes
- Now unlimited scopes across functions, methods, loops, conditionals, types, and enums
February 2025: Bid/Ask Variables
// Only available on 1T (tick) timeframe
bidPrice = bid // Highest buyer price (na on other timeframes)
askPrice = ask // Lowest seller price (na on other timeframes)Pine Script v6 2025 New Features
July 2025: Input active Parameter
All input functions now support conditional activation:
useCustomMA = input.bool(false, "Use Custom MA")
customMALength = input.int(20, "Custom MA Length",
active=useCustomMA, // Grayed out when useCustomMA is false
tooltip="Only available when 'Use Custom MA' is enabled")July 2025: syminfo.current_contract
// For continuous futures - returns underlying contract ticker
currentContract = syminfo.current_contract // Returns na for non-continuousNovember 2025: syminfo.isin
// International Securities Identification Number (12 chars)
isinCode = syminfo.isin // Empty string if unavailableSeptember 2025: Plot Line Styles
plot(series, linestyle=plot.linestyle_solid) // Default
plot(series, linestyle=plot.linestyle_dashed) // Dashed line
plot(series, linestyle=plot.linestyle_dotted) // Dotted lineOctober 2025: Enhanced time() and time_close()
New timeframe_bars_back parameter:
// Get time from 5 bars back on the DAILY timeframe (not current chart)
dailyTimeBack = time("D", timeframe_bars_back=5)
// Positive = past bars, Negative = future (expected) timestamps
futureTime = time("D", timeframe_bars_back=-1) // Expected next barAugust 2025: Increased String Length
- Maximum string length: 40,960 characters (was 4,096)
June 2025: Library Constant Exports
// In library:
//@version=6
library("MyLib")
export const float PI = 3.14159265359
export const int MAX_BARS = 500
export const string VERSION = "1.0.0"May 2025: time_close on Non-Time-Based Charts
For Renko, Line Break, Kagi, Point & Figure, Range charts:
time_closeof open realtime bar now returnsnatime_close[1]now works immediately after bar closes
April 2025: Percentage-Based Ticker Styles
// New "PercentageLTP" style for percentage box sizing
renkoTicker = ticker.renko(syminfo.tickerid, "PercentageLTP", 1.0)
kagiTicker = ticker.kagi(syminfo.tickerid, "PercentageLTP", 0.5)
pnfTicker = ticker.pointfigure(syminfo.tickerid, "PercentageLTP", 1.0)March 2025: box.set_xloc()
// Modify box x-coordinates after creation
box.set_xloc(myBox, left, right, xloc.bar_index)
box.set_xloc(myBox, leftTime, rightTime, xloc.bar_time)CRITICAL: Line Wrapping Rules (Updated December 2025)
Inside Parentheses (FLEXIBLE)
// ✅ Any indentation works inside ()
plot(series,
title="Plot",
color=color.blue, // Different indentation OK
linewidth=2)
indicator("Title",
overlay=true,
max_bars_back=500)Outside Parentheses (STRICT)
// ✅ CORRECT - Non-multiple-of-4 indentation
longCondition = ta.crossover(ema50, ema200) and
rsi < 30 and
volume > ta.sma(volume, 20)
// ❌ WRONG - Multiple of 4 (or same level)
longCondition = ta.crossover(ema50, ema200) and
rsi < 30 // Error: 4 spaces
longCondition = ta.crossover(ema50, ema200) and
rsi < 30 // Error: same indentationCRITICAL: Ternary Operators - Keep on ONE Line
// ❌ NEVER split ternary across lines
text = condition ?
"value1" :
"value2" // ERROR!
// ✅ ALWAYS keep on one line
text = condition ? "value1" : "value2"
// ✅ For long ternaries, use intermediate variables
trueText = str.format("Long value {0}", param1)
falseText = str.format("Other value {0}", param2)
result = condition ? trueText : falseTextCRITICAL: Plot Scope Restriction
NEVER use plot() inside local scopes:
// ❌ WRONG - All of these fail:
if condition
plot(value) // ERROR: Cannot use 'plot' in local scope
for i = 0 to 10
plot(close[i]) // ERROR!
myFunc() =>
plot(close) // ERROR!
// ✅ CORRECT patterns:
plot(condition ? value : na) // Conditional plotting
plot(value, color=condition ? color.blue : na) // Conditional color
// For dynamic drawing in local scopes, use:
if condition
line.new(...) // OK
label.new(...) // OK
box.new(...) // OK⚠️ CRITICAL: UDT-First Architecture
For any complex data structure, ALWAYS define User Defined Types (UDTs) FIRST before writing any other code.
Why UDT-First?
- Encapsulation: Bundle related data and drawing objects together
- Methods: Add behavior directly to types with
methodsyntax - Unlimited Lookback: Use
xloc.bar_timeinstead ofxloc.bar_index(5000 bar limit!) - Clean Arrays: One
array<MyType>instead of 6+ parallel arrays - Self-Managing Drawings: Types can create/delete their own visual objects
UDT Definition Pattern
// ALWAYS define UDTs early in script (after inputs, before calculations)
type Regression
// Time coordinates (for xloc.bar_time - NO lookback limit!)
int startTime
int endTime
// Bar indices (for Y calculations: y = slope * barIndex + intercept)
int startBarIndex
int endBarIndex
// Data parameters
float slope
float intercept
float stdDev
float pearsonR
// State flags
bool isLive = false
bool isOriginal = false
// Drawing objects (managed internally)
line centerLine = na
line upperLine = na
line lowerLine = na
linefill fill = naUDT Methods Pattern
// Delete method - clean up drawing objects
method delete(Regression this) =>
if not na(this.centerLine)
line.delete(this.centerLine)
if not na(this.upperLine)
line.delete(this.upperLine)
if not na(this.lowerLine)
line.delete(this.lowerLine)
if not na(this.fill)
linefill.delete(this.fill)
this.centerLine := na
this.upperLine := na
this.lowerLine := na
this.fill := na
// Calculation method
method calculateY(Regression this, int barIdx) =>
this.slope * barIdx + this.intercept
// Draw method - use xloc.bar_time for unlimited lookback!
method draw(Regression this, color baseColor, int width) =>
this.delete() // Clean up old drawings first
startY = this.calculateY(this.startBarIndex)
endY = this.calculateY(this.endBarIndex)
// ✅ CRITICAL: Use xloc.bar_time - NO 5000 bar limit!
this.centerLine := line.new(
this.startTime, startY,
this.endTime, endY,
xloc=xloc.bar_time, // ← UNLIMITED LOOKBACK
color=baseColor,
width=width)⚠️ CRITICAL: xloc.bar_time vs xloc.bar_index
ALWAYS use xloc.bar_time for drawing objects that may need historical display:
// ❌ WRONG - Limited to 5000 bars back
line.new(bar_index - 100, y1, bar_index, y2, xloc=xloc.bar_index)
// ✅ CORRECT - Unlimited historical lookback
line.new(time[100], y1, time, y2, xloc=xloc.bar_time)
// Store TIME when events occur, not just bar_index
var int eventTime = na
var int eventBarIndex = na
if eventOccurred
eventTime := time // For drawing
eventBarIndex := bar_index // For Y calculationUDT Storage Pattern
// Single array of UDTs instead of parallel arrays
var array<Regression> regressions = array.new<Regression>()
var Regression liveRegression = na
var Regression originalRegression = na
// ❌ WRONG - Parallel arrays (hard to maintain)
var array<float> slopes = array.new<float>()
var array<float> intercepts = array.new<float>()
var array<int> startBars = array.new<int>()
var array<int> endBars = array.new<int>()
// ... 6+ arrays to keep in sync!
// ✅ CORRECT - Single UDT array
var array<Regression> regressions = array.new<Regression>()Creating and Storing UDTs
// Create new instance with all data
newRegression = Regression.new(
startTime = capturedStartTime,
endTime = capturedEndTime,
startBarIndex = capturedStartBar,
endBarIndex = capturedEndBar,
slope = calculatedSlope,
intercept = calculatedIntercept,
stdDev = calculatedStdDev,
pearsonR = calculatedR
)
// Add to collection
array.push(regressions, newRegression)Iterating UDT Arrays with for...in
// ✅ BEST: Use for...in for UDT arrays
for reg in regressions
baseColor = reg.slope >= 0 ? uptrendColor : downtrendColor
reg.draw(baseColor, lineWidth)
// ✅ With index when needed
for [i, reg] in regressions
if i == array.size(regressions) - 1
// Special handling for last itemTime Capture Pattern
// Capture BOTH time and bar_index when events occur
var int startTime = na
var int startBarIndex = na
var int endTime = na
var int endBarIndex = na
if eventStart
startTime := time // For xloc.bar_time drawing
startBarIndex := bar_index // For Y calculations
if eventEnd
endTime := time
endBarIndex := bar_index
// Create UDT with both coordinate systems
newItem = MyType.new(
startTime = startTime,
endTime = endTime,
startBarIndex = startBarIndex,
endBarIndex = endBarIndex
)UDT Architecture Checklist
- Define UDT type BEFORE any calculations
- Store
timevalues for drawing coordinates - Store
bar_indexvalues for Y calculations - Include drawing objects (
line,box,label) as UDT fields - Add
delete()method to clean up drawings - Add
draw()method usingxloc.bar_time - Use single
array<MyType>instead of parallel arrays - Use
for...into iterate UDT arrays
Documentation Access
Primary documentation references:
/docs/pinescript-v6/quick-reference/syntax-basics.md- Core syntax/docs/pinescript-v6/reference-tables/function-index.md- Function reference/docs/pinescript-v6/core-concepts/execution-model.md- Execution model/docs/pinescript-v6/core-concepts/repainting.md- Repainting issues/docs/pinescript-v6/quick-reference/limitations.md- Platform limits
Project File Management
- Save work to
/projects/[project-name].pine - Update file header with accurate project information
- Never create unnecessary files
Script Structure Templates
Indicator Template
// built with PineScript Agents by TradersPost
//@version=6
indicator(title="", shorttitle="", overlay=true)Strategy Template (IMPORTANT: Include alert annotation)
// built with PineScript Agents by TradersPost
//@version=6
strategy(title="", shorttitle="", overlay=true)
//@strategy_alert_message {{strategy.order.alert_message}}
// ============================================================================
// INPUTS
// ============================================================================
// Group 1: Main Settings
setting1 = input.int(14, "Setting", group="Main Settings",
tooltip="Description of what this does")
// Group 2: Visual Settings
showPlots = input.bool(true, "Show Plots", group="Visual Settings")
plotColor = input.color(color.blue, "Plot Color", group="Visual Settings",
active=showPlots) // Grayed out when showPlots is false
// ============================================================================
// CALCULATIONS
// ============================================================================
// Cache boundaries for loops (March 2025 breaking change)
arraySize = array.size(myArray)
for i = 0 to arraySize - 1
// Process...
// ============================================================================
// CONDITIONS
// ============================================================================
// ============================================================================
// PLOTS
// ============================================================================
// Use new linestyle parameter (September 2025)
plot(ma, "MA", color.blue, linewidth=2, linestyle=plot.linestyle_solid)
// ============================================================================
// ALERTS
// ============================================================================TradingView Constraints (2025 Updated)
Limits
- Maximum 500 bars historical reference
- Maximum 500 plot/hline/fill outputs
- Maximum 64 drawing objects (label/line/box/table)
- Maximum 40 security() calls
- Maximum 100KB compiled script size
- Tables: max 100 cells
- Arrays: max 100,000 elements
- Strings: max 40,960 characters (increased August 2025)
- Scopes: Unlimited (removed February 2025)
Platform Quirks
- bar_index starts at 0
- na propagation in calculations
- Historical vs real-time calculation differences
- Strategy calculations on bar close (unless calc_on_every_tick)
bid/askonly available on 1T timeframe
Best Practices
Avoid Repainting
// Use barstate.isconfirmed for signals
if barstate.isconfirmed and buyCondition
strategy.entry("Long", strategy.long)
// Proper request.security() usage
htfClose = request.security(syminfo.tickerid, "D", close,
lookahead=barmerge.lookahead_off)Performance Optimization
// Cache repeated calculations
sma20 = ta.sma(close, 20)
sma50 = ta.sma(close, 50)
crossUp = ta.crossover(sma20, sma50)
// Combine security() calls
[htfClose, htfHigh, htfLow] = request.security(syminfo.tickerid, "D",
[close, high, low])User Experience (Use 2025 Features)
// Input groups with active parameter
advancedMode = input.bool(false, "Advanced Mode", group="Settings")
advSetting = input.int(10, "Advanced Setting",
group="Settings",
active=advancedMode, // July 2025 feature
tooltip="Only visible in advanced mode")Error Handling
// Check for na values
safeValue = na(value) ? 0 : value
// Handle division by zero
safeDiv = denominator != 0 ? numerator / denominator : 0
// Cache loop boundaries (March 2025 breaking change)
arrSize = array.size(arr)
for i = 0 to arrSize - 1
// ...Code Review Checklist
Architecture (Check First!)
- Complex data uses UDT-first pattern
- Drawing objects use
xloc.bar_time(not bar_index) - Time values captured for historical drawing
- Single UDT array instead of parallel arrays
Script Basics
//@version=6declaration//@strategy_alert_message {{strategy.order.alert_message}}for strategies (placed after thestrategy()call)- Proper title and overlay setting
Inputs & UX
- Inputs have tooltips and groups
- Inputs use
activeparameter where appropriate - Using new plot linestyles where appropriate
- Proper plot styling
Code Quality
- No repainting issues
- na values handled
- Loop boundaries cached (March 2025 fix)
- Efficient calculations
- Clear variable names
- Alert conditions if needed
Write code that is production-ready, efficient, and uses UDT-first architecture with the latest Pine Script v6 features.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

