保持敬畏之心
交易是一场持久战

Pine Script(266):未声明标识符与变量重复声明错误

#Pine Script入门教学

什么原因导致TradingView出现”未声明的标识符”错误消息?

几乎所有的TradingView脚本都会使用自定义的、由用户定义的变量,其中有相当一部分甚至会使用自定义函数。这些变量和函数有助于避免代码重复,并使代码更易于管理。但如果它们触发了’undeclared identifier’(未声明的标识符)错误,那情况就另当别论了。本文将探讨如何修复这类错误!

探究TradingView的未声明的标识符错误

TradingView Pine语言内置了大量变量和函数,能为我们的指标和策略脚本提供各种信息和功能。但我们也可以创建自己的变量和函数,从而避免一遍又一遍地执行相同的计算。

虽然自定义变量和函数通常能让我们的编程工作更轻松,但有时它们也会带来一些小麻烦,例如当我们遇到’undeclared identifier’错误时。当这个错误发生且我们的脚本已经添加到图表上时,我们会看到’cannot compile script’(无法编译脚本)的提示:

这个提示信息过于笼统,帮助不大。但幸运的是,在Pine编辑器的控制台窗口中,还有一条信息更丰富的错误提示。

在那里,会显示类似以下内容:

Processing script...
line 5: Undeclared identifier `emavalue`;
line 7: Undeclared identifier `plotColour`
Script 'Error example' has been saved

这就提供了更多可供操作的信息。接下来,让我们看看如何利用这条错误信息来修复代码问题。

修复TradingView的未声明的标识符错误

虽然’undeclared identifier’错误信息可能有点烦人,但其原因通常只是我们代码中的一个小错误。这使得修复这个错误相当直接。第一步,仔细阅读错误信息的第一行,记下行号以及提示不正确的变量或函数名。第二步,在Pine编辑器中跳转到该行,并找到错误所提及的变量或函数。第三步,查看错误行上方的代码,找到你最初是如何命名该变量或函数的,使用那个确切的名称来修正错误。第四步,保存脚本,如果还有其他的’undeclared identifier’错误,重复以上步骤。

请注意:标识符(Identifier)是我们为自定义变量或函数所起的名字。标识符就是当我们创建变量或函数时,出现在==>左侧的那个名字。这个名字可以由大小写字母、下划线(_)和数字组成(但标识符不能以数字开头)。

另外,’undeclared identifier’错误可能会引发一连串的连锁错误。但不要被控制台中满屏的红色吓倒。这仅仅是因为当我们在一个标识符上犯错时,TradingView也会为后续使用到它的代码触发错误。所以,可能屏幕上显示了10个错误,而实际上我们只犯了一个错误。因此,不必担心看到多个错误,只需修复第一个错误,然后保存脚本,看看其他的错误是否随之消失。

现在,让我们来看看几种会触发’undeclared identifier’错误的情境。

错误示例1:变量名拼写错误

最可能导致’undeclared identifier’错误的情境,就是我们在使用变量名时出现了拼写错误。这一点也有些恼人,因为我们明明知道变量名应该是什么,只是不小心打错了。

一个犯了此错误的指标示例如下:

//@version=5
indicator(title="错误示例", overlay=true)

emaValue   = ta.ema(close, 25)
plotColour = close > emaVlue ? color.green : color.red // 此处有拼写错误

plot(emaValue, color=plotColour, linewidth=2)

问题分析:这里我们收到了关于 emaVlue 的’undeclared identifier’错误。这显然应该是我们在第4行创建的变量 emaValue

解决方案:要修复该错误,我们只需在第5行将 emaVlue 修正为 emaValue 即可:

plotColour = close > emaValue ? color.green : color.red

错误示例2:变量名大小写错误

我们为自定义变量或函数所起的名字是大小写敏感的。因此,我们必须使用与创建时完全相同的大小写来引用它们。

但大小写错误很容易犯。例如:

//@version=5
indicator(title="错误示例", overlay=true)

