I've found some solutions using the triangle area to find lines but It's not what I need because in further steps will not be a solution for my problem.
I've been working on a nested loop where I see the slope between point 0 and 1 and gives me a projection for next points (expexcted price for each point) If the price is the same - tolerance I have found a line.
Now I've the first loop returning me Slopes but I'm struggling with the second loop to get the exp_price comparision... Any idea on how to find this lines simple?
initial_data = {'index': [4, 17, 24, 36, 42],
'High': [805.000000, 1094.939941, 1243.489990, 1201.949951, 1172.839966],
}
test = pd.DataFrame(initial_data)
slope_data = {'index': [4, 17, 24, 36, 42],
'High': [805.000000, 1094.939941, 1243.489990, 1518.7, 1172.839966],
'Slope': [0, 22.30307, 21.22144, 22.93417, -57.64334],
}
The nested loop is an option, but maybe is an easiest way vecotrizing to know which 3 are a line?
for i in range(len(test)):
#test.loc[:,'slope'] = (test.loc[i,'High'] - test.loc[i,'High']) / (test.loc[i,'index'] - test.loc[i,'index'])
test['slope'] = round((test['High']-test['High'].shift(1)) / (test['index']-test['index'].shift(1)),8)
print(test)
for j in range(len(test)):
exp_price = (test['High'].shift(1) (test['slope']*(test['index']-test['index'].shift(j))))
#If exp_price of j equals High of i ( - 0,5% tolerance) I've found a line!
# print(values)
test['result'] = values
print(test)
Note I want to compare 0,1 with 2, 3 and 4.
0, 2 with 3, 4.
0, 3 with 4.
1, 2 with 3, 4.
and so on... That's why I try to use the nested loop.
CodePudding user response:
You can do this:
coords = list(zip(test['index'], test.High))
slope = pd.DataFrame([[(coly - rowy)/(colx - rowx) if colx > rowx else None for colx, coly in coords] for rowx, rowy in coords], columns=coords, index=coords)
pointsAndCandidate = [(i, j, k) for i in range(len(test.index) - 2) for j in range(i 1, len(test.index) - 1) for k in range(j 1, len(test.index))]
df3 = pd.DataFrame(columns=[
'linex','liney','candx','candy', 'slope'], index = pointsAndCandidate, data = [
(*coords[row[1]], *coords[row[2]], slope.iloc[
row[0], row[1]]) for row in pointsAndCandidate])
df3['projy'] = df3.liney df3.slope * (df3.candx - df3.linex)
df3['inline'] = (df3.candy / df3.projy - 1).abs() < 0.01
print(df3)
Output:
linex liney candx candy slope projy inline
(0, 1, 2) 17 1094.939941 24 1243.489990 22.303072 1251.061448 True
(0, 1, 3) 17 1094.939941 36 1201.949951 22.303072 1518.698316 False
(0, 1, 4) 17 1094.939941 42 1172.839966 22.303072 1652.516751 False
(0, 2, 3) 24 1243.489990 36 1201.949951 21.924500 1506.583984 False
(0, 2, 4) 24 1243.489990 42 1172.839966 21.924500 1638.130981 False
(0, 3, 4) 36 1201.949951 42 1172.839966 12.404686 1276.378067 False
(1, 2, 3) 24 1243.489990 36 1201.949951 21.221436 1498.147217 False
(1, 2, 4) 24 1243.489990 42 1172.839966 21.221436 1625.475830 False
(1, 3, 4) 36 1201.949951 42 1172.839966 5.632106 1235.742586 False
(2, 3, 4) 36 1201.949951 42 1172.839966 -3.461670 1181.179932 True
Explanation:
- Create a dataframe containing the slopes of pairs of interest in the upper diagonal
- Create a list of all index combinations of interest:
point1, point2, candidate
; for the example in the question, this is (0,1,2), (0,1,3), (0,1,4), (0,2,3), (0,2,4), (0,3,4), (1,2,3), (1,2,4), (1,3,4), (2,3,4) - Create a dataframe with columns
linex, liney, candx, candy, slope
which are the x, y coords of one of the points on the line, the coords of the candidate point, and the slope of the line - Add to it the column
projy
which is the projected y coord for the candidate's x coord, and also the columninline
which indicates whethercandy
matchesprojy
within a given tolerance, meaning the candidate is indeed collinear with the two points.
Intermediate results:
test
index High
0 4 805.000000
1 17 1094.939941
2 24 1243.489990
3 36 1201.949951
4 42 1172.839966
coords
[(4, 805.0), (17, 1094.939941), (24, 1243.48999), (36, 1201.949951), (42, 1172.839966)]
slope
(4, 805.0) (17, 1094.939941) (24, 1243.48999) (36, 1201.949951) (42, 1172.839966)
(4, 805.0) None 22.303072 21.924500 12.404686 9.679999
(17, 1094.939941) None NaN 21.221436 5.632106 3.116001
(24, 1243.48999) None NaN NaN -3.461670 -3.925001
(36, 1201.949951) None NaN NaN NaN -4.851664
(42, 1172.839966) None NaN NaN NaN NaN
pointsAndCandidate
[(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
result
linex liney candx candy slope projy inline
(0, 1, 2) 17 1094.939941 24 1243.489990 22.303072 1251.061448 True
(0, 1, 3) 17 1094.939941 36 1201.949951 22.303072 1518.698316 False
(0, 1, 4) 17 1094.939941 42 1172.839966 22.303072 1652.516751 False
(0, 2, 3) 24 1243.489990 36 1201.949951 21.924500 1506.583984 False
(0, 2, 4) 24 1243.489990 42 1172.839966 21.924500 1638.130981 False
(0, 3, 4) 36 1201.949951 42 1172.839966 12.404686 1276.378067 False
(1, 2, 3) 24 1243.489990 36 1201.949951 21.221436 1498.147217 False
(1, 2, 4) 24 1243.489990 42 1172.839966 21.221436 1625.475830 False
(1, 3, 4) 36 1201.949951 42 1172.839966 5.632106 1235.742586 False
(2, 3, 4) 36 1201.949951 42 1172.839966 -3.461670 1181.179932 True