Thinkscript: Recursive Counter - recursion

I'd like to create a scan in thinkorswim where it returns stocks that have closed higher then when it opened for 4 days or more out of the last 5 days.
This is the current code I have, but I don't know if it is correct or how to limit it to only the last 5 days:
def count = if (close > open) then 1 else 0;
rec counter = counter[1] + count;
plot scan =
counter >= 5;

Here are some alternatives:
Did you want the last 4 or 5 days consecutively to close higher? If so, this option will check for that:
# set aggregation because you want the last 5 days,
# not the last 5 bars regardless of time set
def closeVal = close(period=AggregationPeriod.DAY);
def openVal = open(period=AggregationPeriod.DAY);
# define the condition you want met (it'll check for this on every bar)
def countCondition = closeVal > openVal;
# sum the last 4 bars (days in this case, due to aggregation setting)
# note: the indexes are pointing to the current bar, 1 bar prior, 2 bars prior, and 3 bars prior
# also, each `true` condition will equal 1; `false` is 0
def sumLast4 = countCondition + countCondition[1] + countCondition[2] + countCondition[3];
# ensure last 4 all closed higher than they opened
def last4Condition = (sumLast4 == 4);
# if the last 4 days met the condition, then add in the 5th day prior;
# else, just use the sum of those last 4
def total = if last4Condition then sumLast4 + countCondition[5] else sumLast4;
# plot the final desired condition:
# at least the last 4 days closed higher than their open
plot scan = total >= 4;
If the days closing higher don't need to be consecutive:
# set aggregation because you want the last 5 days, not the last 5 bars
def closeVal = close(period=AggregationPeriod.DAY);
def openVal = open(period=AggregationPeriod.DAY);
# define the condition you want met (it'll check for this on every bar)
def countCondition = closeVal > openVal;
# sum the last 5 bars (days in this case, due to aggregation setting)
# note: each `true` condition will equal 1; `false` is 0
def sumLast5 = countCondition + countCondition[1] + countCondition[2] + countCondition[3] + countCondition[4];
# plot the final desired match
plot scan = sumLast5 > 3;
Using fold, ThinkScript's equivalent of a for loop. This one finds 4 out of the last 5, but not necessarily consecutive:
# set the length - using `input` means you can edit in the scan settings
input length = 5;
# set aggregation because you want the last 5 days, not the last 5 bars
def closeVal = close(period=AggregationPeriod.DAY);
def openVal = open(period=AggregationPeriod.DAY);
# declare a `counter` variable, but we'll set its value in the `if` statement
def counter;
# ensure all data is available by checking to see if the 5th bar back is a number
if !isNaN(closeVal[length - 1]){
# we have a number, so let's fold...
# `with count = 0` initializes a variable called `count` to 0
# for i = 0 to length... (i will go 0 thru 4; it ends when it sees 5)
# if closeVal[i] (the closeVal i bars back) is less than openVal[i]
# then `count = count + 1` else `count` just remains the same as it last was
# when the loop is done, put the `count` value into the `counter` variable
counter = fold i = 0 to length with count = 0 do if getValue(closeVal, i) > getValue(openVal, i) then count + 1 else count;
}
else {
# if the 5th bar back wasn't a number, we can't calculate
# so, simply set the counter to indicate it's Not a Number
counter = Double.NaN;
}
plot scan = counter > 3;
*edited to clarify that a true value equals 1, while a false value equals 0

easy way:
#comment: declare five Booleans for each of five days
def candle1 = close[5] > open[5];
def candle2 = close[4] > open[4];
def candle3 = close[3] > open[3];
def candle4 = close[2] > open[2];
def candle5 = close[1] > open[1];
#
#comment: add up all the green candles(value == 1) and red candles(value == 0)
def sumofgreencandles = candle1 + candle2 + candle3+ candle4 + candle5;
#
#comment: return one if 4 or five candles are green, zero if 3 or fewer are green-
plot fouroffivegreen= if sumofgreencandles > 3 then low else double.nan;
#
#comment: add an arrow to graph where condition exists:
fouroffivegreen.setpaintingstrategy(paintingstrategy.arrow_UP);
fouroffivegreen.setdefaultcolor(color.cyan);
This will place a cyan colored arrow under any bar or point where at least the last four of five periods closed higher than open. I know it looks clunky, but if you use a fold statement, it is much slower and will delay the rendering of your charts.