emaValue   = ta.ema(close, 25)
plotColour = close > emavalue ? color.green : color.red // 此处大小写错误

plot(emaValue, color=plotColour, linewidth=2)

问题分析:这里脚本报错是因为我们在第5行使用了 emavalue。由于我们在第4行创建该变量时将其命名为 emaValue,我们也应该使用正确的大小写来引用它。

解决方案:要修复此处的错误,我们将第五行更改为:

plotColour = close > emaValue ? color.green : color.red

错误示例3:调用自定义函数时缺少括号

当我们创建一个TradingView函数时,我们首先声明其名称,然后在括号 () 内列出所有参数,并以函数代码结束。即使我们的自定义函数不使用任何参数,它也需要括号。要正确地引用该函数,我们必须在其名称后使用括号。如果我们不这样做,就会再次遇到’undeclared identifier’错误。

假设我们有一个 emaCustom() 函数,但试图以 emaCustom 的形式来执行它:

//@version=5
indicator(title="错误示例", overlay=false)

emaCustom() =>
    quickEMA = ta.ema(close, 10)
    slowEMA = ta.ema(close, 40)
    ta.ema(quickEMA - slowEMA, 15)

plot(emaCustom, color=color.orange, linewidth=2) // 此处缺少括号

问题分析:此示例代码遇到错误,是因为我们将 emaCustom() 函数引用为 emaCustom。没有函数名后面的括号 (),TradingView会认为我们想使用一个变量,而上面的指标并没有名为 emaCustom 的变量。

解决方案:要修复该问题,我们将第9行更改为以 emaCustom() 的形式来执行该函数:

plot(emaCustom(), color=color.orange, linewidth=2)

错误示例4:在声明变量前就对其进行更新

在TradingView中,我们有两种方式来设置我们的自定义变量。我们用 = 来创建变量并赋予它某个值。之后如果我们想更新它的值,我们使用 :=。但必须遵循这个顺序——我们首先创建变量(用 =),然后才能更新它(:=)。

如果我们不小心搞反了 =:= 的顺序,我们的代码就会触发’undeclared identifier’错误。例如:

//@version=5
indicator(title="错误示例", overlay=false)

movAvg := ta.sma(close, 20) // 错误:在声明前就更新

plot(movAvg, color=color.orange, linewidth=2)

movAvg = ta.ema(close, 10) // 错误:声明太晚

plot(movAvg, color=color.teal, linewidth=2)

问题分析:这里我们首先试图更新 movAvg 变量(第4行),之后才试图声明它(第6行)。这让TradingView感到困惑,错误提示说在试图更新其值时找不到 movAvg

解决方案:要修复此错误,我们将 =:= 的位置交换一下即可:

//@version=5
indicator(title="错误示例", overlay=false)

movAvg = ta.sma(close, 20) // 先用 = 声明

plot(movAvg, color=color.orange, linewidth=2)

movAvg := ta.ema(close, 10) // 后用 := 更新

plot(movAvg, color=color.teal, linewidth=2)

错误示例5:对自引用变量使用了错误的赋值操作符

当我们用一个自引用变量遇到’undeclared identifier’错误时,情况会变得更复杂。当一个变量引用了它自身在前一根K线上的值时(如 profit := profit[1] + todayProfit),该变量便被称为自引用变量。

要正确使用自引用变量,需要分两步走:首先,我们必须用 = 操作符创建该变量并为其设定一个初始值(如 profit = 0.0)。此时,我们还不能引用它自身!第二步,我们用 := 操作符来更新该变量的值,此时我们可以引用该变量在前一根K线上的值了。

但如果我们只对一个自引用变量使用 =,就会遇到’undeclared identifier’错误。例如:

//@version=5
indicator(title="错误示例", overlay=false)

barNumber = nz(barNumber[1]) + 1 // 错误:在同一行声明和自引用

plot(barNumber, color=color.orange, linewidth=2)
plot(bar_index, color=color.purple, linewidth=2)

