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

Pine Script(267):字符替代、类型分配与行尾延续错误

#Pine Script入门教学

如何纠正TradingView的”字符处没有可行的替代方案”错误?

在TradingView Pine中编程,就像学习一门语言一样。我们需要遵循特定的语法规则(syntax),才能编写出有效的代码。一旦我们违反了这些规则,就会遇到错误。其中一种错误便是’no viable alternative at character’。本文将探讨这个错误的含义以及如何修复它。

深入了解TradingView的没有可行的替代方案错误

在TradingView中,所有的指标和策略脚本都由一系列语句组成,这些语句可以定义变量、创建自定义函数或执行函数。这些语句的结构以及我们在每一行中输入的内容,都由TradingView的语法规则所决定。这些规则就像我们日常语言中的语法一样,它们确保我们最终能得到正确、有效的代码。

当我们在代码中犯了语法错误时,就会得到一个所谓的语法错误。其中之一便是’no viable alternative at character’。当我们遇到这个错误时,可能会出现两种情况。如果错误发生时,我们的脚本已经在图表上,那么一个通用的’cannot compile script’(无法编译脚本)消息会出现在品种名称的正下方:

由于很多其他TradingView错误也使用这个提示,它本身并没有提供太多关于具体错误情况的信息。幸运的是,还有第二条错误信息。

这个错误会显示在Pine编辑器的控制台日志中,看起来像这样:

Processing script...
line 4: no viable alternative at character '}'
Script 'Error example' has been saved

这个消息提供了多得多的细节。它甚至提到了具体的错误以及在哪里找到它。接下来,让我们看看如何解读这个错误并修复代码问题。

修复TradingView的’no viable alternative at character’错误

‘no viable alternative at character’错误,其字面意思是在某个字符处没有可行的替代方案,它通常发生在我们输入了一个在当前代码上下文中不合法的字符时。例如,我们可能在一个需要逗号(,)的地方输入了句点(.),或者用花括号({)代替了圆括号(())。

虽然遇到这些错误有点烦人,但错误信息本身提供了关于错误发生位置的有用信息,这使得修复这个编程错误相对直接。第一步,仔细阅读错误信息,注意解决错误的关键信息:行号和该行中不正确的字符。第二步,在你的TradingView脚本中跳转到该行号,并寻找错误信息中提到的那个字符。有时,错误信息可能没有明确指出是哪个字符错了,在这种情况下,你就需要自己仔细检查那一行代码,找出不正确的字符。第三步,用正确的字符替换那个不正确的字符。这个错误通常只是一个简单的键盘按键失误,所以在该行中仔细查找任何输入错误。

为了更好地理解’no viable alternative at character’错误,让我们看几个会弹出这个错误的具体情境。

错误示例1:使用分号(;)结束代码行

触发该错误的一个情境是,代码行以分号(;)结束。虽然很多其他编程语言确实用 ; 来结束一条语句,但TradingView Pine不是其中之一。

假设我们这样编写一个指标:

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

emaValue = ta.ema(hl2, 30); // 错误:Pine中不需要分号

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

问题分析:这里我们收到了错误,因为第4行的语句以 ; 结尾。在TradingView Pine中,我们不应该使用任何行尾结束符。

解决方案:我们只需简单地将那行有问题的代码修改为:

emaValue = ta.ema(hl2, 30)

错误示例2:简单的按键失误

这个错误有时可能很恼人,因为它可能仅仅源于一次简单的按键失误。

例如,这里我们本应按 , 键,却误输入了 .

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

emaValue = ta.ema(hl2. 30) // 错误:应用逗号分隔参数

plotColour = (close > open) ? color.red : color.green
plot(emaValue, color=plotColour, linewidth=2)

问题分析:TradingView函数的参数应该用逗号(,)分隔,而不是句点(.)。

解决方案:我们将第4行修改为:

emaValue = ta.ema(hl2, 30)

错误示例3:引用历史K线数据时用错字符

与其他TradingView错误相比,即便是经验丰富的Pine Script程序员,也可能频繁遇到’no viable alternative at character’错误,因为它本质上更像一个拼写或输入错误。

下面就是一个例子。这里我们按 Shift 键太早,结果输入了 } 而不是 ]

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

plotValue = open != close[1} ? // 错误:应为 ]
     ta.sma(close, 10) :
     ta.ema(close, 12)
plot(plotValue, color=color.orange, linewidth=2)

解决方案:要修复这里的错误,我们将 close[1} 中的 } 替换为 ]。所以第4行变成:

plotValue = open != close[1] ?
     ta.sma(close, 10) :
     ta.ema(close, 12)