Related

Function that will return the biggest number of consecutive 0's

For a homework problem, in python we are asked to define in a recursive way a function that will return the biggest number of consecutive 0's in binary for any the number n. We need to use "&" and ">>".
For example, the function should return 2 for n = 44 because its binary representation is 101100.
I do not know where to go from here. Any help would be appreciated!
def max_consecutive_zero_iterative(n):
res = 0
streak = 0
while n > 0:
if n & 1:
streak = 0
else:
streak += 1
n = n >> 1
res = max(res, streak)
return res
def max_consecutive_zero_recursive(n):
if n == 0: # end of recursion
return 0
value = max_consecutive_zero_recursive(n >> 1) # call to recursive
current_streak = value & 0xff # current streak is stored in the lowest 8 bits
longest_streak = value >> 8 # longest streak is stored in the upper bits
if n & 1: # if we have a bit set
return max(longest_streak, current_streak) << 8 # we just return the max value between current_streak and longest_streak, stored in upper bits
# else if the bit is not set
current_streak += 1 # we increase our current streak by 1
# and return the max between the longest_streak and current_streak in the upper bits...
return max(longest_streak, current_streak) << 8 | current_streak
# ... but this time we keep information (we don't reset) about the current_streak stored in the lowest 8 bits.
def main():
print(max_consecutive_zero_recursive(0b1000101111000110000000100110) >> 8)
if __name__ == "__main__":
main()

Number of action per year. Combinatorics question

I'm writing a diploma about vaccines. There is a region, its population and 12 month. There is an array of 12 values from 0 to 1 with step 0.01. It means which part of population should we vaccinate in every month.
For example if we have array = [0.1,0,0,0,0,0,0,0,0,0,0,0]. That means that we should vaccinate 0.1 of region population only in first month.
Another array = [0, 0.23,0,0,0,0,0,0, 0.02,0,0,0]. It means that we should vaccinate 0.23 of region population in second month and 0.02 of region population in 9th month.
So the question is: how to generate (using 3 loops) 12(months) * 12(times of vaccinating) * 100 (number of steps from 0 to 1) = 14_400 number of arrays that will contain every version of these combinations.
For now I have this code:
for(int month = 0;month<12;month++){
for (double step = 0;step<=1;step+=0.01){
double[] arr = new double[12];
arr[month] = step;
}
}
I need to add 3d loop that will vary number of vaccinating per year.
Have no idea how to write it.
Idk if it is understandable.
Hope u get it otherwise ask me, please.
You have 101 variants for the first month 0.00, 0.01..1.00
And 101 variants for the second month - same values.
And 101*101 possible combinations for two months.
Continuing - for all 12 months you have 101^12 variants ~ 10^24
It is not possible to generate and store so many combinations (at least in the current decade)
If step is larger than 0.01, then combination count might be reliable. General formula is P=N^M where N is number of variants per month, M is number of months
You can traverse all combinations representing all integers in range 0..P-1 in N-ric numeral system. Or make digit counter:
fill array D[12] with zeros
repeat
increment element at the last index by step value
if it reaches the limit, make it zero
and increment element at the next index
until the first element reaches the limit
It is similar to counting 08, 09, here we cannot increment 9, so make 10 and so on
s = 1
m = 3
mx = 3
l = [0]*m
i = 0
while i < m:
print([x/3 for x in l])
i = 0
l[i] += s
while (i < m) and l[i] > mx:
l[i] = 0
i += 1
if i < m:
l[i] += s
Python code prints 64 ((mx/s+1)^m=4^3) variants like [0.3333, 0.6666, 0.0]

How to calculate elements needed from a loop?

