Skip to content

Latest commit

 

History

History
278 lines (199 loc) · 18.2 KB

Conditional_structures.md

File metadata and controls

278 lines (199 loc) · 18.2 KB

条件结构

Pine Script™ 中的条件结构是ifswitch。它们可以用于:

  • 对于它们的副作用,即当它们不返回值但执行某些操作时,例如将值重新分配给变量或调用函数。
  • 返回一个值或一个元组,然后可以将其分配给一个(或多个,如果是元组)变量。

条件结构,如forwhile结构,可以嵌入;您可以在另一个结构中使用 ifswitch

某些 Pine Script™ 内置函数无法从条件结构的本地块内调用。它们是: alertcondition()barcolor()fill()hline()indicator()library()plot()plotbar()plotcandle()plotchar()plotshape()strategy()。这并不意味着它们的功能不能通过脚本评估的条件来控制——只是不能通过将它们包含在条件结构中来完成。请注意,虽然input*.()本地块中允许函数调用,但它们的功能与脚本全局范围内的功能相同。

条件结构中的局部块必须缩进四个空格或制表符。

用于其副作用的if结构具有以下语法:

if <expression>
    <local_block>
{else if <expression>
    <local_block>}
[else
    <local_block>]

在哪里:

  • 方括号 ( []) 中的部分可以出现零次或一次,大括号 ( {}) 中的部分可以出现零次或多次。
  • <表达式> 必须是“bool”类型或者可以自动转换为该类型,这仅适用于“int”或“float”值(请参阅类型系统页面)。
  • <local_block> 由零个或多个语句组成,后跟一个返回值,该返回值可以是值的元组。它必须缩进四个空格或制表符。
  • 可以有零个或多个子句。else if
  • 可以有零个或一个else子句。

当if后面的 计算结果为true时,将执行第一个本地块,if 结构的执行结束,并返回在本地块末尾计算的值。

当if后面的 计算结果为false时,将计算后续子句(如果有)。当 one 的 计算结果为true时,执行其本地块,if 结构的执行结束,并返回在本地块末尾计算的值。else if

当没有 计算为true 并且else存在子句时,将执行其本地块,if 结构的执行结束,并返回在本地块末尾计算的值。

当没有 的计算结果为true 并且不else存在子句时,将返回na 。

例如,使用if 结构的副作用对于管理策略中的订单流很有用。虽然通常可以使用调用when中的参数 来实现相同的功能strategy.*(),但使用if 结构的代码更易于阅读:

if (ta.crossover(source, lower))
    strategy.entry("BBandLE", strategy.long, stop=lower,
                   oca_name="BollingerBands",
                   oca_type=strategy.oca.cancel, comment="BBandLE")
else
    strategy.cancel(id="BBandLE")

可以使用 if 结构将代码的执行限制在特定的柱上,就像我们在这里将标签的更新限制在图表的最后一个柱上一样:

//@version=5
indicator("", "", true)
var ourLabel = label.new(bar_index, na, na, color = color(na), textcolor = color.orange)
if barstate.islast
    label.set_xy(ourLabel, bar_index + 2, hl2[1])
    label.set_text(ourLabel, str.tostring(bar_index + 1, "# bars in chart"))

注意:

  • ourLabel我们仅在脚本的第一个栏上 初始化变量,因为我们使用var声明模式。用于初始化变量的值由 label.new()函数调用提供,该函数返回一个指向它创建的标签的标签 ID。我们使用该调用来设置标签的属性,因为一旦设置,它们将持续存在,直到我们更改它们为止。
  • 接下来发生的是,在每个连续的柱上,Pine Script™ 运行时将跳过 的初始化ourLabel,并评估if 结构的条件 ( barstate.islast )。它在所有柱上返回false,直到最后一个柱,因此脚本在零柱之后的大多数历史柱上不执行任何操作。
  • 在最后一个柱上,barstate.islast 变为 true 并且结构的本地块执行,在每个图表上修改更新我们的标签的属性,该属性显示数据集中的柱数。
  • 我们希望在没有背景的情况下显示标签的文本,因此我们 在label.new()函数调用中将标签的背景设置为na ,并用于标签的y位置,因为我们不希望它一直移动。通过使用前一个柱的值 和低值的平均值,标签不会移动,直到下一个实时柱打开。hl2[1]
  • 我们在label.set_xy()调用中使用 将标签向右偏移两个条。bar_index + 2

用于返回一个或多个值的if结构 具有以下语法:

[<declaration_mode>] [<type>] <identifier> = if <expression>
    <local_block>
{else if <expression>
    <local_block>}
[else
    <local_block>]