错误示例4:在条件运算符中用错字符

通过条件运算符(?:),我们可以根据一个真/假条件在两个选项中选择一个。我们用冒号(:)来分隔这两个选项——任何其他字符都会触发’no viable alternative at character’错误。

这个示例指标在条件运算符上出错了:

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

emaValue = ta.ema(hl2, 30)

plotColour = close > open ? color.red ; color.green // 错误:应用冒号 :

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

解决方案:要修复这个错误,我们必须将 ; 替换为 :。这使得第6行如下:

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

总结

要正确地编写TradingView脚本,我们必须遵循TradingView Pine的语法规则。当出现语法错误时,可能会发生的一个错误便是’no viable alternative at character’。每当我们使用了一个不合法的字符时,就会出现这个错误消息。

幸运的是,错误信息本身通常会提及行号和不正确的字符。这使得修复错误变得相当直接:只需跳转到那一行,用正确的字符替换掉提示的字符即可。有时,该错误可能没有指明具体是哪个字符错了,在这种情况下,我们就需要自己仔细检查那一行代码。

如何解决TradingView的”无法分配类型表达式”错误?

在TradingView中,如果没有自定义变量,高效编程将变得非常困难,实现复杂脚本更是如此。尽管Pine Script中的变量比其他语言更灵活,但我们仍可能遇到一些错误信息。其中之一就是’cannot assign expression of type’(无法分配该类型的表达式)错误。这个错误到底是怎么回事,我们又该如何修复它呢?

探究TradingView的’cannot assign expression of type’错误

变量让编程变得容易得多。有了它们,我们就不必重复执行相同的计算,这意味着代码冗余更少,使我们的指标和策略脚本更易于阅读。而且,一旦我们更新一个变量,它在脚本中所有地方的值都会随之改变。

但有时,变量也会触发一些令人沮丧的错误。’cannot assign expression of type’就是其中之一。如果脚本在图表上运行时触发此错误,我们会看到无法编译脚本的提示:

这个提示本身帮助不大,因为其他几种错误也会显示同样的消息。但幸运的是,Pine编辑器下方的控制台窗口中提供了更详细的错误信息。

在那里,我们会看到类似下面的内容:

Processing script...
line 9: Variable `plotCr` was declared with series[color] type. Cannot assign it expression of type series
Script 'Error example' has been saved

(第9行:变量 plotCr 被声明为series[color]类型。无法为其分配series类型的表达式)

让我们来解析这个错误,看看这些信息如何帮助我们修复它。

修复TradingView的’cannot assign expression of type’错误

‘cannot assign expression of type’错误发生在我们试图将一种类型的值存入一个持有不同类型值的变量中时。例如,我们不能将一个颜色值存入一个布尔型(真/假)变量中,也不能将一个布尔值存入一个数值型变量中。

修复这个错误的方法如下。第一步,仔细阅读错误信息,注意它提示的行号和变量名称。第二步,在Pine编辑器中定位到指定的行号,找到错误信息中提到的那个变量。第三步,通过以下方式之一来修复错误:如果你只是用错了变量名,那就换成正确的变量名,例如你本想把RSI的值存起来,却不小心把它赋给了用于存储绘图颜色的变量,这时只需将颜色变量名换成你的RSI变量名即可;如果你试图在变量中存储一个错误类型的值,那就换成正确类型的值,例如你试图将一个EMA均线值(数值型)赋给一个布尔型变量,这时应将EMA值换成一个合适的 truefalse 值;如果你确实想将这个不兼容的值存入该变量,那么你需要知道这是不允许的,你必须创建一个新的变量来存储这个不同类型的值,例如如果你的目标是将一个颜色值存入一个布尔型变量,那么你需要创建一个新的颜色变量,并保持原有的布尔型变量只存储布尔值。

在看具体示例之前,让我们先来理解一下什么是变量类型以及类型错误是如何产生的。

变量的类型:一个变量能存储什么值?

在Pine Script中,每个变量在被创造(声明)的那一刻,它的类型就被决定了。我们使用 = 运算符来声明一个新变量并赋给它初始值。

TradingView会根据这个初始值来推断变量的类型。例如,myColour = color.red 会创建一个颜色型变量,而 emaValue = ta.ema(close, 9) 则会创建一个数值型变量。

虽然Pine Script很智能,可以进行一些自动的类型转换(例如,你可以把整数存入一个浮点型变量),但当两种类型完全不兼容时,就会引发’cannot assign expression of type’的错误。

以下是各种变量类型所能接受的值:

