Python和Pandas - 移动平均线交叉

chi*_*liq 9 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
Run Code Online (Sandbox Code Playgroud)

当SMA_15和SMA_45相交时,我想找到所有日期.

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

编辑:

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

数据行,时间:

  • 长SMA(45)值比短SMA(15)值大于短SMA周期(15)并且变小.
  • 长SMA(45)值比短SMA(15)值小于短SMA周期(15)并且变得更大.

unu*_*tbu 14

我正在采用交叉来表示当SMA线 - 作为时间函数 - 相交时,如此投资页面上所示.

在此输入图像描述

由于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)))
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

所以有交叉,

在此输入图像描述

然后

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)
Run Code Online (Sandbox Code Playgroud)

产量

1    20150128
2    20150129
Name: Date, dtype: int64
Run Code Online (Sandbox Code Playgroud)

  • 有点晚了,但对于交叉来说,这两天不应该是等号:`crossing = (((df['SMA_15']` **&lt;** `df['SMA_45']) &amp; (previous_15 &gt;= previous_45 )) | ((df['SMA_15']` **&gt;** `df['SMA_45']) &amp; (previous_15 &lt;= previous_45)))` (2认同)

Jer*_*ril 5

以下方法给出了类似的结果,但比以前的方法花费的时间更少:

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)
Run Code Online (Sandbox Code Playgroud)

这种方法所用的时间: 2.7 ms ± 310 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

先前方法所花费的时间:3.46 ms ± 307 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)