在某些情况下,thinkscript if statement无法按预期进行分支。下面的测试用例可以用来重现这个bug /缺陷。
它通过Grid containing chart and script共享
长话短说,在某些情况下,一种可能的解决方法是使用if表达式,这是一个可能较慢的函数,可能会导致扫描中的脚本执行超时。
thinkscript中的这个相当令人讨厌的bug阻止了我以我需要的方式编写一些扫描和研究。
以下是在图表上显示问题的一些示例代码。
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()。
让我们不要讨论实现目标的替代方法,以找到附加脚本的低,替代方案。
因为我并不是在寻求帮助来实现这个目标。我报告了一个bug,我想知道哪里出了问题,以及如何修复它。换句话说,在这里找到低点只是一个例子,以使脚本更容易遵循。它可以是人们想要脚本计算的任何其他东西。
请让我描述一下脚本。
首先,它使用移动平均进行一些平滑。结果是:
def output;然后脚本定义到右边缘的距离,这样我们就可以使用偏移:
def rightOffset;然后,该脚本构建一个查找表:
def lookup;script getMinValueBetween {}是一个小函数,它以动态方式查找两个偏移位置之间的低点。之所以需要它,是因为GetMinValueOffset()不接受动态参数。
然后我们有script buildValue {}
这就是错误发生的地方。此脚本在右侧边缘执行。
buildValue {}按如下方式执行间接查找:
首先,它进入查找,在lookupPosn = 23处找到值53。
对于53,if通过调用脚本函数getMinValueBetween()查找偏移量53和0之间的下限。它将值存储在def lowAtIndirectLookupPosn;中
如你所见,这确实非常简单--只有38行代码!
问题是,lowAtIndirectLookupPosn包含错误的值,就好像执行了if语句的错误分支一样。
plot testResult应该会抛出4.25的低点。相反,它输出的close[offsetLast]是6.26。
老实说,这是一场灾难,因为无法预测程序中哪条if语句会失败。
发布于 2019-10-10 19:36:05
在少数情况下,可以使用if表达式代替if语句。但是,if表达式仅涵盖部分用例,并且在扫描时可能会以较低的性能执行。更重要的是,
it defeats the purpose of the if statement in an important case,因为它支持条件赋值,但不支持条件执行。换句话说,它在分配两个值中的一个之前执行两个分支。
https://stackoverflow.com/questions/58321894
复制相似问题