I have the following data:
y-n-y-y-n-n-n
This repeats infinitely, such as:
y-n-y-y-n-n-n-y-n-y-y-n-n-n-y-n-y-y-n-n-n...
I have 5 "x".
"x" only sticks with "y".
Meaning, if I distribute x on the loop above, it will be:
y-n-y-y-n-n-n-y-n-y-y-n-n-n
x---x-x-----x-x
I want to count how many of the loop's element I needed to use to spread 5 x across, and the answer is 10.
How do I calculate it with a formula?
I presume what you're saying is that you need to process the first 10 elements of the infinite list to get 5 Y's, which match/stick with the 5 X's you have.
y-n-y-y-n-n-n-y-n-y-y-n-n-n-y-n-y-y-n-n-n...
x-_-x-x-_-_-_-x-_-x
^
L____ 10 elements read from the infinite list to place the 5 x's.
I also presume that your question is: given an input of 5 Xs, what is the number of elements you need to process in the infinite list to match those 5 Xs.
You could calculate it with a loop like the following pseudo-code:
iElementsMatchedCounter = 0
iXsMatchedCounter = 0
iXLimit = 5
strElement = ""
if (InfiniteList.IsEmpty() == false)
{
do
{
strElement = InfiniteList.ReadNextElement()
if (strElement == "y")
{
iXsMatchedCounter += 1
}
iElementsMatchedCounter += 1
} while ( (InfiniteList.IsEndReached() == false) AND (iXsMatchedCounter < iXLimit) )
}
if (iXsMatchedCounter = iXLimit)
then Print(iElementsMatchedCounter)
else Print("End of list reached before all X's were matched!")
The drawback of the above approach is that you are actually reading the infinite list, which might not be preferable.
Instead, given you know your list is an infinitely repeating sequence of the same elements y-n-y-y-n-n-n, you don't even need to loop through the entire list, but just operate on the sub-list y-n-y-y-n-n-n. The following algorithm describes how:
Given your starting input:
iNumberOfXs = 5 (you have 5 Xs to match)
iNumberOfYsInSubList = 3
(you have 3 Ys in the sub-list, the total list repeats infinitely)
iLengthOfSubList = 7 (you have 7 elements in the sub-list
y-n-y-y-n-n-n)
We then have intermediate results which are calculated:
iQuotient
iPartialLengthOfList
iPendingXs
iPendingLengthOfList
iResult
The following steps should give the result:
Divide the iNumberOfXs by iNumberOfYsInSubList. Here, this gives us 5/3 = 1.666....
Discard the remainder of the result (the 0.666...), so you're left with 1 as iQuotient. This is the number of complete sub-lists you have to iterate.
Multiply this quotient 1 with iLengthOfSubList, giving you 1*7=7 as iPartialLengthOfList. This is the partial sum of the result, and is the number of elements in the complete sub-lists you iterate.
Also multiply the quotient with iNumberOfYsInSubList, and subtract this product from iNumberOfXs, i.e. iNumberOfXs - (iQuotient * iNumberOfYsInSubList) = 5 - (1 * 3) = 2. Save this value 2 as iPendingXs, which is the number of as-yet unmatched X's.
Note that iPendingXs will always be less than iLengthOfSubList (i.e. it is a modulo, iPendingXs = iNumberOfXs MODULO iNumberOfYsInSubList).
Now you have the trivial problem of matching 2 X's (i.e. the value of iPendingXs calculated above) in the sub-list of y-n-y-y-n-n-n.
The pending items to match (counted as iPendingLengthOfList) is:
Equal to iPendingXs if iPendingXs is 0 or 1
Equal to iPendingXs + 1 otherwise (i.e. if iPendingXs is greater than 1)
In this case, iPendingLengthOfList = 3, because iPendingXs is greater than 1.
The sum of iPartialLengthOfList (7) and iPendingLengthOfList (3) is the answer, namely 10.
In general, if your sub-list y-n-y-y-n-n-n is not pre-defined, then you cannot hard-code the rule in step 6, but will instead have to loop through only the sub-list once to count the Ys and elements, similar to the pseudo-code given above.
When it comes to actual code, you can use integer division and modulo arithmetic to quickly to the operations in steps 2 and 4 respectively.
iQuotient = iNumberOfXs / iNumberOfYsInSubList // COMMENT: here integer division automatically drops the remainder
iPartialLengthOfList = iQuotient * iLengthOfSubList
iPendingXs = iNumberOfXs - (iQuotient * iNumberOfYsInSubList)
// COMMENT: can use modulo arithmetic like the following to calculate iPendingXs
// iPendingXs = iNumberOfXs % iNumberOfYsInSubList
// The following IF statement assumes the sub-list to be y-n-y-y-n-n-n
if (iPendingXs > 1)
then iPendingLengthOfList = iPendingXs + 1
else iPendingLengthOfList = iPendingXs
iResult = iPartialLengthOfList + iPendingLengthOfList

