在python中找到价格动量的有效方法:平均列

时间:2018-01-13 20:39:23

标签: python pandas numpy

我定义价格动量是给定股票在过去 n 天的动量的平均值。

反过来,动量是一种分类:如果当天的收盘价高于前一天,则每天标记为1;如果价格低于前一天,则标记为-1。

我的库存变化百分比如下:

df['close in percent'] = np.array([0.27772152, 1.05468772, 
                                   0.124156 , -0.39298394, 
                                   0.56415267,  1.67812005])

momentum = df['close in percent'].apply(lambda x: 1 if x > 0 else -1).values

Momentum应该是:[1,1,1,-1,1,1]

因此,如果我找到最后 n = 3天的平均动力,我希望我的价格动力为:

Price_momentum = [Nan, Nan, 1, 1/3, 1/3, 1/3]

我设法使用以下代码使其工作,但这非常慢(数据集是5000多行,执行需要10分钟)。

for i in range(3,len(df)+1,1):
    data = np.array(momentum[i-3:i])
    df['3_day_momentum'].iloc[i-1]=data.mean()

3 个答案:

答案 0 :(得分:7)

您可以创建rolling对象:

df = pd.DataFrame()
df['close_in_percent'] = np.array([0.27772152, 1.05468772, 
                                   0.124156 , -0.39298394, 
                                   0.56415267,  1.67812005])
df['momentum'] = np.where(df['close_in_percent'] > 0, 1, -1)
df['3_day_momentum'] = df.momentum.rolling(3).mean()

在这里,np.whereapply()的替代品,通常很慢,应该作为最后的手段使用。

   close_in_percent  momentum  3_day_momentum
0            0.2777         1             NaN
1            1.0547         1             NaN
2            0.1242         1          1.0000
3           -0.3930        -1          0.3333
4            0.5642         1          0.3333
5            1.6781         1          0.3333

答案 1 :(得分:5)

您可以使用np.where + pd.Rolling.mean -

s = df['close in percent']
pd.Series(np.where(s > 0, 1, -1)).rolling(3).mean()

0         NaN
1         NaN
2    1.000000
3    0.333333
4    0.333333
5    0.333333
dtype: float64

对于v0.17或更低版​​本,还有rolling_mean可直接使用数组。

pd.rolling_mean(np.where(s > 0, 1, -1), window=3)
array([        nan,         nan,  1.        ,  0.33333333,  0.33333333,
        0.33333333])

答案 2 :(得分:3)

那些滚动平均值基本上是均匀的滤波值。因此,我们可以使用SciPy's uniform filter -

JMSMessageChannel

基准

时间from scipy.ndimage.filters import uniform_filter1d def rolling_mean(ar, W=3): hW = (W-1)//2 out = uniform_filter1d(momentum.astype(float), size=W, origin=hW) out[:W-1] = np.nan return out momentum = 2*(df['close in percent'] > 0) - 1 df['out'] = rolling_mean(momentum, W=3) pandas.rolling -

SciPy's uniform filter