问题分析:这里的问题在于我们试图同时做两件事:创建 barNumber 变量,又想在创建时就引用它自身在前一根K线上的值。

解决方案:相反,我们应该先用 = 创建 barNumber,然后才能用 := 来更新它。这意味着,我们将代码修改如下,便可修复该错误:

//@version=5
indicator(title="错误示例", overlay=false)

barNumber = 1 // 步骤1:用 = 声明并初始化
barNumber := nz(barNumber[1]) + 1 // 步骤2:用 := 更新并自引用

plot(barNumber, color=color.orange, linewidth=2)
plot(bar_index, color=color.purple, linewidth=2)

错误示例6:在声明变量前就对其进行前向引用

另一个会导致’undeclared identifier’错误的抽象情境是使用前向引用变量。当我们引用一个尚未被赋值的变量时,该变量便是一个前向引用变量。

要让前向引用变量正常工作,也需要两步:首先,我们必须用 = 创建该变量并为其设定一个默认值(如 stopPrice = 0.0),这行代码必须出现在对该变量的任何引用之前。然后,我们再用 := 将其值更新为我们实际想要它持有的值(如 stopPrice := emaValue - 0.0020)。

如果我们忽略了这一步骤,在用 = 创建变量之前就对其进行了前向引用,便会触发该错误。例如:

//@version=5
indicator(title="错误示例", overlay=false)

plusOne = nz(currentValue[1]) + 1 // 错误:在currentValue被声明前就引用它
currentValue = plusOne + close

plot(currentValue, color=color.orange, linewidth=2)

问题分析:这里的问题是,我们在更新 plusOne 变量时,引用了 currentValue 在前一根K线上的值。但这一操作发生在 currentValue 变量被创建之前。因此,TradingView无法理解我们在说什么,便会报错。

解决方案:要让第4行的前向引用正常工作,我们需要在那一行之前就创建好 currentValue 变量。我们用 = 操作符来做这件事,之后再用 := 来更新它。因此,修复该错误的代码如下:

//@version=5
indicator(title="错误示例", overlay=false)

currentValue = 0.0 // 步骤1:先用 = 声明并初始化
plusOne = nz(currentValue[1]) + 1
currentValue := plusOne + close // 步骤2:后用 := 更新

plot(currentValue, color=color.orange, linewidth=2)

总结

当TradingView无法找到我们试图使用的变量或函数时,便会发生’undeclared identifier’错误。这通常发生在我们输错了名称(包括大小写差异),或者在调用函数名时忘记了括号 ()

这些编码错误幸运地很容易找到和修复。但’undeclared identifier’错误也可能出现在更复杂的情境中,这通常发生在我们混淆了 =:= 操作符时。例如,我们不能在创建变量(=)之前就更新它(:=)。

如果我们在创建变量时就让它引用自身的前一个值,或者在脚本用 = 操作符创建变量之前就引用了它,我们也会遇到’undeclared identifier’错误。要修复这两种情况下的错误,我们应首先用 = 创建变量并赋予初始值,之后才能无误地获取其值或用 := 来更新它。

如何修复TradingView的”变量已声明”错误

如果没有自定义变量,在TradingView中进行高效的编程将十分困难。但不幸的是,变量有时也会触发一些耗时的错误。本文将探讨’variable is already declared’(变量已被声明)这个错误。

探究TradingView的’variable is already declared’错误

创建自定义变量是任何编程语言中都必不可少的一环。它们能让复杂的代码更易于管理,并避免代码重复。没有变量,大多数TradingView指标和策略脚本将难以——甚至不可能——实现。

但变量在为我们的代码带来结构和灵活性的同时,有时也可能显得严格而固执。’variable is already declared’这个错误就是一个例子。当这个错误在图表上触发时,我们会看到无法编译脚本的提示信息:

单凭这个提示我们无法获得太多信息,因为其他几种TradingView错误也会显示同样的消息。幸运的是,Pine编辑器的控制台窗口中提供了更多有用的信息。

在那里,我们会看到类似下面的消息:

