0

thinkscript if 语句在某些情况下无法按预期分支。以下测试用例可用于重现此错误/缺陷。

它通过包含图表和脚本的网格共享

长话短说,在某些情况下,一种可能的解决方法是使用 if 表达式,它是一个函数,它可能更慢,可能导致扫描中的脚本执行超时。

thinkscript 中的这个相当讨厌的错误使我无法以我需要的方式编写一些扫描和研究。

以下是一些在图表上显示问题的示例代码。

input price = close;
input smoothPeriods = 20;
def output = Average(price, smoothPeriods);
# Get the current offset from the right edge from BarNumber()
# BarNumber(): The current bar number. On a chart, we can see that the number increases
# from left 1 to number of bars e.g. 140 at the right edge.
def barNumber = BarNumber();
def barCount = HighestAll(barNumber);
# rightOffset: 0 at the right edge, i.e. at the rightmost bar,
# increasing from right to left.
def rightOffset = barCount - barNumber;

# Prepare a lookup table:
def lookup;
if (barNumber == 1) {
    lookup = -1;
} else {
    lookup = 53;
}

# This script gets the minimum value from data in the offset range between startIndex
# and endIndex. It serves as a functional but not direct replacement for the
# GetMinValueOffset function where a dynamic range is required. Expect it to be slow.
script getMinValueBetween {
    input data = low;
    input startIndex = 0;
    input endIndex = 0;
    plot minValue = fold index = startIndex to endIndex with minRunning = Double.POSITIVE_INFINITY do Min(GetValue(data, index), minRunning);
}

# Call this only once at the last bar.
script buildValue {
    input lookup = close;
    input offsetLast = 0;
# Do an indirect lookup
    def lookupPosn = 23;
    def indirectLookupPosn = GetValue(lookup, lookupPosn);
# lowAtIndirectLookupPosn is assigned incorrectly. The if statement APPEARS to be executed
# as if indirectLookupPosn was 0 but indirectLookupPosn is NOT 0 so the condition
# for the first branch should be met!
    def lowAtIndirectLookupPosn;
    if (indirectLookupPosn > offsetLast) {
        lowAtIndirectLookupPosn = getMinValueBetween(low, offsetLast, indirectLookupPosn);
    } else {
        lowAtIndirectLookupPosn = close[offsetLast];
    }
    plot testResult = lowAtIndirectLookupPosn;
}
plot debugLower;
if (rightOffset == 0) {
    debugLower = buildValue(lookup);
} else {
    debugLower = 0;
}
declare lower;

要为股票 ADT 准备图表,请设置自定义时间范围:

10/09/18 至 10/09/19,汇总期 1 天。

该脚本的目的是在 2019 年 8 月 14 日找到 4.25 的低值。

我知道在 thinkscript 中有多种方法可以做到这一点,例如GetMinValueOffset().

让我们不要讨论实现目标的替代方法,以找到附加脚本的低替代方案。

因为我不是在寻求帮助来实现目标。我正在报告一个错误,我想知道出了什么问题以及如何修复它。换句话说,在这里找到低点只是使脚本更易于理解的一个示例。它可以是任何其他需要脚本计算的东西。

请让我描述一下脚本。

首先,它使用移动平均线进行一些平滑处理。结果是:

def output;

然后脚本定义与右边缘的距离,以便我们可以使用偏移量:

def rightOffset;

然后脚本构建一个查找表:

def lookup;

scriptgetMinValueBetween {}是一个小函数,它以动态的方式找到两个偏移位置之间的低点。它是必需的,因为GetMinValueOffset()不接受动态参数。

然后我们有脚本buildValue {}

这是发生错误的地方。该脚本在右边缘执行。

buildValue {}进行如下间接查找:

首先,它进入查找,在lookupPosn= 23 处找到值 53。

对于 53,如果通过调用脚本函数找到偏移 53 和 0 之间的低点getMinValueBetween()。它将值存储在def lowAtIndirectLookupPosn;

如您所见,这确实非常简单——只有 38 行代码!

问题是,它lowAtIndirectLookupPosn包含错误的值,就好像执行了 if 语句的错误分支一样。

plot testResult应该放出低点4.25。相反,它输出close[offsetLast]的是 6.26。

老实说,这是一场灾难,因为无法预测if程序中的哪个语句会失败。

4

1 回答 1

0

在少数情况下,可以使用 if 表达式代替 if 语句。但是,if 表达式仅涵盖用例的一个子集,并且它可能在扫描中以较低的性能执行。更重要的是,

它在一个重要的情况下违背了 if 语句的目的,因为它支持条件赋值但不支持条件执行。换句话说,它在分配两个值之一之前执行两个分支。

于 2019-10-10T11:36:05.277 回答