问题
I'm creating a class based directional indicator that given a number of days (n_days
) and a list of numbers, it gives the (number of numbers out of the most recent n_days
on which the number was higher than the previous number minus the n_days
out of the previous n_days
on which the number went down). So if the number in the list increases I want it to return +1
, if it decreases I want it to return -1
, otherwise it should be 0
so the first number should always be 0
since you can't compare it to anything. Then based on n_days
I basically want to take the sum of the of the recent n_days, so for example in a list of [1,2,2,1,2,1]
the change should be [0,+1,0,-1,1,-1]
and if I want the sum of the change in the 2 recent numbers for each day so it should be [0,+1,-1,0,+1,0]
because on the first day there is only 0, on the second day you take the sum of the most recent two days 0+(+1)=1
, the third day (+1)+0=+1
, the fourth day 0+(-1)=-1
and so forth. Here is my code that's not working:
class Directionalindicator():
def __init__(self, n_days, list_of_prices):
self.n_days = n_days
self.list_of_prices = list_of_prices
def calculate(self):
change = []
for i in range(len(self.list_of_prices)):
if self.list_of_prices[i-1] < self.list_of_prices[i]:
change.append(1)
elif self.list_of_prices[i-1] > self.list_of_prices[i]:
change.append(-1)
else:
change.append(0)
directional = []
for i in range(len(change)):
directional.append(sum(change[i+1-self.n_days:i+1]))
return directional
testing it with:
y = Directionalindicator(2,[1,2,2,1,2,1])
y.calculate()
should return:
[0,+1,+1,-1,0,0]
and it does.
But testing it with:
y = Directionalindicator(3, [1,2,3,4,5,6,7,8,9,10])
y.calculate()
should return
[0, 0, 2, 3, 3, 3, 3, 3, 3, 3]
but it returns
[0, 0, 1, 3, 3, 3, 3, 3, 3, 3]
I printed change to see what it was doing and the first value is a -1 instead of a 0. Also, the code in one of the answers works using zip, but I don't understand why mine doesn't work for that list from 1-10.
回答1:
Your comparison
i > i-1
will always be True
. You are comparing each price to itself minus one, which will always be smaller. Instead, you should be comparing pairs of prices. zip
is useful for this:
change = [0] # first price always zero change
for a, b in zip(self.list_of_prices, self.list_of_prices[1:]):
if a < b: # price went up
change.append(1)
elif a > b: # price went down
change.append(-1)
else: # price stayed the same
change.append(0)
When you plug this into your code and use your example
Directionalindicator(2, [1, 2, 2, 1, 2, 1])
you get:
change == [0, 1, 0, -1, 1, -1]
directional == [0, 1, 1, -1, 0, 0]
This seems to be correct according to your initial statement of the rules, but for some reason doesn't match your "expected output" [0, 1, -1, 0, 1, 0]
from the end of your question.
The reason your edit doesn't work is that you are using an index i
on the list. When i == 0
, i-1 == -1
. When used as an index list_of_prices[-1]
, this gives you the last element in the list. Therefore change
contains [-1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
, as it compares 1
with 10
, not [0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
as you expected.
来源:https://stackoverflow.com/questions/21850041/class-based-directional-indicator