关于 pinescript
面向 TradingView 指标和策略开发者的 Pine Script 技能,强调先核对最新文档,并关注语法、平台限制及信号和回测验证。
主要功能
- 01按版本核对文档
- 02语法与平台限制指导
- 03性能和调试实践
- 04策略验证与发布指导
适用场景
- 01编写 Pine Script 指标
- 02构建并测试交易策略
- 03调试信号与重绘行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ iliaal/ ai-skills --skill pinescript安装后在 Claude Code 中输入/pinescript确认已加载。
附带文件references/evidence/findings-log.mdSPEC.md
详细介绍
Pine Script 开发
实现前先验证:对于 Pine Script 特定版本的语法或新增内置函数,请先查阅当前官方文档,再编写代码。有条件时优先使用 Context7(query-docs)。否则,请使用可用的网页工具阅读适用于脚本版本的 TradingView Pine Script 文档。TradingView 会频繁更新 Pine Script,训练数据可能已经过时。
关键语法规则
- 保持简单的三元表达式易于阅读;多行表达式必须使用有效的续行缩进。对于复杂的三元表达式,请使用中间变量:
isBull = close > open barColor = isBull ? color.green : color.red - 括号外的续行必须缩进非 4 的倍数个空格:与起始行缩进相同会报错,缩进 4、8、12 个空格也会被解析为局部代码块并报错(通常使用 2 个空格)。括号内(函数调用、带括号的表达式)可使用任意缩进,包括 4 的倍数
- 绝不能在局部作用域(if/for/函数)中使用 plot();请改用条件值:
plot(condition ? value : na) - 当信号需要使用图表柱的收盘值时,请使用
barstate.isconfirmed。它不能保证请求的更高时间框架数值已确认;请单独检查request.security()的偏移和 lookahead。
平台限制
为脚本确定规模前,请查看当前平台限制:64 个 plot 计数(一次调用可能占用多个);line、box 或 label ID 各最多 500 个,polyline ID 最多 100 个;40 次唯一的 request.*() 调用,Ultimate 上为 64 次;100,000 个编译后的令牌。历史缓冲区、请求的盘中数据和图表历史各有限制;request.security() 没有通用的 500 根柱历史限制。
- 使用
xloc.bar_index定位的绘图最多只能向过去延伸 9,999 根柱,向未来延伸 500 根柱;对于更早的数据,请将绘图切换为xloc.bar_time并传入时间戳(未使用xloc.bar_time的时间值会被视为未来柱索引并报错) - 设置相应的
max_*_count声明参数,并使用滚动缓冲区限制增长:推入每个对象,然后在超出预期线条数量时执行line.delete(arr.shift())。每种绘图类型的默认显示数量约为 50 个。
性能
- 元组 security 调用:使用一次返回
[close, high, low]的request.security(),而不是分 3 次调用 - 使用
array.new<type>(size)预分配数组,而不是边推入边调整大小 - 在全局作用域中每根柱上计算依赖历史数据的函数,例如
ta.rsi()。使用已存储的结果对信号谓词进行短路求值;请参阅 Pine v6 惰性求值。 - 将重复计算缓存到变量中;Pine 会在每根柱上重新计算
- 使用
for item in myArray(或for [i, item] in myArray)遍历集合,而不是使用for i = 0 to array.size(...) - 1;这两种形式都会在后续迭代中使用更新后的集合大小。 - 对于
for...in,调整数组或矩阵大小时,请考虑迭代边界的变化。添加或移除 map 条目时,请在修改原始 map 的同时遍历map.keys()快照或map.copy()。避免直接用循环结果初始化var/varip:循环会在第一次迭代后停止。请先声明变量,再用:=赋值,或从函数返回循环结果。请参阅 Pine v6 循环规则。 - 将相关值建模为用户定义类型,而不是使用多个平行数组:定义带有
float entry、int startBar和method函数的type Trade,并将其存储在一个array<Trade>中。平行数组(entries、startBars等)只要有一次 push/remove 遗漏就会失去同步,而且每项操作都必须在每个数组中重复执行;一个类型化数组可将每个对象的字段放在一起
调试
通过 log.info()、log.warning() 和 log.error() 使用 Pine Logs,并进行以下可视化检查:
- 标签调试:使用
label.new(bar_index, high, str.tostring(myVar))检查数值;明确限制保留的标签数量。 - 表格监视器:使用
table.new()和barstate.islast创建实时变量仪表板 - 调试模式开关:使用
if input.bool(false, "Debug")编写本地调试代码;绘图调用保持在全局作用域。 - 重绘检查:记录带时间戳的实时信号,然后在重新加载后对比相同的柱。
value[1]指的是前一根柱,无法检测更早计算结果的修订。
策略与回测
- 使用
strategy.*函数:strategy.wintrades、strategy.losstrades、strategy.grossprofit - 在更新持久化回撤状态之前先声明它:
var float maxEquity = strategy.equity maxEquity := math.max(maxEquity, strategy.equity) dd = maxEquity > 0 ? (maxEquity - strategy.equity) / maxEquity * 100 : na - 根据超额收益的均值除以其标准差,并乘以每年周期数的平方根,估算年化 Sharpe;说明采样间隔和年化假设,并处理方差为零的情况。
- 滚动前向验证:在第 1 个时期优化,在第 2 个时期测试;在第 2 个时期重新优化,在第 3 个时期测试。将性能退化与抽样不确定性、成本和市场状态变化进行比较;没有任何通用百分比可以判定过拟合。
- 指标准确性测试:在柱
t,将prediction[horizon]与此时已实现的结果进行评分,例如close > close[horizon],并排除预热柱。正偏移引用过去,绝不引用未来柱;参见历史引用。 - 统计每个切片的评估次数:调优期间被评分 N 次的切片就是调优数据,无论它被如何标记;因此,在每个切片上运行多参数扫描,会让“验证”数据变成选择偏差。至少保留一个切片,并明确规定查看次数预算;等参数锁定后再使用该切片。如果想“再看一次”,就该停止。
- 每个切片的最优参数互相冲突,表明策略不稳定:在添加市场状态分类器之前,先将稳健的固定参数与更简单的策略进行比较。使用入场前可获取的信息拟合任何分类器,并在未触及的数据上验证;仅凭最优参数冲突,并不能证明所有固定参数都无效。
- 启用市场状态门控后,重新运行每次参数扫描:门控前的扫描结果无法直接沿用,因为被排除的亏损时段会掩盖参数的实际效果。针对一种策略失效模式校准的过滤器,不能直接套用到基于相同信号的其他策略。
可视化
- 使用
color.from_gradient()为趋势强度着色 - 自适应文本大小:日内使用
size.small,日线及更长周期使用size.normal - 动态表格行数:通过输入开关,根据已启用的功能调整大小
- 当控制开关关闭时,
input.*(..., active = condition)会将输入项显示为灰色(例如,只有勾选“Use smoothing”后,才能编辑平滑长度),这比用工具提示说明“除非……否则忽略”更清晰 - 专业配色常量:定义一次 BULL_COLOR、BEAR_COLOR、NEUTRAL_COLOR,并设置透明度
发布
- 文档应作为注释放在 .pine 文件顶部,位于
indicator()/strategy()之前 - 使用
@version、@description、@param标签 - 多行工具提示:
tooltip="Line 1" + "\n" + "Line 2" - 发布前,请查阅当前 TradingView 发布规则,确认脚本的可见性和类别;不要根据固定清单推断平台政策。
常见编码错误
- 指标堆叠(RSI + Stochastics + CCI):它们测量的都是同一项内容(动量)。应改用不同类别的指标。
- 在未触碰过的数据上评估参数稳定性;数值看起来特别具体,并不能证明存在过拟合,而使用整数也无法避免过拟合。
- 说明信号是有意在柱线内更新,还是需要等待柱线确认;测试这一行为,包括请求的时间范围。
- 将阈值硬编码而不使用
input(),会让脚本无法在不同交易品种上进行测试。
工作流
- 在 Pine Editor 中编写指标/策略
- 使用多个时间范围,通过柱线回放和策略测试器进行测试
- 在信任回测结果之前进行滚动前向验证(参见上文的策略与回测)
- 验证:在 3 个以上的交易品种和 2 个以上的时间范围上运行
验证
- 指标在 TradingView 上编译无错误
- 通过比较实时柱线与重新加载后的柱线,验证信号稳定性,并检查更高时间范围的请求;仅仅存在保护机制并不能证明其有效。
- 在不同时间范围内,对 3 个以上的交易品种进行滚动前向测试
评论
支持 Markdown