I'm creating a Pine Script version 5 Indicator with a for loop and getting this error: 'if' cannot be used as a variable or function name - for-loop

Here is the script. I believe the issue is the if statement in the for Loop but I don't understand why. Please help me understand what is the issue with the code. Thanks
//#version=5
study("Two Consecutive Engulfing Patterns", overlay=true)
// Define the number of bars to look back for pattern recognition
barsBack = input(title="Number of Bars Back", type=integer, defval=100)
// Define the candle body size for the pattern recognition
bodySize = input(title="Candle Body Size", type=float, defval=0.01)
// Initialize a variable to track the number of bearish or bullish engulfing patterns
count = 0
// Loop through the bars and look for the pattern
for i = 0 to barsBack - 1
if bearish_engulfing(i, bodySize)
count := count + 1
else if bullish_engulfing(i, bodySize)
count := count - 1
else
count := 0
end
// Generate an SMS alert and visual indicator if two consecutive patterns are found
if count == 2
alert("Two Consecutive Bearish Engulfing Patterns", message="Two Consecutive Bearish Engulfing Patterns", type=alert.SMS)
plot(bar_index, close, color=red, linewidth=2)
else if count == -2
alert("Two Consecutive Bullish Engulfing Patterns", message="Two Consecutive Bullish Engulfing Patterns", type=alert.SMS)
plot(bar_index, close, color=green, linewidth=2)
end
I verified there are 4 indented spaces. The end statement in the for loop is highlighted as a area of concern but the error highlights the if statement.

Related

Loop sentences using return

Im trying to loop through sentences and tags_to_label contains array of position of words in the sentence e.g: Adam lemmington ate an apple so tag_to_label = [1 2] position of the nouns in the sentence. Here im trying to return 1 if the length of tags_to_label > 1 else 0 but my code only loops through one sentence, is there a way to loop through all the sentences?
for i, item in enumerate(tags_to_label):
if len(tags_to_label) > 1:
return 1
else:
return 0

Writing a function that returns true if given string has exactly 6 characters

I am trying to write a function that returns true or false if a given string has exactly 6 consecutive characters with the same value. If the string has more or less than 6, it will return false:
I am not allowed to use lists, sets or import any packages. I am only restricted to while loops, for loops, and utilizing basic mathematical operations
Two example runs are shown below:
Enter a string: 367777776
True
Enter a string: 3677777777776
False
Note that although I entered numbers, it is actually a string within the function argument for example: consecutive('3777776')
I tried to convert the string into an ASCII table and then try and filter out the numbers there. However, I
def consecutive(x):
storage= ' '
acc=0
count=0
for s in x:
storage+= str(ord(s)) + ' '
acc+=ord(s)
if acc == acc:
count+=1
for s in x-1:
return count
My intention is to compare the previous character's ASCII code to the current character's ASCII code in the string. If the ASCII doesnt match, I will add an accumulator for it. The accumulator will list the number of duplicates. From there, I will implement an if-else statement to see if it is greater or less than 6 However, I have a hard time translating my thoughts into python code.
Can anyone assist me?
That's a pretty good start!
A few comments:
Variables storage and acc play the same role, and are a little more complicated than they have to be. All you want to know when you arrive at character s is whether or not s is identical to the previous character. So, you only need to store the previously seen character.
Condition acc == acc is always going to be True. I think you meant acc == s?
When you encounter an identical character, you correctly increase the count with count += 1. However, when we change characters, you should reset the count.
With these comments in mind, I fixed your code, then blanked out a few parts for you to fill. I've also renamed storage and acc to previous_char which I think is more explicit.
def has_6_consecutive(x):
previous_char = None
count = 0
for s in x:
if s == previous_char:
???
elif count == 6:
???
else:
???
previous_char = ???
???
You could use recursion. Loop over all the characters and for each one check to see of the next 6 are identical. If so, return true. If you get to the end of the array (or even within 6 characters of the end), return false.
For more info on recursion, check this out: https://www.programiz.com/python-programming/recursion
would something like this be allowed?
def consecF(n):
consec = 1
prev = n[0]
for i in n:
if i==prev:
consec+=1
else:
consec=1
if consec == 6:
return True
prev = i
return False
n = "12111123333221"
print(consecF(n))
You can try a two pointer approach, where the left pointer is fixed at the first instance of some digit and the right one is shifted as long as the digit is seen.
def consecutive(x):
left = 0
while left != len(x):
right = left
while right < len(x) and x[right] == x[left]:
right += 1
length = (right - 1) - left + 1 # from left to right - 1 inclusive, x[left] repeated
if length == 6: # found desired length
return True
left = right
return False # no segment found
tests = [
'3677777777776',
'367777776'
]
for test in tests:
print(f"{test}: {consecutive(test)}")
Output
3677777777776: False
367777776: True
You should store the current sequence of repeated chars.
def consecutive(x):
sequencechar = ' '
repetitions = 0
for ch in x:
if ch != sequencechar:
if repetitions == 6:
break
sequencechar = ch
repetitions = 1
else:
repetitions += 1
return repetitions == 6
If I could, I would not have given the entire solution, but this still is a simple problem. However one has to take care of some points.
As you see the current sequence is stored, and when the sequence is ended and a new starts, on having found a correct sequence it breaks out of the for loop.
Also after the for loop ends normally, the last sequence is checked (which was not done in the loop).