变量类型 允许的值
Integer (整数) 整数、浮点数、na
Float (浮点数) 浮点数、整数、na
Bool (布尔型) 布尔值、浮点数、整数、na
Color (颜色) 颜色、na

这个表格也揭示了哪些类型之间是不兼容的:颜色型变量不能存储任何数值(整数或浮点数)或布尔值;数值型变量(整数或浮点数)不能存储布尔值;布尔型变量不能存储颜色值。

让我们通过几个具体的例子来加深理解。

错误示例:将布尔值赋给数值型变量

数值型变量是最常用的。但我们不能用它们来存储布尔(true/false)值。当我们尝试这样做时,就会报错:

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

movAvg = ta.sma(close, 20) // movAvg 在此被声明为数值型
plot(movAvg, color=color.orange, linewidth=2)

// 错误!试图将布尔值 (close > low) 赋给数值型变量 movAvg
movAvg := close > low
plot(ta.sma(close, 40), color=movAvg ? color.teal : color.orange,
     linewidth=2)
line 8: Variable `movAvg` was declared with series type. Cannot assign it expression of type series[bool]

要修复这个错误,我们不能将布尔值硬塞给数值型变量,而应该为这个布尔逻辑创建一个新的变量:

// 正确的做法:创建一个新的布尔变量
colourPlot = close > low
plot(ta.sma(close, 40), color=colourPlot ? color.teal : color.orange,
     linewidth=2)

错误示例:将数值存入颜色型变量

当我们试图将一个数值(比如EMA的值)存入一个设计用来存储颜色的变量时,同样会报错:

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

movAvg = ta.sma(close, 20)
// plotCr 在此被声明为颜色型
plotCr = close > movAvg ? color.teal : color.orange
plot(movAvg, color=plotCr, linewidth=2)

// 错误!试图将数值 (ta.ema) 赋给颜色型变量 plotCr
plotCr := ta.ema(close, 10)
bgcolor(close > plotCr ? color.green : color.red)
line 9: Variable `plotCr` was declared with series[color] type. Cannot assign it expression of type series

修复方法同样是创建一个新的变量来存储EMA的值:

emaValue = ta.ema(close, 10)
bgcolor(close > emaValue ? color.green : color.red)

错误示例:将颜色存入布尔型变量

反之,将颜色值存入布尔型变量也是不被允许的:

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

highs = ta.highest(high, 20)[1]

// newHigherHigh 在此被声明为布尔型
newHigherHigh = high > highs
plot(highs, color=newHigherHigh ? color.green : color.orange,
     linewidth=2)

// 错误!试图将颜色值赋给布尔型变量 newHigherHigh
newHigherHigh := high > high[1] ? color.teal : na
bgcolor(newHigherHigh)
line 11: Variable `newHigherHigh` was declared with series[bool] type. Cannot assign it expression of type series[color]

我们只需为背景颜色创建一个新的变量即可解决问题:

bgColour = high > high[1] ? color.teal : na
bgcolor(bgColour)

总结

在TradingView中,变量的类型是在其首次被声明(使用 =)时根据初始值决定的。此后,向该变量赋一个不兼容类型的值,就会触发’cannot assign expression of type’的错误。

修复这个错误其实比它听起来要简单:仔细阅读错误提示,定位到出错的行和变量,然后决定是应该使用一个不同的变量,还是为这个新类型的值创建一个全新的变量。

如何纠正TradingView的”行尾无延续”错误?

通过巧妙地使用缩进和空白字符,我们能让TradingView指标和策略脚本的代码更易于阅读。但缩进是一件非常精确的事情:仅仅一个空格的差异,就可能让我们的脚本出现’end of line without continuation’的错误。本文将探讨这个错误到底是怎么回事。

探究行尾无续行错误

在TradingView中,空白字符是一个重要的特性。我们不仅通过EnterTabSpace键来格式化代码的外观,也通过它们来决定哪些语句属于同一个代码块。例如,当我们缩进一个自定义函数的所有语句时,TradingView便知道哪些代码行属于该函数,哪些不属于。

TradingView在处理空白字符方面相当严格:这里或那里多一个或少一个空格,都可能导致截然不同的结果。当我们搞乱了脚本的缩进时,很可能会遇到’end of line without continuation’错误。当这个错误发生时,可能会出现两种情况。如果脚本已经在图表上运行,我们会在品种名称下方看到通用的’cannot compile script’(无法编译脚本)错误提示:

这个提示帮助不大,因为大多数TradingView错误都显示同样的信息。一个信息更丰富的错误消息,可以在TradingView的Pine编辑器中找到。

