#python #pandas #multi-index
Вопрос:
Я пытаюсь использовать значения пола и потолка в cumsum. Всякий раз, когда uniqueEntry имеет положительное значение, Позиции увеличиваются, а всякий раз, когда uniqueExit положительный, Позиции уменьшаются. Тем не менее, позиции должны иметь значение пола 0 и потолок 3.
Во-вторых, для каждого Символа, если uniqueEntry запускается, когда Позиции находятся на предельном значении, как uniqueEntry, так и uniqueExit (для каждого символа) игнорируются при расчете Позиций до тех пор, пока uniqueEntry не будет запущен, когда Позиции находятся ниже предельного значения. Желаемые результаты в последнем примере.
На практике я рассматриваю позиции по акциям, ограничивая количество позиций значением и исключая остальные. Возможно ли это без зацикливания?
Данные испытаний:
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
np.random.seed(56)
symbols, symlen = 2, 3
times = np.arange(datetime(2021, 1, 5), datetime(2021, 1, 12), timedelta(days=1)).astype(np.datetime64)
tlen = len(times)
A, Z = np.array(['A', 'Z']).view('int32')
symbol_names = np.random.randint(low=A, high=Z, size=symbols * symlen, dtype='int32').view(f'U{symlen}')
limit = np.random.randint(low=0, high=5, size=symbols*tlen, dtype='int32')
reset = np.random.randint(low=-1, high=1, size=symbols*tlen, dtype='int32')
times = np.concatenate([times] * symbols)
names = np.array([y for x in [[s] * tlen for s in symbol_names] for y in x])
value_col = np.random.randint(low=30, high=60, size=len(times), dtype='uint32')
df = pd.DataFrame({'Values': value_col}, index=[times, names])
df.index = df.index.set_names(['Date', 'Symbol'])
Создайте столбцы, определяющие условия:
df['uniqueEntry'] = np.where(df.Values > 45, 1, 0)
df['uniqueExit'] = np.where(df.Values < 40, 1, 0)
Сортировка и окончание:
df = df.sort_index(level='Date')
df['Positions'] = (df.uniqueEntry - df.uniqueExit).cumsum()
Текущий результат:
df
Values uniqueEntry uniqueExit Positions
Date Symbol
2021-01-05 ACL 42 0 0 0
VEP 40 0 0 0
2021-01-06 ACL 30 0 1 -1
VEP 31 0 1 -2
2021-01-07 ACL 38 0 1 -3
VEP 46 1 0 -2
2021-01-08 ACL 59 1 0 -1
VEP 43 0 0 -1
2021-01-09 ACL 52 1 0 0
VEP 50 1 0 1
2021-01-10 ACL 34 0 1 0
VEP 36 0 1 -1
2021-01-11 ACL 44 0 0 -1
VEP 48 1 0 0
Желаемые результаты:
Values uniqueEntry uniqueExit Positions
Date Symbol
2021-01-05 ACL 42 0 0 0
VEP 40 0 0 0
2021-01-06 ACL 30 0 1 0
VEP 31 0 1 0
2021-01-07 ACL 38 0 1 0
VEP 46 1 0 1
2021-01-08 ACL 59 1 0 2
VEP 43 0 0 2
2021-01-09 ACL 52 1 0 3
VEP 50 1 0 3 <- should be excluded
2021-01-10 ACL 34 0 1 2
VEP 36 0 1 2 <- should be ignored as uniqueEntry triggered while Positions = 3
2021-01-11 ACL 44 0 0 1
VEP 48 1 0 2
Комментарии:
1. Я не думаю, что это возможно без использования цикла for, так как значение позиций зависит от предыдущего значения. Возможно, вы сможете найти какой-то способ, выполнив некоторые причудливые манипуляции/вызовы функций, но что плохого в том, чтобы просто делать
df.iterrows()
?2. Скорость. Но я рассматриваю зацикливание, но с использованием итераций (), так как это значительно быстрее или с использованием numba. Очевидно, что зацикливание-это экспоненциально более простое решение здесь.