Grouping data using loops (signal processing in MATLAB)

I am working in MATLAB with a signal data that consist of consecutive dips as shown below. I am trying to write a code which sorts the contents of each dip into a separate group. How should the general structure of such a code look like?
The following is my data. I am only interested in the portion of the signal that lies below a certain threshold d (the red line):
And here is the desired grouping:
Here is an unsuccessful attempt:
k=0; % Group number
for i = 1 : length(signal)
if signal(i) < d
k=k+1;
while signal(i) < d
NewSignal(i, k) = signal(i);
i = i + 1;
end
end
end
The code above generated 310 groups instead of the desired 12 groups.
Any explanation would be greatly appreciated.
Taking Benl generated data you can do the following:
%generate data
x=1:1000;
y=sin(x/20);
for ii=1:9
y=y+-10*exp(-(x-ii*100).^2./10);
end
y=awgn(y,4);
%set threshold
t=-4;
%threshold data
Y = char(double(y<t) + '0'); %// convert to string of zeros and ones
%search for start and ends
This idea is taken from here
[s, e] = regexp(Y, '1+', 'start', 'end');
%and now plot and see that each pair of starts and end
% represents a group
plot(x,y)
hold on
for k=1:numel(s)
line(s(k)*ones(2,1),ylim,'Color','k','LineStyle','--')
line(e(k)*ones(2,1),ylim,'Color','k','LineStyle','-')
end
hold off
legend('Data','Starts','Ends')
Comments: First of all I choose an arbitrary threshold, it is up to you to find the "best" one in your data. Additionally I didn't group the data explicitly but rather this approach gives you the start and end of each epoch with a dip (you might call it group). So you could say that each index is the grouping index. Finally I did not debug this approach for corner cases, when dips fall on starts and ends...
In MATLAB you cannot change the loop index of a for loop. A for loop:
for i = array
loops over each column of array in turn. In your code, 1 : length(signal) is an array, each of its elements is visited in turn. Inside this loop there is a while loop that increments i. However, when this while loop ends and the next iteration of the for loop runs, i is reset to the next item in the array.
This code therefore needs two while loops:
i = 1; % Index
k = 0; % Group number
while i <= numel(signal)
if signal(i) < d
k = k + 1;
while signal(i) < d
NewSignal(i,k) = signal(i);
i = i + 1;
end
end
i = i + 1;
end
Easy, the function you're looking for is bwlabel, which when combined with logical indexing makes this simple.
To start I made some fake data which resembled your data
x=1:1000;
y=sin(x/20);
for ii=1:9
y=y+-10*exp(-(x-ii*100).^2./10);
end
y=awgn(y,4);
plot(x,y)
Then set your threshold and use 'bwlabel'
d=-4;% set the threshold
groupid=bwlabel(y<d);
bwlabel labels connected groups in a black and white image, what we've effectively done here is make a black and white (logical 0 & 1) 1D image in the logical vector y<d. bwlabel returns the number of the region at the index of the region. We're not interested in the 0 region, so to get the x values or y values of the nth region, simply use x(groupid==n), for example with my test data
x_4=x(groupid==4)
y_4=y(groupid==4)
x_4 = 398 399 400 401 402
y_4 = -5.5601 -7.8280 -9.1965 -7.9083 -5.8751

Creating a checkerboard using Ruby and "\n" not disappearing

