在 Pandas 中找到移动平均线的当前交叉点和先前交叉点之间的最小值

Find the minimum value between a current and previous crossovers of moving-averages in Pandas

我有一个很大的股票价格数据框 df.columns = ['open','high','low','close']

问题定义: 当发生 EMA 交叉时,我指的是 df['cross'] = cross。每次发生交叉时,如果我们将当前交叉标记为交叉 4,我想检查交叉 3 和 4 之间的 df['low'] 的最小值是否大于 df['low' 的最小值] 在交叉点 1 和交叉点 2 之间。到目前为止,我已经根据从 'Gherka' 收到的帮助尝试编写代码。我已经对交叉进行了索引,并找到了连续交叉之间的最小值。 因此,每次发生交叉时,都必须将其与前 3 次交叉进行比较,我需要检查 MIN(CROSS4,CROSS 3) > MIN(CROSS2,CROSS1)。

如果你们能帮助我完成,我将不胜感激。

import pandas as pd    
import numpy as np    
import bisect as bs

data = pd.read_csv("Nifty.csv")    
df = pd.DataFrame(data)    

df['5EMA'] = df['Close'].ewm(span=5).mean()    
df['10EMA'] = df['Close'].ewm(span=10).mean()    
condition1 = df['5EMA'].shift(1) < df['10EMA'].shift(1)    
condition2 = df['5EMA'] > df['10EMA']    
df['cross'] = np.where(condition1 & condition2, 'cross', None)    
cross_index_array = df.loc[df['cross'] == 'cross'].index

def find_index(a, x):    
    i = bs.bisect_left(a, x)    
    return a[i-1]

def min_value(x):
    """Find the minimum value of 'Low' between crossovers 1 and 2, crossovers 3 and 4, etc..."""    
    cur_index = x.name    
    prev_cross_index = find_index(cross_index_array, cur_index)    
    return df.loc[prev_cross_index:cur_index, 'Low'].min()

df['min'] = None    
df['min'][df['cross'] == 'cross'] = df.apply(min_value, axis=1)    
print(df)

这应该可以解决问题:

import pandas as pd

df = pd.DataFrame({'open': [1, 2, 3, 4, 5],
                   'high': [5, 6, 6, 5, 7],
                   'low': [1, 3, 3, 4, 4],
                   'close': [3, 5, 3, 5, 6]})

df['day'] = df.apply(lambda x: 'bull' if (
    x['close'] > x['open']) else None, axis=1)

df['min'] = None
df['min'][df['day'] == 'bull'] = pd.rolling_min(
    df['low'][df['day'] == 'bull'], window=2)

print(df)

#    close  high  low  open   day   min
# 0      3     5    1     1  bull   NaN 
# 1      5     6    3     2  bull     1
# 2      3     6    3     3  None  None
# 3      5     5    4     4  bull     3
# 4      6     7    4     5  bull     4

公开征求意见!

如果我对你的问题的理解正确,你需要一个动态的 "rolling window" 来计算最小值。假设您的索引是默认索引,这意味着它按升序排序,您可以尝试以下方法:

import pandas as pd
import numpy as np
from bisect import bisect_left

df = pd.DataFrame({'open': [1, 2, 3, 4, 5],
                   'high': [5, 6, 6, 5, 7],
                   'low': [1, 3, 2, 4, 4],
                   'close': [3, 5, 3, 5, 6]})

这使用与 mommermi 相同的样本数据,但将第三天的低点更改为 2,因为第三天也应包含在 "rolling window" 中。

df['day'] = np.where(df['close'] > df['open'], 'bull', None)

我们使用矢量化 numpy 运算计算 day 列,这应该会更快一些。

bull_index_array = df.loc[df['day'] == 'bull'].index

我们存储我们标记为多头的行(天)的索引值。

def find_index(a, x):
    i = bisect_left(a, x)
    return a[i-1]
核心库中的

Bisect将使我们能够以高效的方式找到前一个牛市的指数。这要求索引按默认排序。

def min_value(x):
    cur_index = x.name
    prev_bull_index = find_index(bull_index_array, cur_index)
    return df.loc[prev_bull_index:cur_index, 'low'].min()

接下来,我们定义一个函数,它将通过按先前和当前索引对原始数据帧进行切片来创建 "dynamic" 滚动 window。

df['min'] = df.apply(min_value, axis=1)

最后,我们将 min_value 函数逐行应用于数据框,得到:

    open    high    low     close   day     min
0   1       5       1       3       bull    NaN
1   2       6       3       5       bull    1.0
2   3       6       2       3       None    2.0
3   4       5       4       5       bull    2.0
4   5       7       4       6       bull    4.0