Подтвердить что ты не робот

Добавление вычисленного столбца (ов) к кадру данных в pandas

У меня есть набор данных о ценах OHLC, который я проанализировал из CSV в фрейм данных Pandas и пересчитал до 15-минутных баров:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 500047 entries, 1998-05-04 04:45:00 to 2012-08-07 00:15:00
Freq: 15T
Data columns:
Close    363152  non-null values
High     363152  non-null values
Low      363152  non-null values
Open     363152  non-null values
dtypes: float64(4)

Я хотел бы добавить различные вычисляемые столбцы, начиная с простых столбцов, таких как Диапазон периода (H-L), а затем логические значения, чтобы указать наличие ценовых моделей, которые я буду определять - например, образец свечи молотка, для которого определение образца:

def closed_in_top_half_of_range(h,l,c):
    return c > l + (h-l)/2

def lower_wick(o,l,c):
    return min(o,c)-l

def real_body(o,c):
    return abs(c-o)

def lower_wick_at_least_twice_real_body(o,l,c):
    return lower_wick(o,l,c) >= 2 * real_body(o,c)

def is_hammer(row):
    return lower_wick_at_least_twice_real_body(row["Open"],row["Low"],row["Close"]) \
    and closed_in_top_half_of_range(row["High"],row["Low"],row["Close"])

Основная проблема: как мне сопоставить функцию со столбцом, в частности, где я хотел бы сослаться на более чем один другой столбец или целую строку или что-то еще?

Этот пост посвящен добавлению двух вычисляемых столбцов из одного исходного столбца, который близок, но не совсем так.

И немного более продвинутый: для ценовых паттернов, которые определяются со ссылкой на более чем один столбец (T), как я могу ссылаться на разные строки (например, T-1, T-2 и т.д.) Из определения функции?

4b9b3361

Ответ 1

Точный код будет отличаться для каждого столбца, который вы хотите сделать, но, скорее всего, вы захотите использовать функции map и apply. В некоторых случаях вы можете просто вычислить, используя существующие столбцы напрямую, поскольку столбцы являются объектами Pandas Series, которые также работают как массивы Numpy, которые автоматически работают по элементам для обычных математических операций.

>>> d
    A   B  C
0  11  13  5
1   6   7  4
2   8   3  6
3   4   8  7
4   0   1  7
>>> (d.A + d.B) / d.C
0    4.800000
1    3.250000
2    1.833333
3    1.714286
4    0.142857
>>> d.A > d.C
0     True
1     True
2     True
3    False
4    False

Если вам нужно использовать такие операции, как max и min внутри строки, вы можете использовать apply с axis=1 для применения любой функции, которая вам нравится в каждой строке. Вот пример, который вычисляет min(A, B)-C, который, кажется, похож на ваш "нижний фитиль":

>>> d.apply(lambda row: min([row['A'], row['B']])-row['C'], axis=1)
0    6
1    2
2   -3
3   -3
4   -7

Надеюсь, это даст вам некоторое представление о том, как действовать.

Изменить: для сравнения строк с соседними строками простейший подход состоит в том, чтобы разрезать столбцы, которые вы хотите сравнить, оставив начало/конец, а затем сравните результирующие фрагменты. Например, это скажет вам, для каких строк элемент в столбце A меньше, чем следующий элемент строки в столбце C:

d['A'][:-1] < d['C'][1:]

и это делает другой путь, говоря вам, какие строки имеют A меньше, чем предыдущая строка C:

d['A'][1:] < d['C'][:-1]

Выполнение ['A"][:-1] срезает последний элемент столбца A и делает ['C'][1:] срезает первый элемент столбца C, поэтому, когда вы выровняете эти два и сравниваете их, вы сравниваете каждый элемент в с C из следующей строки.

Ответ 2

У вас может быть is_hammer в терминах row["Open"] и т.д., как показано ниже

def is_hammer(rOpen,rLow,rClose,rHigh):
    return lower_wick_at_least_twice_real_body(rOpen,rLow,rClose) \
       and closed_in_top_half_of_range(rHigh,rLow,rClose)

Затем вы можете использовать карту:

df["isHammer"] = map(is_hammer, df["Open"], df["Low"], df["Close"], df["High"])

Ответ 4

Первые четыре функции, которые вы перечислите, будут работать и на векторах, за исключением того, что lower_wick нужно адаптировать. Что-то вроде этого,

def lower_wick_vec(o, l, c):
    min_oc = numpy.where(o > c, c, o)
    return min_oc - l

где o, l и c - векторы. Вы можете сделать это таким образом, вместо этого, который просто берет df как входной сигнал и избегает использования numpy, хотя он будет намного медленнее:

def lower_wick_df(df):
    min_oc = df[['Open', 'Close']].min(axis=1)
    return min_oc - l

Другие три будут работать над столбцами или векторами точно так же, как они есть. Затем вы можете закончить с помощью

def is_hammer(df):
    lw = lower_wick_at_least_twice_real_body(df["Open"], df["Low"], df["Close"]) 
    cl = closed_in_top_half_of_range(df["High"], df["Low"], df["Close"])
    return cl & lw

Операторы бит могут выполнять заданную логику для булевых векторов, & для and, | для or и т.д. Этого достаточно, чтобы полностью векторизовать выбранные вами выборочные вычисления и быть относительно быстрыми. Возможно, вы, возможно, ускорите еще больше, временно работая с массивами numpy, лежащими в основе данных, при выполнении этих вычислений.

Во второй части я бы рекомендовал ввести столбец с указанием шаблона для каждой строки и написать семейство функций, которые относятся к каждому шаблону. Затем группируйте шаблон и примените соответствующую функцию к каждой группе.