Python 基于滚动窗口的状态检测

Python 基于滚动窗口的状态检测,python,pandas,Python,Pandas,根据下面的可复制代码,我有以下数据帧: df.tail(10) open high low close 200MA 20MA Trend date 2020-12-24 1.3273 1.3384 1.3257 1.3384 1.324826 1.325365 Up 2020-12-25 1.3408 1.3408 1.3268 1.326

根据下面的可复制代码,我有以下数据帧:

df.tail(10)

             open   high    low       close   200MA       20MA    Trend
date                            
2020-12-24  1.3273  1.3384  1.3257  1.3384  1.324826    1.325365    Up
2020-12-25  1.3408  1.3408  1.3268  1.3268  1.324926    1.326240    Up
2020-12-26  1.3268  1.3283  1.3217  1.3239  1.325008    1.326085    Up
2020-12-27  1.3240  1.3240  1.3078  1.3078  1.325009    1.325215    Up
2020-12-28  1.3103  1.3103  1.2878  1.2878  1.324973    1.323490    Down
2020-12-29  1.2893  1.2932  1.2876  1.2886  1.324951    1.321890    Down
2020-12-30  1.2871  1.2937  1.2810  1.2906  1.324923    1.319755    Down
2020-12-31  1.2905  1.3020  1.2905  1.2993  1.324934    1.318450    Down
2021-01-01  1.3006  1.3022  1.2896  1.2905  1.324893    1.316830    Down
2021-01-02  1.2909  1.3085  1.2890  1.3008  1.324908    1.315660    Down
我需要一个基于以下条件的新列:

  • 每行回顾20个周期的滚动窗口
  • 如果在过去20个周期内,有df['20MA']>df['200MA']的行&
  • 如果在过去20个周期内,也有行为df['20MA']
所需输出:

import pandas as pd
import numpy as np

def genMockDataFrame(days,startPrice,colName,startDate,seed=None): 
   
    periods = days*24
    np.random.seed(seed)
    steps = np.random.normal(loc=0, scale=0.0018, size=periods)
    steps[0]=0
    P = startPrice+np.cumsum(steps)
    P = [round(i,4) for i in P]

    fxDF = pd.DataFrame({ 
        'ticker':np.repeat( [colName], periods ),
        'date':np.tile( pd.date_range(startDate, periods=periods, freq='H'), 1 ),
        'price':(P)})
    fxDF.index = pd.to_datetime(fxDF.date)
    fxDF = fxDF.price.resample('D').ohlc()
    return fxDF

df = genMockDataFrame(290,1.1904,'eurusd','19/3/2020',seed=1)

df["200MA"] = df["close"].rolling(window=200).mean()
df["20MA"] = df["close"].rolling(window=20).mean()
df.loc[df['20MA'] > df['200MA'], "Trend"] = "Up"
df.loc[df['20MA'] < df['200MA'], "Trend"] = "Down"
  • 如果满足条件,将值“中性”添加到名为“趋势20窗口”的新列中
我曾尝试在Pandas中使用滚动窗口功能,但很难获得所需的结果

复制示例的代码:

import pandas as pd
import numpy as np

def genMockDataFrame(days,startPrice,colName,startDate,seed=None): 
   
    periods = days*24
    np.random.seed(seed)
    steps = np.random.normal(loc=0, scale=0.0018, size=periods)
    steps[0]=0
    P = startPrice+np.cumsum(steps)
    P = [round(i,4) for i in P]

    fxDF = pd.DataFrame({ 
        'ticker':np.repeat( [colName], periods ),
        'date':np.tile( pd.date_range(startDate, periods=periods, freq='H'), 1 ),
        'price':(P)})
    fxDF.index = pd.to_datetime(fxDF.date)
    fxDF = fxDF.price.resample('D').ohlc()
    return fxDF

df = genMockDataFrame(290,1.1904,'eurusd','19/3/2020',seed=1)