在控制台窗口中,我们会看到类似这样的内容:

Processing script...
line 4: mismatched input 'end of line without line continuation' expecting ')'
Script 'Error example' has been saved

这个错误信息就提供了我们可以用来修复问题的线索。让我们来学习如何做。

修复TradingView的’end of line without continuation’错误

‘end of line without continuation’(行尾无续行)这个错误信息听起来可能有些神秘和抽象。但幸运的是,解决这个问题比它的名字所暗示的要容易得多。第一步,仔细阅读错误信息,并记下提示的行号。第二步,在Pine编辑器中跳转到该行号,寻找任何空白或缩进上的错误并加以修正。

这里有个重要提示:TradingView错误提示的行号,是该条语句开始的地方。例如,当我们有一个跨越第5-7行的多行语句,而实际错误在第6行时,错误信息仍然会指向第5行,因为错误的语句是从那里开始的。这意味着,有时我们需要在错误信息提示的行号往下一到两行去寻找真正的错误所在。

为了让修复这个错误的过程更具体,我们将在下文探讨几个错误示例。但首先,我们快速回顾一下TradingView的空白字符规则。

理解TradingView的缩进和空白规则

在TradingView中,我们如何缩进代码是一件大事。因为缩进决定了一段代码是新的语句、前一行代码的延续,还是属于一个自定义函数、循环或if/else语句块。其他语言通常使用花括号({})来定义代码块,而TradingView则使用TabSpace

TradingView Pine的缩进规则是这样的:当我们将一条语句分散到多行时(即续行),从第二行开始的额外行必须缩进至少5个空格(或等效的1个Tab键+1个空格)。当我们创建一个多行函数、if/else语句块或循环时,其代码块内的每一行都必须缩进4个空格(或1个Tab键)。如果我们在一个多行函数内部又创建了一个多行语句,那么该语句的额外行需要缩进至少9个空格(或2个Tab键+1个空格)。如果我们的if语句中包含了另一个嵌套的ifif/else语句,那么这个嵌套的语句块需要缩进8个空格(或2个Tab键)。

虽然了解这些规则有帮助,但你不必死记硬背。在Pine编辑器中,有一个方便的功能可以帮助我们快速判断缩进是否正确。

技巧:在Pine编辑器中快速查看缩进

要查看某一行代码使用了多少空白,我们只需寻找Pine编辑器中的细小垂直标尺即可:

这些细小的垂直标尺出现在每4个空格(即1个Tab键)的位置。所以,如果我们的行是用一个Tab键缩进的,我们就看不到这条垂直标尺(因为代码的第一个字符正好压在标尺上)。但如果我们的代码是用5个空格缩进的,这条垂直标尺就可见了。

换句话说,对于多行语句(续行),我们应该能看到这条垂直标尺,因为它们至少需要5个空格的缩进。对于多行函数、if语句和循环的代码块,我们不应该看到这条垂直标尺,因为它们都应该正好缩进一个Tab(4个空格)。当这些代码块中包含另一个嵌套的代码块时,我们应该能看到一条垂直标尺,因为这时需要2个Tab(8个空格)的缩进,而标尺出现在第1个Tab(4个空格)的位置。

现在,让我们探讨一些会触发’end of line without continuation’错误的示例脚本,以及如何修复它们。

错误示例1:多行语句被错误地缩进了4个空格

当我们有一行很长的代码时,可以将其分散到多行。为此,我们需要用至少5个空格来缩进额外的行。

但如果一个多行语句被错误地缩进了4个空格(或其倍数),我们的代码就会触发错误。示例如下:

//@version=5
indicator(title="错误示例",
    overlay=true) // 错误:续行只缩进了4个空格

plotColour = color.green
plot(ta.sma(close, 10), color=plotColour, linewidth=2)

问题分析:这里,indicator()函数被分成了多行,但其续行(第3行)只缩进了4个空格(一个Tab),这被Pine语言解释为一个新的代码块,而非上一行的延续。

解决方案:多行语句的续行至少需要5个空格。我们只需在第3行的开头多加一个空格即可:

indicator(title="错误示例",
     overlay=true)

错误示例2:用Tab的整数倍来缩进多行语句

分散到多行的语句应该被缩进,但不能正好是4个空格的整数倍。

换句话说,多行语句的续行不能有4、8、12或16个空格(或1、2、3、4个Tab键)的缩进。否则,就会触发错误。例如:

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

plotValue = open != close[1] ?
        close : // 错误:续行缩进了8个空格
        low - (.1 * close)

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