I feel as if I am close to a solution and have been tinkering around with this as a newb for some time. Why, for some reason, are my "\n"'s not disappearing when outputted for "next line" and the output has unneeded white space?
Task: Write a function which takes one parameter representing the dimensions of a checkered board. The board will always be square, so 5 means you will need a 5x5 board.
The dark squares will be represented by a unicode white square, while the light squares will be represented by a unicode black square (the opposite colors ensure the board doesn't look reversed on code wars' dark background). It should return a string of the board with a space in between each square and taking into account new lines.
An even number should return a board that begins with a dark square. An odd number should return a board that begins with a light square.
The input is expected to be a whole number that's at least two, and returns false otherwise (Nothing in Haskell).
I am close, and here is what I have so far:
def checkered_board(dimension)
black = "\u25A1 "
white = "\u25A0 "
checkboard = nil
checker_array = []
if dimension < 2 or dimension.is_a? String
return false
else
count = dimension
while count <= dimension && count > 0
if count % 2 == 0
checkboard = ("\u25A1 \u25A0" + "\n")
checker_array << checkboard
count -= 1
else
checkboard = ("\u25A0 \u25A1" + "\n")
checker_array << checkboard
count -= 1
end
end
end
checkboard = checker_array.join(" ")
p checkboard
end
Here is the TDD specs:
Test.assert_equals(checkered_board(0), false)
Test.assert_equals(checkered_board(2), "\u25A1 \u25A0\n\u25A0 \u25A1")
Note: Hidden specs demonstrate that it should respond with false if dimension is not an integer. .is_a? String and .is_a? Integer is not working for me too.
Output appears like so, and is not appearing even:
□ ■
■ □
Thanks for any and all help :).
Try changing:
if dimension < 2 or dimension.is_a? String
to
if !dimension.is_a?(Integer) || dimension < 2
The left most test will be done first. At the moment, if dimension is a String, it is first compared with 2 - which will raise an error - before it is tested as to whether it is a String. You need to check the type of object before you compare it with another object.
Also, I think the check should be whether dimension is not an Integer, rather than whether it is a String. For example, in your original code, what would happen if dimension was an Array?
The join method will concatenate the elements with a space character inserted between them. So this line from the program:
checkboard = checker_array.join(" ")
will result in this string:
"\u25A1 \u25A0\n \u25A0 \u25A1"
Omitting the argument to join should produce the expected output, ie.:
checkboard = checker_array.join
Refer to the documentation on the Array join method.

Word search algorithm using an m.file

I have already implemented my algorithm using cells of multiple strings on Matlab, but I can't seem to do it through reading a file.
On Matlab, I create cells of strings for each line, let's call them line.
So I get
line= 'string1' 'string2' etc
line= 'string 5' 'string7'...
line=...
and so on. I have over 100s of lines to read.
What I'm trying to do is compare the words from to the first line to itself.
Then combine the first and second line, and compare the words in the second line to the combined cell. I accumulate each cell I read and compare with the last cell read.
Here is my code on
for each line= a,b,c,d,...
for(i=1:length(a))
for(j=1:length(a))
AA=ismember(a,a)
end
combine=[a,b]
[unC,i]=unique(combine, 'first')
sorted=combine(sort(i))
for(i=1:length(sorted))
for(j=1:length(b))
AB=ismember(sorted,b)
end
end
combine1=[a,b,c]
.....
When I read my file, I create a while loop which reads the whole script until the end, so how I can I implement my algorithm if all my cells of strings have the same name?
while~feof(fid)
out=fgetl(fid)
if isempty(out)||strncmp(out, '%', 1)||~ischar(out)
continue
end
line=regexp(line, ' ', 'split')
Suppose your data file is called data.txt and its content is:
string1 string2 string3 string4
string2 string3
string4 string5 string6
A very easy way to retain only the first unique occurrence is:
% Parse everything in one go
fid = fopen('C:\Users\ok1011\Desktop\data.txt');
out = textscan(fid,'%s');
fclose(fid);
unique(out{1})
ans =
'string1'
'string2'
'string3'
'string4'
'string5'
'string6'
As already mentioned, this approach might not work if:
your data file has irregularities
you actually need the comparison indices
EDIT: solution for performance
% Parse in bulk and split (assuming you don't know maximum
%number of strings in a line, otherwise you can use textscan alone)
fid = fopen('C:\Users\ok1011\Desktop\data.txt');
out = textscan(fid,'%s','Delimiter','\n');
out = regexp(out{1},' ','split');
fclose(fid);
% Preallocate unique comb
comb = unique([out{:}]); % you might need to remove empty strings from here
% preallocate idx
m = size(out,1);
idx = false(m,size(comb,2));
% Loop for number of lines (rows)
for ii = 1:m
idx(ii,:) = ismember(comb,out{ii});
end
Note that the resulting idx is:
idx =
1 1 1 1 0 0
0 1 1 0 0 0
0 0 0 1 1 1
The advantage of keeping it in this form is that you save on space with respect to a cell array (which imposes 112 bytes of overhead per cell). You can also store it as a sparse array to potentially improve on storage costs.
Another thing to note, is that even if the logical array is longer than the e.g. double array which is indexing, as long as the exceeding elements are false you can still use it (and by construction of the above problem, idx satisfies this requirement).
An example to clarify:
A = 1:3;
A([true false true false false])

Resources