Python和Pandas - 移动平均线交叉

时间:2015-02-05 13:32:00

标签: python numpy pandas

有一个带有一些股票数据的Pandas DataFrame对象。 SMA是从之前45/15天计算的移动平均线。

Date      Price   SMA_45      SMA_15
20150127  102.75  113         106
20150128  103.05  100         106
20150129  105.10  112         105
20150130  105.35  111         105
20150202  107.15  111         105
20150203  111.95  110         105
20150204  111.90  110         106

我希望找到所有日期,当SMA_15和SMA_45相交时。

使用Pandas或Numpy可以有效地完成吗?怎么样?

编辑:

我的意思是'十字路口':

数据行,时间:

  • 长SMA(45)值比短SMA(15)值大于短SMA期(15)并且变小。
  • 长SMA(45)值小于短SMA(15)值超过短SMA期间(15)并且变得更大。

3 个答案:

答案 0 :(得分:14)

我正在采用交叉来表示何时SMA线 - 作为时间的函数 - 相交,如this investopedia page所示。

enter image description here

由于SMA表示连续功能,因此存在交叉时, 对于给定的行,(SMA_15小于SMA_45)和(之前的SMA_15是 大于之前的SMA_45) - 反之亦然。

在代码中,可以表示为

previous_15 = df['SMA_15'].shift(1)
previous_45 = df['SMA_45'].shift(1)
crossing = (((df['SMA_15'] <= df['SMA_45']) & (previous_15 >= previous_45))
            | ((df['SMA_15'] >= df['SMA_45']) & (previous_15 <= previous_45)))

如果我们将您的数据更改为

Date      Price   SMA_45      SMA_15
20150127  102.75  113         106
20150128  103.05  100         106
20150129  105.10  112         105
20150130  105.35  111         105
20150202  107.15  111         105
20150203  111.95  110         105
20150204  111.90  110         106

以便有交叉点,

enter image description here

然后

import pandas as pd

df = pd.read_table('data', sep='\s+')
previous_15 = df['SMA_15'].shift(1)
previous_45 = df['SMA_45'].shift(1)
crossing = (((df['SMA_15'] <= df['SMA_45']) & (previous_15 >= previous_45))
            | ((df['SMA_15'] >= df['SMA_45']) & (previous_15 <= previous_45)))
crossing_dates = df.loc[crossing, 'Date']
print(crossing_dates)

产量

1    20150128
2    20150129
Name: Date, dtype: int64

答案 1 :(得分:0)

作为unutbu答案的替代方法,也可以执行以下操作来查找SMA_15跨越SMA_45的索引。

diff = df['SMA_15'] < df['SMA_45']
diff_forward = diff.shift(1)
crossing = np.where(abs(diff - diff_forward) == 1)[0]
print(crossing)
>>> [1,2]

print(df.iloc[crossing])
>>>
       Date   Price  SMA_15  SMA_45
1  20150128  103.05    100    106
2  20150129  105.10    112    105

答案 2 :(得分:0)

以下方法可获得相似的结果,但所需时间少于以前的方法:

df['position'] = df['SMA_15'] > df['SMA_45']
df['pre_position'] = df['position'].shift(1)
df.dropna(inplace=True) # dropping the NaN values
df['crossover'] = np.where(df['position'] == df['pre_position'], False, True)
  

此方法花费的时间:2.7 ms ± 310 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

     

previous approach花费的时间:3.46 ms ± 307 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)