df["200MA"] = df["close"].rolling(window=200).mean()
df["20MA"] = df["close"].rolling(window=20).mean()
df.loc[df['20MA'] > df['200MA'], "Trend"] = "Up"
df.loc[df['20MA'] < df['200MA'], "Trend"] = "Down"
将熊猫作为pd导入
将numpy作为np导入
def genMockDataFrame(天、startPrice、colName、startDate、seed=None):
周期=天*24
np.随机种子(种子)
步数=np.随机.正常(loc=0,刻度=0.0018,大小=周期)
步数[0]=0
P=startPrice+np.cumsum(步数)
P=[P中i的第(i,4)轮]
fxDF=pd.DataFrame({
“ticker”:名词重复([colName],句点),
“日期”:np.tile(pd.date_范围(起始日期,周期=周期,频率=H'),1),
‘价格’:(P)})
fxDF.index=pd.to_datetime(fxDF.date)
fxDF=fxDF.price.resample('D').ohlc()
返回fxDF
df=genMockDataFrame(290,1.1904,'EURUUSD','19/3/2020',seed=1)
df[“200MA”]=df[“关闭”]。滚动(窗口=200)。平均值()
df[“20MA”]=df[“关闭”]。滚动(窗口=20)。平均值()
df.loc[df['20MA']>df['200MA'],“趋势”]=“上升”
df.loc[df['20MA']
您可以使用通过使用
.gt()
.lt()
df['20MA']
df['200MA']
进行比较而创建的布尔掩码,并通过检查
.sum()
.ge>滚动窗口中满足条件的行数>=1来检查滚动窗口中的结果(1) 
。然后在掩码上使用
.loc()
为匹配行的新列指定“中性”,如下所示:

df['Trend 20 Window'] = ''        # init to ''
periods = 20
mask = df['20MA'].gt(df['200MA']).rolling(periods).sum().ge(1) & df['20MA'].lt(df['200MA']).rolling(periods).sum().ge(1)
df.loc[mask, 'Trend 20 Window'] = 'Neutral'
演示 让我们用您的样本数据(10行)进行测试,使用较小的滚动窗口3

df['Trend 20 Window'] = ''
periods = 3
mask = df['20MA'].gt(df['200MA']).rolling(periods).sum().ge(1) & df['20MA'].lt(df['200MA']).rolling(periods).sum().ge(1)
df.loc[mask, 'Trend 20 Window'] = 'Neutral'
结果:

              open    high     low   close     200MA      20MA Trend Trend 20 Window
date                                                                                
2020-12-24  1.3273  1.3384  1.3257  1.3384  1.324826  1.325365    Up                
2020-12-25  1.3408  1.3408  1.3268  1.3268  1.324926  1.326240    Up                
2020-12-26  1.3268  1.3283  1.3217  1.3239  1.325008  1.326085    Up                
2020-12-27  1.3240  1.3240  1.3078  1.3078  1.325009  1.325215    Up                
2020-12-28  1.3103  1.3103  1.2878  1.2878  1.324973  1.323490  Down         Neutral
2020-12-29  1.2893  1.2932  1.2876  1.2886  1.324951  1.321890  Down         Neutral
2020-12-30  1.2871  1.2937  1.2810  1.2906  1.324923  1.319755  Down                
2020-12-31  1.2905  1.3020  1.2905  1.2993  1.324934  1.318450  Down                
2021-01-01  1.3006  1.3022  1.2896  1.2905  1.324893  1.316830  Down                
2021-01-02  1.2909  1.3085  1.2890  1.3008  1.324908  1.315660  Down                

您可以使用通过使用
.gt()
.lt()
df['20MA']
df['200MA']
进行比较而创建的布尔掩码,并通过使用
检查满足滚动窗口内条件的行数的
.sum()
检查滚动窗口内的结果
。然后在掩码上使用
.loc()
为匹配行的新列指定“中性”,如下所示:

df['Trend 20 Window'] = ''        # init to ''
periods = 20
mask = df['20MA'].gt(df['200MA']).rolling(periods).sum().ge(1) & df['20MA'].lt(df['200MA']).rolling(periods).sum().ge(1)
df.loc[mask, 'Trend 20 Window'] = 'Neutral'
演示 让我们用您的样本数据(10行)进行测试,使用较小的滚动窗口3

df['Trend 20 Window'] = ''
periods = 3
mask = df['20MA'].gt(df['200MA']).rolling(periods).sum().ge(1) & df['20MA'].lt(df['200MA']).rolling(periods).sum().ge(1)
df.loc[mask, 'Trend 20 Window'] = 'Neutral'
结果:

              open    high     low   close     200MA      20MA Trend Trend 20 Window
date                                                                                
2020-12-24  1.3273  1.3384  1.3257  1.3384  1.324826  1.325365    Up                
2020-12-25  1.3408  1.3408  1.3268  1.3268  1.324926  1.326240    Up                
2020-12-26  1.3268  1.3283  1.3217  1.3239  1.325008  1.326085    Up                
2020-12-27  1.3240  1.3240  1.3078  1.3078  1.325009  1.325215    Up                
2020-12-28  1.3103  1.3103  1.2878  1.2878  1.324973  1.323490  Down         Neutral
2020-12-29  1.2893  1.2932  1.2876  1.2886  1.324951  1.321890  Down         Neutral
2020-12-30  1.2871  1.2937  1.2810  1.2906  1.324923  1.319755  Down                
2020-12-31  1.2905  1.3020  1.2905  1.2993  1.324934  1.318450  Down                
2021-01-01  1.3006  1.3022  1.2896  1.2905  1.324893  1.316830  Down                
2021-01-02  1.2909  1.3085  1.2890  1.3008  1.324908  1.315660  Down