thinkscript scan debugging


Category:
0
0

There is some good news, we can debug scan code by using the plot statement to let the scan engine test a condition. We see that the condition is true if the results are the full set of symbols. Example:

<pre>

input offset = 0;
def sum = 1;
plot scan = GetValue(sum, BarNumber() -1 + offset) == 1;

<pre>

The plot statement gets executed once only at the last bar – therefore it always works as expected.

The interesting part when we discover a bug, mainly when our test fails (expected vs actual value).

Failing example:

<pre>

input offset = 0;
def sum;
if (BarNumber() == 1) {
sum = 1;
} else {
if (BarNumber() < 5) {
sum = sum[1] + 1;
} else {
sum = sum[1]; # This causes the problem.
#sum = Double.NaN;# alternative: does not corrupt previous value but useless.
}
}
plot scan = GetValue(sum, BarNumber() -1 + offset) == 1;

</pre>

This is interesting because this discovers a bug in the scan engine not a bug in our code. WE see that simply reading the previous value of <pre>sum</pre> changes its value.

I have tried to discuss this with Ameritrade which is difficult because they usuallly take a week to respond. Therefore, a real dialog is not possible.

I am urging thinkscript scan developers to review this  and try to increase AmeriTrade’s awareness of the problem. I hope this helps a little with your own scan efforts.

 

Marked as spam
Posted by (Questions: 3, Answers: 7)
Asked on June 25, 2019 11:20 am
962 views
1
Private answer

We have a workaround:

GetValue(sum1, 1) as a replacement of sum1[1].

We now have definite proof that my test case exposes a thinkscript bug. There should be no need to use dynamic indexing with GetValue() because [1] uses a constant.

So it pays to be exact and thorough (testing variable content using the plot statement in a scan).

I was getting sick of the nonsense responses from Ameritrade.

Whether this workaround is actually stable and generally applicable is still an open question.


input offset = 0;
def sum1;
if (BarNumber() == 1) {
sum1 = 1;
} else {
if (BarNumber() >= 5) {
#sum1 = GetValue(sum1, 1); # Workaround
sum1 = sum1[1]; # This causes the problem.
} else {
sum1 = sum1[1] + 1;
}
}
plot scan = GetValue(sum1, BarNumber() -1 + offset) == 1;

Marked as spam
Posted by (Questions: 3, Answers: 7)
Answered on June 28, 2019 6:55 am
While the first value of sum1 is no longer corrupted, which is an improvement, subsequent values are 0, so no assignment occurs with sum1 = GetValue(sum1, 1), and no computation occurs with sum1 = GetValue(sum1, 1) + 1. Nothing works.
( at June 28, 2019 10:37 am)
0
Private answer

I believe this issue is addressed when you convert your recursive variable, sum, to a CompoundValue() statement.

Details here: http://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Others/CompoundValue.html

This is the code I ended up with after debugging the code to make sure it works:

input offset = 0;
rec sum = CompoundValue(1, if BarNumber() == 1 then 1 else if BarNumber() < 5 then sum[1] + 1 else sum[1], 1);
plot scan = GetValue(sum, BarNumber() -1 + offset) == 1;

Marked as spam
Posted by (Questions: 39, Answers: 3711)
Answered on June 26, 2019 1:25 pm
You are successfully using the test method, the plot statement as provided. You are using it to verify different code to solve a problem that isn't really the problem. Sure you have solved that trivial problem. But I think we have a misunderstanding. The CompoundValue() function is applicable of course in this simple test case. However it works only with a single result. Like the if() function works only with a single result. Therefore we have the if statement for more complex scenarios. It is like saying we no longer are allowed to use the if statement, we should always use the if() function because the if statement has a bug as I showed. In other words, there should always be an if statement equivalent of the CompoundValue() function.
( at June 26, 2019 2:53 pm)
I will admit that I never run across this issue in my coding. Perhaps because I am used to applying the tools in a way that avoids this and other so-called bugs. In this example I applied the same exact nested if statement as you have done. So we are not limited to a single if statement when we apply the CompoundValue() statement. Given that I found a way to make this work using CompoundValue(), I believe the problem you are experiencing is that your recursion is failing to initialize properly. Therefore it is creating a N/A result instead of a numerical value. Perhaps you can find a way to restructure your nested if statement to ensure the recursive variables are properly initialized? That's about all I have to say on the topic. I do tons and tons of custom projects and never run into this.
( at June 26, 2019 3:50 pm)
I am glad that you confirm this is actually an issue. You provide a workaround that works with a specific coding style which I cannot use in my application. I need the ”if” statement not the ”if()” function, and I cannot replace that ”if” statement with the CompoundValue() function except in this trivial case which is a test case not an actual application problem. That is because, with my coding style, I need multiple statements in the if(){}else{} construct. I also need to initialize multiple variables in the first branch. CompoundValue() as a function is limited to a single output value. I cannot split my code up into multiple CompoundValue() root nodes – one for each variable to initialize – just for the sake of using this type of initialization. In other words, CoupoundValue() does NOT solve all initialization problems. It sounds convincing what you say that thinkscript fails to initialize with my approach. I have seen this problem pop up in so many scenarios it is not funny. The above may explain why this issue is not present in most basic scenarios. Another reason is that a scan as opposed to a chart study always uses the full amount of data so there is no data beyond the left edge to pre-fetch. But my code is not pre-fetching. I am not asking for a solution here because I think it is too hard and frustrating. Thanks for your advice though. I am just highlighting the issue here so others using this style may find it easier to go back to Ameritrade and ask for a bug fix. Apart from that, I think to see this problem unfold, to see that this unthinkable result is even possible in any programming language, is very interesting and intriguing. Also, the facts should be reason enough for Ameritrade to at least document this effect in a documentation page. And this example code is the most basic code I could produce to show that defect.
( at June 28, 2019 2:11 am)
The code implements a counter. The 2nd value at offset = 1 should be 2. It is 0. So far, nothing on this page works. It really pays to check the results.
( at June 29, 2019 6:19 pm)