ПРОБЛЕМА
Я работаю над функцией Pandas и обнаружил, что мой список ATR_l добавляется в мой фрейм данных на 1 строку позже, чем мне бы хотелось.
В частности, в столбце Выходной сигнал ATR результат 0,457500 должен быть в строке индекса 13, а не в 14 и т. Д.
Кроме того, что вычисления дают правильные результаты!
УСТРАНЕНИЕ НЕИСПРАВНОСТЕЙ
Сначала я подумал, что это может быть проблема с индексом между моим фреймом данных и списком ATR_l, однако print(i, ATR_l)
показывает правильное значение ATR_l при i (13)
Я также заметил первое значение ATR_l в нулевом списке ATR_l, чего я не ожидал.Из того, что я могу сказать, это генерируется, когда я define
ATR_l в ATR_l = [0]
и вызывает отставание строки на выходе ATL_l.
Когда я определяю пустой список ATR_l = []
, я получаю ошибку, выданную в df['ATR'] = ATR_l
с ValueError: Length of values does not match length of index
Какие есть варианты удалить или не добавлять этот ноль в список в первую очередь?
К вашему сведению - с использованием Python 3.6
КОД
def ATRpd():
data = pd.read_csv('data.txt', sep=",", header=0)
df = data
n = 14
i = 0
TR_l = [0]
ATR_l = [0]
while i < df.index[-1]:
TR = max(df.at[i + 1, 'High'], df.at[i, 'Close']) - min(df.at[i + 1, 'Low'], df.at[i, 'Close'])
TR_l.append(round(TR,3))
i = i + 1
df['TR'] = TR_l
df['MA'] = round(df.TR.rolling(n).mean(),4)
i = 0
while i < df.index[-1]:
if i <= n - 1:
ATR = df.at[i, 'MA']
elif i > n - 1:
ATR = (ATR * 13 + df.at[i, 'TR']) / 14
ATR_l.append(round(ATR,6))
if i < 20:
# print(i, ATR)
print(i, ATR_l)
i = i + 1
df['ATR'] = ATR_l
print(df.head(20))
ВЫХОД
ASXCode DateValue Open High ... Close TR MA ATR
0 BHP 26/09/2016 21.47 21.670 ... 21.55 0.000 NaN 0.000000
1 BHP 27/09/2016 21.35 21.520 ... 21.50 0.380 NaN NaN
2 BHP 28/09/2016 21.21 21.460 ... 21.39 0.295 NaN NaN
3 BHP 29/09/2016 22.22 22.540 ... 22.40 1.150 NaN NaN
4 BHP 30/09/2016 22.45 22.550 ... 22.38 0.440 NaN NaN
5 BHP 3/10/2016 22.61 22.870 ... 22.75 0.490 NaN NaN
6 BHP 4/10/2016 22.75 22.900 ... 22.90 0.200 NaN NaN
7 BHP 5/10/2016 22.74 22.950 ... 22.85 0.280 NaN NaN
8 BHP 6/10/2016 23.15 23.260 ... 23.12 0.410 NaN NaN
9 BHP 7/10/2016 23.20 23.400 ... 23.30 0.400 NaN NaN
10 BHP 10/10/2016 23.40 23.630 ... 23.40 0.330 NaN NaN
11 BHP 11/10/2016 23.73 23.870 ... 23.80 0.470 NaN NaN
12 BHP 12/10/2016 23.18 23.440 ... 23.44 0.790 NaN NaN
13 BHP 13/10/2016 23.11 23.220 ... 22.75 0.770 0.4575 NaN
14 BHP 14/10/2016 22.34 22.590 ... 22.54 0.460 0.4904 0.457500
15 BHP 17/10/2016 22.35 22.620 ... 22.39 0.330 0.4868 0.457679
16 BHP 18/10/2016 22.30 22.660 ... 22.64 0.420 0.4957 0.448559
17 BHP 19/10/2016 22.50 22.530 ... 22.47 0.600 0.4564 0.446519
18 BHP 20/10/2016 22.58 23.025 ... 22.85 0.555 0.4646 0.457482
19 BHP 21/10/2016 22.96 23.260 ... 23.04 0.410 0.4589 0.464447
Выход ATR_l
0 [0, nan]
1 [0, nan, nan]
2 [0, nan, nan, nan]
3 [0, nan, nan, nan, nan]
4 [0, nan, nan, nan, nan, nan]
5 [0, nan, nan, nan, nan, nan, nan]
6 [0, nan, nan, nan, nan, nan, nan, nan]
7 [0, nan, nan, nan, nan, nan, nan, nan, nan]
8 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan]
9 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
10 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
11 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
12 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
13 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575]
14 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575, 0.457679]
15 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575, 0.457679, 0.448559]
16 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575, 0.457679, 0.448559, 0.446519]
17 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575, 0.457679, 0.448559, 0.446519, 0.457482]
18 [0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0.4575, 0.457679, 0.448559, 0.446519, 0.457482,
РЕШЕНИЕ 1
Основываясь на замечательных советах из YPadawan
, приведенных ниже, я смог исправить исходную проблему с кодом, добавив +1
к df.index[-1]+1:
расчета ATR.
i = 0
while i < df.index[-1]+1:
if i <= n - 1:
ATR = df.at[i, 'MA']
elif i > n - 1:
ATR = (ATR * 13 + df.at[i, 'TR']) / 14
ATR_l.append(round(ATR,6))
РЕШЕНИЕ 2
Принимая во внимание совет избегать итерации и необходимо использовать iterrows()
, если это необходимо, я нашел следующее рабочее решение, которое мне гораздо большеЯ краткий и легкий для понимания.
Единственное, что я размышляю, - могу ли я избежать итерации ATR.
Я полагаю, что у меня нет выбора, так как мне нужно сослаться на предыдущий ряд ATR для вычисления следующего значения ATR.Я правильно со своим мнением по этому поводу?
def ATRpd2():
data = pd.read_csv('data.txt', sep=",", header=0)
df = data
n = 14
df['Close_prev'] = df['Close'].shift(1)
df['TR'] = df[['High', 'Close_prev']].max(axis=1) - df[['Low', 'Close_prev']].min(axis=1)
df['MA'] = round(df.TR.rolling(n).mean(),6)
ATR_l = []
for idx, row in df.iterrows():
if idx <= n - 1:
ATR = row['MA']
else:
ATR = (ATR * (n - 1) + row['TR']) / n
ATR_l.append(round(ATR,6))
df['ATR'] = ATR_l
print(df.head(20))