语法指南

在 TradingGoose 中编写指标的 PineTS 语法规则

PineTS 使用 JavaScript/TypeScript 语法,与 Pine Script 的运行时行为保持一致。如果你用过 TradingView 的 Pine Script,迁移会很顺畅——主要区别在于变量声明和标准 JS 语法约定。

变量声明

PineTS 区分 let 和 var,以匹配 Pine Script 的执行模型。这是最需要理解的核心概念。

let — 每根 K 线重新计算

使用 let 声明的变量(以及使用 const 声明的不可变值)会在每根 K 线上重新求值,与标准 Pine Script 变量完全一致:

// Recalculated on every bar
const sma20 = ta.sma(close, 20);
let direction = close > open ? 1 : -1;

var — 跨 K 线持久状态

使用 var 声明的变量仅在第一次(第一根 K 线)初始化,并在后续 K 线中保留其值——与 Pine Script 的 var 关键字一致:

// Initialized once, persists across bars
var cumulativeVolume = 0;
cumulativeVolume = cumulativeVolume + volume;

在 PineTS 中,var 不等同于标准 JavaScript 的 var。它采用 Pine Script 的语义:变量只设置一次并持续保留。如果你需要一个每根 K 线都重置的值,请使用 let。

并排对比

行为Pine ScriptPineTS
每根 K 线重新计算float x = closelet x = close 或 const x = close
跨 K 线持久保留var float x = 0.0var x = 0.0
重新赋值x := x + 1x = x + 1

历史数据访问

使用中括号表示法访问前一根 K 线的值,与 Pine Script 完全一致:

const prevClose = close[1];     // 1 bar ago
const tenBarsAgo = close[10];   // 10 bars ago
const momentum = close - close[10];

循环

标准 JavaScript 循环语法:

// Pine Script: for i = 0 to 9
let sum = 0;
for (let i = 0; i < 10; i++) {
  sum += close[i];
}
let i = 0;
let sum = 0;
while (i < 10) {
  sum += close[i];
  i++;
}

控制流

// If/else
if (close > open) {
  direction = 1;
} else {
  direction = -1;
}

// Ternary
const color = close > open ? '#00FF00' : '#FF0000';

// Switch
switch (maType) {
  case 'ema': return ta.ema(close, length);
  case 'sma': return ta.sma(close, length);
  default: return ta.rma(close, length);
}

函数

使用标准 JavaScript 语法定义可复用函数:

// Pine Script: f_ma(source, length) => ta.sma(source, length)
function f_ma(source, length) {
  return ta.sma(source, length);
}

const ma = f_ma(close, 20);
plot(ma, 'Custom MA');

元组(多个返回值)

有些函数(如 ta.macd() 和 ta.bb())会返回多个值。使用数组解构:

// Pine Script: [macdLine, signalLine, hist] = ta.macd(close, 12, 26, 9)
const [macdLine, signalLine, hist] = ta.macd(close, 12, 26, 9);

// Pine Script: [middle, upper, lower] = ta.bb(close, 20, 2)
const [middle, upper, lower] = ta.bb(close, 20, 2);

特殊值

值描述
na不可用 —— 等同于 Pine Script 中的 null/undefined
nz(value)将 na 替换为零(或指定的默认值)
color图表颜色命名空间
const prev = close[1];
const change = na(prev) ? 0 : close - prev;  // Handle na values
const safeValue = nz(someCalculation, 0);     // Default to 0 if na

完整示例:抛物线 SAR

此示例演示了 var 用于持久状态、if/else 逻辑、历史数据访问以及自定义函数:

indicator('Custom SAR', { overlay: true });

const start = input.float(0.02, 'Start');
const increment = input.float(0.02, 'Increment');
const maximum = input.float(0.2, 'Maximum');

function pine_sar(start, inc, max) {
  var result = na;
  var maxMin = na;
  var acceleration = na;
  var isBelow = false;

  let isFirstTrendBar = false;

  if (bar_index == 1) {
    if (close > close[1]) {
      isBelow = true;
      maxMin = high;
      result = low[1];
    } else {
      isBelow = false;
      maxMin = low;
      result = high[1];
    }
    isFirstTrendBar = true;
    acceleration = start;
  }

  // ... calculation logic ...
  return result;
}

const sar = pine_sar(start, increment, maximum);
plot(sar, 'SAR', { style: plot.style_cross });