【问题标题】:Condition check based on Pandas rolling window基于 Pandas 滚动窗口的条件检查
【发布时间】:2021-05-05 12:50:54
【问题描述】:

根据下面的可重现代码,我有以下数据框:

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']

期望的输出:

  • 如果满足条件,则将值“Neutral”添加到名为“Trend 20 Window”的新列中。

我曾尝试在 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"

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以使用通过使用.gt().lt()df['20MA']df['200MA'] 进行比较创建的布尔掩码,并通过检查.sum() 的滚动窗口内满足滚动条件的行数来使用.rolling() 检查滚动窗口内的结果.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                
    

    【讨论】:

      猜你喜欢
      • 2019-03-11
      • 1970-01-01
      • 2021-09-26
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 1970-01-01
      相关资源
      最近更新 更多