thinkscript if statement failure

送分小仙女□ 提交于 2019-12-11 16:14:05

问题


The thinkscript if statement fails to branch as expected in some cases. The following test case can be used to reproduce this bug / defect.

To cut the long story short, a possible workaround in some cases is to use the if-expression which is a function, which may be slower, potentially leading to Script execution timeout in scans.

This fairly nasty bug in thinkscript prevents me from writing some scans and studies the way I need to.

Following is some sample code that shows the problem on a chart.

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;

To prepare the chart for the stock ADT, please set custom time frame:

10/09/19 to 10/09/18, aggregation period 1 day.

The aim of the script is to find the low value of 4.25 on 08/14/2019.

I DO know that there are various methods to do this in thinkscript such as GetMinValueOffset().

Let us please not discuss alternative methods of achieving the objective to find the low, alternatives for the attached script.

Because I am not asking for help achieving the objective. I am reporting a bug, and I want to know what goes wrong and perhaps how to fix it. In other words, finding the low here is just an example to make the script easier to follow. It could be anything else that one wants a script to compute.

Please let me describe the script.

First it does some smoothing with a moving average. The result is:

def output;

Then the script defines the distance from the right edge so we can work with offsets:

def rightOffset;

Then the script builds a lookup table:

def lookup;

script getMinValueBetween {} is a little function that finds the low between two offset positions, in a dynamic way. It is needed because GetMinValueOffset() does not accept dynamic parameters.

Then we have script buildValue {}

This is where the error occurs. This script is executed at the right edge.

buildValue {} does an indirect lookup as follows:

First it goes into lookup where it finds the value 53 at lookupPosn = 23.

With 53, if finds the low between offset 53 and 0, by calling the script function getMinValueBetween(). It stores the value in def lowAtIndirectLookupPosn;

As you can see, this is very simple indeed - only 38 lines of code!

The problem is, that lowAtIndirectLookupPosn contains the wrong value, as if the wrong branch of the if statement was executed.

plot testResult should put out the low 4.25. Instead it puts out close[offsetLast] which is 6.26.

Quite honestly, this is a disaster because it is impossible to predict which of any if statement in your program will fail or not.


回答1:


In a limited number of cases, the if-expression can be used instead of the if statement. However the if-expression covers only a subset of use cases and it may execute with lower performance in scans. More importantly,

it defeats the purpose of the if statement in an important case



来源:https://stackoverflow.com/questions/58321894/thinkscript-if-statement-failure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!