在哪里:

  • 方括号 ( []) 中的部分可以出现零次或一次,大括号 ( {}) 中的部分可以出现零次或多次。
  • <declaration_mode> 是变量的声明模式
  • 是可选的,就像在几乎所有 Pine Script™ 变量声明中一样(请参阅types
  • 是变量的名称
  • <表达式> 可以是文字、变量、表达式或函数调用。
  • <local_block> 由零个或多个语句组成,后跟一个返回值,该返回值可以是值的元组。它必须缩进四个空格或制表符。
  • 分配给该变量的值是 <local_block> 的返回值, 如果没有执行本地块,则为na 。

这是一个例子:

//@version=5
indicator("", "", true)
string barState = if barstate.islastconfirmedhistory
    "islastconfirmedhistory"
else if barstate.isnew
    "isnew"
else if barstate.isrealtime
    "isrealtime"
else
    "other"

f_print(_text) =>
    var table _t = table.new(position.middle_right, 1, 1)
    table.cell(_t, 0, 0, _text, bgcolor = color.yellow)
f_print(barState)

可以省略else块。在这种情况下,如果condition 为 false,则会将值(nafalse"")分配给该 var_declarationX变量。

这是一个示例,显示 当没有执行本地块时如何返回na 。如果在这里, 则返回na :close > open``false

x = if close > open
    close

脚本可以包含if嵌套结构if和其他条件结构。例如:

if condition1
    if condition2
        if condition3
            expression

但是,从性能角度来看,不建议嵌套这些结构。如果可能,通常更优化的做法是使用多个逻辑运算符组成单个if语句,而不是多个嵌套if块:

if condition1 and condition2 and condition3
    expression

开关 结构有两种形式可以切换键表达式的不同值:

[[<declaration_mode>] [<type>] <identifier> = ]switch <expression>
    {<expression> => <local_block>}
    => <local_block>

另一种形式不使用表达式作为键;它打开不同表达式的求值:

[[<declaration_mode>] [<type>] <identifier> = ]switch
    {<expression> => <local_block>}
    => <local_block>

在哪里:

  • 方括号 ( []) 中的部分可以出现零次或一次,大括号 ( {}) 中的部分可以出现零次或多次。
  • <declaration_mode> 是变量的声明模式
  • 是可选的,就像在几乎所有 Pine Script™ 变量声明中一样(请参阅types
  • 是变量的名称
  • <表达式> 可以是文字、变量、表达式或函数调用。
  • <local_block> 由零个或多个语句组成,后跟一个返回值,该返回值可以是值的元组。它必须缩进四个空格或制表符。
  • 分配给该变量的值是 <local_block> 的返回值, 如果没有执行本地块,则为na 。
  • 最后的允许您指定一个返回值,该返回值充当结构中没有执行其他情况时使用的默认值。=> <local_block>

仅执行switch结构的一个本地块。因此,它是一个不会因情况而异的**结构化交换机。因此,声明是不必要的。break

这两种形式都可以作为用于初始化变量的值。

if结构一样,如果没有执行任何本地块,则返回na 。

让我们看一个 使用表达式的switch示例:

//@version=5
indicator("Switch using an expression", "", true)

string maType = input.string("EMA", "MA type", options = ["EMA", "SMA", "RMA", "WMA"])
int maLength = input.int(10, "MA length", minval = 2)

float ma = switch maType
    "EMA" => ta.ema(close, maLength)
    "SMA" => ta.sma(close, maLength)
    "RMA" => ta.rma(close, maLength)
    "WMA" => ta.wma(close, maLength)
    =>
        runtime.error("No matching MA type found.")
        float(na)

plot(ma)

注意:

  • 我们要打开的表达式是变量,它是“input int”类型(有关“ inputmaType ”限定符是什么的解释,请参见此处)。由于它在脚本执行期间无法更改,这保证了用户选择的任何 MA 类型都将在每个柱上执行,这是像 ta.ema()这样的函数的要求 ,这些函数需要一个“简单 int”参数作为其参数。length
  • 如果没有找到 的匹配值maType,则交换机 将执行由 引入的最后一个本地块=>,该块充当包罗万象的角色。我们在该块中生成运行时错误。我们还以float(na)这样的方式结束它,以便本地块返回一个其类型与结构中其他本地块的类型兼容的值,以避免编译错误。

这是不使用表达式的switch结构的示例:

//@version=5
strategy("Switch without an expression", "", true)

bool longCondition  = ta.crossover( ta.sma(close, 14), ta.sma(close, 28))
bool shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))

switch
    longCondition  => strategy.entry("Long ID", strategy.long)
    shortCondition => strategy.entry("Short ID", strategy.short)

注意:

  • 我们使用开关 来选择要发出的适当策略顺序,具体取决于longConditionshortCondition“bool”变量是否为true
  • longCondition和的建筑条件shortCondition 是排他性的。虽然它们可以false同时存在,但它们不能true同时存在。 因此,仅执行switch结构的一个本地块这一事实对我们来说不是问题。
  • 我们在进入 switch结构之前评估对ta.crossover()ta.crossunder() 的调用。不这样做(如以下示例所示)将阻止在每个柱上执行函数,这将导致编译器警告和不稳定的行为:
//@version=5
strategy("Switch without an expression", "", true)

switch
    // Compiler warning! Will not calculate correctly!
    ta.crossover( ta.sma(close, 14), ta.sma(close, 28)) => strategy.entry("Long ID", strategy.long)
    ta.crossunder(ta.sma(close, 14), ta.sma(close, 28)) => strategy.entry("Short ID", strategy.short)

当结构体中使用多个局部块时,其所有局部块的返回值类型必须匹配。这仅适用于在声明中使用结构体为变量赋值的情况,因为变量只能有一种类型,如果语句在其分支中返回两种不兼容的类型,则无法正确确定变量类型。如果该结构未分配到任何位置,则其分支可以返回不同的值。

这段代码编译得很好,因为closeopen都是以下类型float

x = if close > open
    close
else
    open

此代码无法编译,因为第一个本地块返回一个float值,而第二个本地块返回 a string,并且 - 语句的结果if分配给x变量:

// Compilation error!
x = if close > open
    close
else
    "open"