Processing script...
line 8: Variable `movAvg` is already declared.
Script 'Error example' has been saved

让我们来解析这个错误,看看这些信息如何帮助我们修复’variable is already declared’的问题。

修复TradingView的’variable is already declared’错误

尽管这个错误信息可能有点令人困惑,但它包含了非常有用的线索,这使得修复这类错误相对直接。第一步,仔细阅读错误信息,注意它提示的行号以及引发错误的变量名称。第二步,在Pine编辑器中定位到指定的行号,在那一行,将 = 运算符替换为 := 运算符。第三步,保存脚本,看看是否还有新的错误出现。如果还有其他的’variable is already declared’错误,重复以上步骤即可。

为了更好地理解这个错误,让我们先回顾一下TradingView变量的工作原理,然后再通过一个具体的例子来加深理解。

TradingView变量:创建(声明)vs. 更新

与其他一些脚本语言不同,TradingView的Pine Script对变量的创建和更新做了严格的区分。我们使用 = 运算符来创建一个新变量,并为其赋予一个初始值,例如 rsiValue = ta.rsi(close, 12),这个过程也被称为声明(declare)一个变量。在变量被创建之后,我们可以使用 := 运算符来更新它的值,例如 rsiValue := ta.rsi(close, 4)

在大多数脚本中,我们可能并不需要频繁地更新变量。但如果你确实需要根据某些条件来改变变量的值,请务必记住:= 用于创建,:= 用于更新。例如:

// 使用 = 来声明和初始化变量
plotColour = color.green

// ...

// 稍后,使用 := 来更新变量的值
if close > ta.ema(close, 20)
    plotColour := color.orange

// 声明 rsiValue 变量
rsiValue = ta.rsi(close, 14)

// ...

// 根据条件更新 rsiValue 的值
rsiValue := timeframe.isintraday ? ta.rsi(close, 5) :
     ta.rsi(close, 22)

错误示例:重复声明同一个变量

所以,我们用 = 运算符来创建变量,然后用 := 来更新它。但我们不能对同一个变量多次使用 =。当我们尝试这样做时,就会得到’variable is already declared’的错误。

例如,下面的指标代码就会触发这个错误:

//@version=5
indicator(title="错误示例", overlay=false)

movAvg = ta.sma(close, 20)
plot(movAvg, color=color.orange, linewidth=2)

// 错误!试图用 = 再次声明 movAvg
movAvg = ta.ema(close, 10)
plot(movAvg, color=color.teal, linewidth=2)
Processing script...
line 8: Variable `movAvg` is already declared.
Script 'Error example' has been saved

在这里,我们在第4行使用 = 创建了 movAvg 变量。然后在第8行,我们又试图用 = 来更新它的值。但这在Pine Script中是不被允许的——我们必须使用 := 来更新一个已经存在的变量。

因此,要修复这个错误,我们只需将代码修改为:

//@version=5
indicator(title="错误示例", overlay=false)

movAvg = ta.sma(close, 20)
plot(movAvg, color=color.orange, linewidth=2)

// 正确!使用 := 来更新 movAvg
movAvg := ta.ema(close, 10)
plot(movAvg, color=color.teal, linewidth=2)

总结

自定义变量使得在TradingView中编程变得更加容易。但我们需要牢记创建变量和更新变量之间的区别。因为如果我们试图多次创建同一个变量,TradingView就会报出’variable is already declared’的错误。

我们使用 = 运算符来创建一个新变量并为其赋值,这个过程称为声明。之后,如果想在脚本的后续部分修改这个变量的值,就必须使用 := 运算符。

修复’variable is already declared’错误只需简单的几步:首先,仔细阅读错误提示,记下行号和变量名;然后,定位到那一行代码,将 = 替换为 :=;最后,保存脚本并检查是否还有新的错误。

赞(0)
未经允许不得转载:图道交易 » Pine Script(266):未声明标识符与变量重复声明错误
分享到

评论 抢沙发

登录

找回密码

注册