问题分析:这里的条件运算符被分成了多行,但其续行被缩进了8个空格(两个Tab),这是一个不被允许的续行缩进。

解决方案:我们只需在每个续行的开头再添加一个空格,打破4的倍数这个规则即可:

plotValue = open != close[1] ?
     close :
     low - (.1 * close)

错误示例3:不应缩进的独立行被错误地缩进

Pine编辑器会自动保持与上一行相同的缩进级别,这在编写长函数或复杂循环时很方便。

但是,我们不应该用与前几行相同的缩进来开始一个新的、独立的语句。只有当新代码确实属于前一行的延续时,才应保持相同的缩进。如果我们忘记重置缩进级别,迟早会遇到错误。例如:

//@version=5
strategy(overlay=true, title="错误示例策略")
// ... (部分代码省略) ...
plotColour = strategy.position_size > 0 ? color.red :
     strategy.position_size < 0 ? color.green :
     color.yellow

    plot(ta.sma(close, 10), color=plotColour) // 错误:此行不应缩进

问题分析:第16行的 plot() 语句是一个新的、独立的语句,但它错误地沿用了 plotColour 变量多行定义的缩进。

解决方案:我们只需移除 plot() 前面的所有空白字符即可:

plotColour = strategy.position_size > 0 ? color.red :
     strategy.position_size < 0 ? color.green :
     color.yellow
plot(ta.sma(close, 10), color=plotColour)

错误示例4:函数体内的代码行缩进多了一个空格

当我们创建一个多行代码的自定义函数时,每一条语句都需要用4个空格或1个Tab键(或其倍数)来缩进。即使缩进只多了一个空格,代码也无法编译。例如:

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

plotValue(a, b) =>
     c = a + 0.1 * b // 错误:缩进了5个空格
    sum = a + b + c
    sum / 3.21

plot(plotValue(close, low), color=color.orange, linewidth=2)

问题分析:plotValue() 函数体内的 c = ... 这一行被缩进了5个空格,而函数体内的语句块应该正好缩进4个空格(或其倍数)。

解决方案:只需移除多余的那个空格,让所有语句块内的代码行都对齐即可:

plotValue(a, b) =>
    c = a + 0.1 * b
    sum = a + b + c
    sum / 3.21

错误示例5:忘记缩进多行语句

当我们将一条语句分散到多行时,其额外的行应该用至少5个空格来缩进。但有时在复制粘贴代码时,缩进可能会丢失。这时,TradingView就会报错。例如:

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

emaValue = ta.sma(close, 20)
alertcondition(close > emaValue, // 错误:续行没有缩进
"Example alert",
"Close is above emaValue")

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

问题分析:alertcondition() 函数跨越了三行,但其续行完全没有缩进。

解决方案:我们只需为其续行添加至少5个空格的缩进即可:

alertcondition(close > emaValue,
     "Example alert",
     "Close is above emaValue")

错误示例6:if/else语句中的缩进不正确

当我们编写 if/else 语句时,其代码块需要缩进1个Tab(或4个空格)。如果缩进不正确,哪怕只差一个空格,也会触发错误。例如:

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

value = if close > open
    math.max(close, math.min(low, high))
else
     math.min(close, math.max(low, high)) // 错误:缩进了5个空格

plot(value, color=color.blue, linewidth=3, style=plot.style_circles)

问题分析:else 关键字下方的语句被缩进了5个空格,而它应该只缩进4个空格。

解决方案:我们确保 ifelse 下的代码块都使用相同的、正确的缩进(4个空格或1个Tab):

value = if close > open
    math.max(close, math.min(low, high))
else
    math.min(close, math.max(low, high))

总结

在TradingView中,缩进和空白字符是语法的一部分。TabSpace不仅格式化代码,还决定了哪些代码行被视为同一条语句的延续。

当我们弄错了缩进时,很可能会遇到’end of line without continuation’错误。虽然这个错误听起来复杂,但修复它并不难。仔细阅读错误信息并记下行号,然后跳转到该行,寻找并修正缩进问题。

TradingView的缩进规则非常精确:代码块(函数体、if/else块、循环)内的语句,应缩进4个空格(或1个Tab键);多行语句的续行,应缩进至少5个空格(或1个Tab键+1个空格)。

要快速查看一行的缩进,可以留意Pine编辑器中的细小垂直标尺,它出现在每4个空格的位置。对于代码块,你不应该看到这条标尺;对于续行,你应该能看到这条标尺。

赞(0)
未经允许不得转载:图道交易 » Pine Script(267):字符替代、类型分配与行尾延续错误
分享到

评论 抢沙发

登录

找回密码

注册