外观
条件结构
约 3111 字大约 10 分钟
简介
Mine Script® 中的条件结构包括 if和 switch。它们可以用于:
- 对于它们的副作用,即当它们不返回值但执行某些操作时,例如为变量重新赋值或调用函数。
- 返回一个值或一个元组,然后可以将其分配给一个(或多个,如果是元组的话)变量。
条件结构(例如 for和 while结构)可以嵌入;您可以在另一个结构中使用if或switch。
某些 Mine Script 内置函数无法在条件结构的局部块中调用。它们是: alertcondition()、 barcolor()、 fill()、 hline()、 indicator()、 plot()、 plotbar()、 plotcandle()、 plotchar()、 plotshape()和 strategy()。这并不意味着它们的功能不能由脚本评估的条件控制,只是不能通过将它们包含在条件结构中来实现。请注意,虽然input*.()允许在局部块中调用函数,但它们的功能与在脚本的全局范围内相同。
条件结构中的局部块必须缩进四个空格或一个制表符。
if结构
if利用其副作用
利用其副作用的 if 结构语法如下:
if <expression>
<local_block>
{else if <expression>
<local_block>}
[else
<local_block>]其中:
- 用方括号(
[])括起来的部分可以出现零次或一次,用花括号({})括起来的部分可以出现零次或多次。 <expression>必须是"bool"类型或可自动转换为该类型,这种情况仅适用于"int"或"float"值(参见类型系统页面)。<local_block>由零个或多个语句组成,后跟一个返回值,该返回值可以是值的元组。必须缩进四个空格或一个制表符。- 可以有零个或多个
else if子句。 - 可以有零个或一个
else子句。
当if后的<expression>求值为true时,执行第一个局部代码块,if结构执行结束,并返回该局部代码块末尾求得的(一个或多个)值。
当if后的<expression>求值为false时,若存在连续的else if子句,则依次对其求值。当任一else if的<expression>求值为true时,执行对应的局部代码块,if结构执行结束,并返回该代码块末尾求得的(一个或多个)值。
当所有<expression>均求值为false且存在else子句时,执行该else的局部代码块,if结构执行结束,并返回该代码块末尾求得的(一个或多个)值。
当所有<expression>均求值为false且不存在else子句时,返回na值。
例如,在策略中使用if结构来管理订单流时,利用其副作用会非常实用。虽然同样的功能在低版本通常可以通过在strategy.*()调用中使用when参数来实现,但采用if结构的代码通常更易于阅读:
Mine Script®
已复制
使用if结构可以限制代码在特定K线上的执行,正如我们在此将标签更新限制在图表最后一根K线上所示:
Mine Script®
已复制
需注意:
- 我们仅在脚本的第一根K线上初始化
ourLabel变量(使用了var声明模式)。用于初始化变量的值由label.new()函数调用提供,该函数返回一个指向所创建标签的标签ID。我们通过该调用设置标签属性,因为这些属性一旦设置将持续生效,直到我们再次修改它们。 - 接下来的运行过程是:在后续的每根K线上,Mine Script运行时将跳过
ourLabel的初始化,并评估if结构的条件(barstate.islast)。在到达最后一根K线之前,该条件在所有K线上都返回false,因此脚本在除第一根K线外的大部分历史K线上不执行任何操作。 - 在最后一根K线上,barstate.islast变为true,此时if结构的局部代码块被执行,并在每次图表更新时修改我们标签的属性(该标签显示数据集中的K线数量)。
- 我们希望显示不带背景的标签文本,因此在label.new()函数调用中将标签背景设置为na,并使用
hl2[1]作为标签的y轴位置(因为我们不希望标签频繁移动)。通过使用前一根K线最高价和最低价的平均值,标签位置将保持稳定,直到下一根实时K线开盘时才更新位置。 - 在label.set_xy()调用中,我们使用
bar_index + 2将标签向右偏移两个K线单位。
if结构用于返回值时
用于返回一个或多个值的 if 结构语法如下:
[<declaration_mode>] [<type>] <identifier> = if <expression>
<local_block>
{else if <expression>
<local_block>}
[else
<local_block>]其语法规则如下:
- 方括号(
[])内的部分可以出现零次或一次,花括号({})内的部分可以出现零次或多次。 <declaration_mode>表示变量的声明模式<type>为可选参数(与绝大多数Mine Script变量声明相同,详见类型系统)<identifier>表示变量名称<expression>可以是字面量、变量、表达式或函数调用<local_block>由零个或多个语句组成,并以返回值结尾(返回值可以是值的元组)。必须缩进四个空格或一个制表符。- 变量的赋值结果将是
<local_block>的返回值,若未执行任何局部代码块则赋值为na。
这是一个示例:
Mine Script®
已复制
可以省略 else 代码块。在这种情况下,如果条件为假,将会为 var_declarationX 变量分配一个空值(na、false 或 "")。
以下示例展示了当未执行任何局部代码块时返回 na 的情况。若此处 close > open 条件为假,则将返回 na:
Mine Script®
已复制
脚本中可以包含带有嵌套 if 和其他条件结构的 if 结构。例如:
Mine Script®
已复制
不过,从性能角度考虑,不建议使用嵌套结构。在可能的情况下,通常更优的做法是构建一个包含多个逻辑运算符的单一 if 语句,而非使用多个嵌套的 if 代码块:
Mine Script®
已复制
switch结构
switch结构有两种形式。第一种形式根据键表达式的不同值进行分支选择:
[[<declaration_mode>] [<type>] <identifier> = ]switch <expression>
{<expression> => <local_block>}
=> <local_block>另一种形式不使用表达式作为键值,而是根据不同表达式的求值结果进行分支选择:
[[<declaration_mode>] [<type>] <identifier> = ]switch
{<expression> => <local_block>}
=> <local_block>其语法规则如下:
- 方括号
[]包裹的部分可出现0次或1次 - 花括号
{}包裹的部分可出现0次或多次 <declaration_mode>表示变量的声明模式<type>为可选参数(与大多数Mine Script变量声明相同,详见类型系统)<identifier>表示变量名称<expression>可以是字面量、变量、表达式或函数调用<local_block>由零个或多个语句组成,并以返回值结尾(返回值可以是值的元组)。必须缩进4个空格或1个制表符。- 变量的赋值结果将是
<local_block>的返回值,若未执行任何局部代码块则赋值为na。 - 最后的
=> <local_block>允许指定默认返回值,当结构中没有其他case被执行时使用。
switch结构仅会执行其中一个局部代码块,因此这是一种结构化分支选择,不会穿透执行后续case条件。因此,无需使用break语句中断执行。
两种形式都允许作为变量初始化的赋值来源。
与if结构相同,若未执行任何局部代码块,则默认返回na值。
switch带表达式的结构
让我们看一个使用表达式的switch示例:
Mine Script®
已复制
需要注意:
- 我们用作switch条件的
maType变量属于"input int"类型(关于"[input]"限定符的解释请参见此处)。由于该变量在脚本执行期间不可更改,这保证了用户选择的均线类型会在每根K线上执行,这是ta.ema()等函数的要求——它们的长度参数需要"简单整型"(simple int)输入。 - 如果未找到与
maType匹配的值,switch将执行由=>引入的最后一个局部代码块作为兜底处理。我们在该代码块中生成运行时错误,并以float(na)结尾,使该代码块返回的值与结构中其他局部代码块的类型兼容,从而避免编译错误。
不使用表达式的switch结构
这是一个不使用表达式的switch结构示例:
Mine Script®
已复制
需注意:
- 我们使用switch结构根据
longCondition或shortCondition这两个"bool"型变量的真值,来选择发送相应的策略订单。 longCondition和shortCondition的构建条件互斥。虽然它们可以同时为假,但不会同时为真。因此switch结构仅执行一个局部代码块的特性不会造成问题。- 我们在进入switch结构之前,预先计算ta.crossover()和ta.crossunder()的调用结果。若不这样做(如下例所示),将导致这些函数无法在每根K线上执行,从而引发编译器异常行为:
Mine Script®
已复制
局部代码块类型匹配要求
在结构中使用多个局部代码块时,所有局部代码块的返回值类型必须一致。此要求仅适用于将结构用于变量声明赋值的情况,因为一个变量只能有一种类型。如果语句在不同分支中返回两个不兼容的类型,将无法正确确定变量类型。若该结构未在任何地方进行赋值,则其分支可以返回不同类型的值。
这段代码能够正常编译,因为close和open都属于float类型:
Mine Script®
已复制
这段代码无法通过编译,因为第一个局部代码块返回的是浮点型(float)值,而第二个局部代码块返回的是字符串(string)类型,且if语句的结果被赋值给了变量x:
Mine Script®
已复制