Python Programming While Loop

Hi I'm new to python and programming in general. I am trying write a program that uses a while loop to add integers from 1 to the number entered. the program also has to give an error statement if the user enters a 0 or negative number. So far the integers add up and the error statement works but the program is not looping, it only asks the user to input a number one time. Please help. This is my source code so far. Thanks
x = int(input("Enter a positive number not including zero:" ))
total = 0
n = 1
while n <= x:
total = total + n
n = n + 1
# prints the total of integers up to number entered
print("Sum of integers from 1 to number entered= ",total)
if x <= 0 or x == -x:
print ("invalid entry")
Try this code...
op='y'
while op=='y':
x = int(input("Enter a positive number not including zero:" ))
total = 0
n = 1
if x > 0:
while n <= x:
total = total + n
n = n + 1
# prints the total of integers up to number entered
print("Sum of integers from 1 to number entered= ",total)
else:
print ("invalid entry")
op = raw_input("Are you want to continue this operation (y/n):" )
Put your whole code this way
done = False
while not done:
//your entire code here except the last 2 lines
if x > 0:
done = True

How to find the range for a given number, interval and start value?

Provided the below values
start value = 1
End Value = 20
Interval = 5
I have been provided a number 6. I have to find the range of numbers in which the number 6 falls say now the answer is 6-10.
If the given number is greater than the end value then return the same number.
Is there any formula so that i can generate the range for the number?
UPDATE
I tried the below solution, But it is not working if the range interval is changed,
$end_value = $start_value + $range_interval;
// we blindly return the last term if value is greater than max value
if ($input_num > $end_value) {
return '>' . $end_value;
}
// we also find if its a first value
if ($input_num <= $end_value && $value >= $start_value) {
return $start_value . '-' . $end_value;
}
// logic to find the range for a given integer
$dived_value = $input_num/$end_value;
// round the value to get the exact match
$rounded_value = ceil($dived_value);
$upper_bound_range = $rounded_value*$end_value;
$lower_bound_range = $upper_bound_range - $end_value;
return $lower_bound_range . '-'. $upper_bound_range;
In (c-style) pseudocode:
// Integer division assumed
rangeNumber = (yourNumber - startValue) / rangeLength;
lower_bound_range = startValue + rangeNumber*rangeLength;
upper_bound_range = lower_bound_range + rangeLength-1;
For your input:
rangeNumber = (6-1)/5 = 1
lower_bound_range = 1 + 5*1 = 6
upper_bound_range = 10
and so range is [6, 10]
The answer depends on whether you talk about integers or floats. Since all your example numbers are integers, I assume you talk about those. I further assume that all your intervals contain the same number of integers, in your example 5, namely 1...5, 6...10, 11...15, and 16...20. Note that 0 is not contained in the 1st interval (otherwise the 1st interval had 6 numbers).
In this case the answer is easy.
Let be:
s the start value that is not contained in the 1st interval,
i the interval size, i.e. the number of integers that it contains,
p the provided number to which an interval should be assigned,
b the 1st integer in this interval, and
e the last integer in this interval.
Then:
b = s + (p-s-1)\i * i + 1 (here, "\" means integer division, i.e. without remainder)
e = b + i - 1
In your example:
s = 0, i = 5, p = 6, thus
b = 0 + (6-0-1)\5 * 5 + 1 = 6
e = 6 + 5 - 1 = 10

Resources