如何创建保留其值的变量

use*_*343 1 thinkscript

在 thinkscript 图表和扫描中,任何脚本都会针对每个柱执行多次。此类执行之间的程序状态存储在数组变量中,这些变量可以直接访问或通过[]或通过偏移量访问GetValue()。许多涉及某种模式识别的脚本需要通过为这些变量分配初始值来在第一个柱处初始化这些变量。在后续柱上执行时,脚本会复制先前的值或创建新值。然后,根据某些其他条件,脚本可能会检查当前数组条目是否仍等于第一个数组条目,以发现数据中是否发生了有趣的事情。

以下测试脚本遵循这个简单的模式。它的唯一目的是使用扫描器来验证单个变量的第一个条目是否保留其值。

扫描在最后一个柱处执行单个绘图语句。该脚本的唯一标准是被测试的变量保持其值并且不会被其他东西改变。在 thinkscript 中更改变量或变量数组条目是非法的,不应该发生。但是,此脚本显示变量的第一个条目被覆盖。这是如何发生的以及如何避免这种情况?

def index;
def myVar;
if (BarNumber() == 1) {
    index = -1;
    myVar = close;
} else {
    if (close > myVar[1]) {
        myVar = close;
        index = index[1];
    } else {
        if (close <= myVar[1]) {
            index = 1;
        } else {
            index = index[1];
        }
        myVar = myVar[1];
    }
}
plot scan = GetValue(index, BarNumber() -1) == -1;
Run Code Online (Sandbox Code Playgroud)

lea*_*nne 5

另外,对于任何来到这里寻找实际上如何创建一个保留其值的变量的人- 意味着该值不会跨条改变,因为你不希望它改变 - 这里有 3 种方法......

使用递归变量,如下所示:

方法一if语句

# declare variable without initializing
def myVar;

# set up `if` condition for which variable should be set
if ( BarNumber() == 1 ) {
  
  # set the value you want when the condition is met
  # in this case, the variable is set to the close value at bar 1
  myVar = close;
}
# thinkScript always requires an `else` 
else {

  # now, here, if you want the variable to change, enter the desired value,
  # or, if you want it to always stay the same, then...
  myVar = myVar[1];

}
Run Code Online (Sandbox Code Playgroud)

方法2if表达式

# same as above, really, but more compact; use parens as desired for clarity
def myVar = if BarNumber() == 1 then close else myVar[1];
Run Code Online (Sandbox Code Playgroud)

方法 3CompoundValue()

注:一般情况下CompoundValue()与上面的例子作用相同,所以不需要使用;然而,有时必须使用它。请参阅下面的代码了解更多详细信息。

def myVar = CompoundValue(1,
                          if BarNumber() == 2 then close[1] else myVar[1],
                          0);

plot test = myVar;
Run Code Online (Sandbox Code Playgroud)

一些CompoundValue()细节

首先,参数,因为文档中的描述可能会令人困惑:

一个参数length. 它代表柱编号,之后 CompoundValue()将使用第二个参数中的表达式。

1 是该参数接受的最小(也是默认)值。

第二个参数"visible data"。这里的值必须是一个表达式,通常是一个计算(尽管我if在这个例子中使用了一个表达式)。

这是当值超过长度CompoundValue()时将使用的数据操作。例如,对于本示例,由于第一个参数中有 1,因此表达式在thinkScript 处理第二个柱之前不会生效。在第 0 和 1 小节处,第三个参数值将发挥作用。BarNumber()if

close请注意,我在表达式中使用了 for 的偏移量。由于我必须在参数中至少输入 1 length,因此 thinkScript 在开始使用表达式之前将位于第 2 小节。因此,我必须表明前一根柱线 ( close[1]) 的收盘价确实是我想要的。

第三个参数, "historical data", 是将用于第一个参数之前的条数的值,包括第一个参数中的长度(条数)值。

对于这个例子,我输入了 0,但我也可以使用Double.NaN. 对于我来说这并不重要,因为我不关心在计算点之前设置任何值。

CompoundValue()文档给出了一个现在很容易理解的斐波那契示例。它还说明了为什么人们可能想要为先前的柱设置一个值:

def x = CompoundValue(2, x[1] + x[2], 1);
plot FibonacciNumbers = x;
Run Code Online (Sandbox Code Playgroud)

length= 2,因此第二个参数的计算将在第三个柱出现之前进行。

"visible data"= ,将对第二个柱之后的每个柱(即从第三个柱向前)x[1] + x[2]进行计算。

"historical data"= 1,因此对于柱 1 和柱 2,将使用常数值 1 代替第二个参数中的计算。这适用于斐波那契计算!


至于为什么要使用CompoundValue()而不是上面的前两种方法,主要是CompoundValue在绘制具有多个长度或“偏移”的项目时需要这种方法。简而言之,thinkScript 会将所有绘制的偏移量更改为等于最大偏移量。CompoundValue与其他绘制的变量不同,它保留其指定的偏移值。

有关详细信息,请参阅 thinkScript 教程的第 12 章。过去/未来偏移和预取,以及我对 SO 问题理解和转换 ThinkScripts 复合值函数的 回答