简体   繁体   English

Python和Pandas - 移动平均线交叉

[英]Python and Pandas - Moving Average Crossover

There is a Pandas DataFrame object with some stock data. 有一个带有一些股票数据的Pandas DataFrame对象。 SMAs are moving averages calculated from previous 45/15 days. 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

I want to find all dates, when SMA_15 and SMA_45 intersect. 当SMA_15和SMA_45相交时,我想找到所有日期。

Can it be done efficiently using Pandas or Numpy? 可以使用Pandas或Numpy有效地完成吗? How? 怎么样?

EDIT: 编辑:

What I mean by 'intersection': 我的意思是'十字路口':

The data row, when: 数据行,时间:

  • long SMA(45) value was bigger than short SMA(15) value for longer than short SMA period(15) and it became smaller. 长SMA(45)值比短SMA(15)值大于短SMA周期(15)并且变小。
  • long SMA(45) value was smaller than short SMA(15) value for longer than short SMA period(15) and it became bigger. 长SMA(45)值比短SMA(15)值小于短SMA周期(15)并且变得更大。

I'm taking a crossover to mean when the SMA lines -- as functions of time -- intersect, as depicted on this investopedia page . 我正在采用交叉来表示当SMA线 - 作为时间函数 - 相交时, 如此投资页面上所示

在此输入图像描述

Since the SMAs represent continuous functions, there is a crossing when, for a given row, (SMA_15 is less than SMA_45) and (the previous SMA_15 is greater than the previous SMA_45) -- or vice versa. 由于SMA表示连续函数,因此对于给定行(SMA_15小于SMA_45)和(先前的SMA_15大于先前的SMA_45)时存在交叉 - 或反之亦然。

In code, that could be expressed as 在代码中,可以表示为

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)))

If we change your data to 如果我们将您的数据更改为

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

so that there are crossings, 所以有交叉,

在此输入图像描述

then 然后

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)

yields 产量

1    20150128
2    20150129
Name: Date, dtype: int64

As an alternative to the unutbu 's answer, something like below can also be done to find the indices where SMA_15 crosses SMA_45 . 作为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

The following methods gives the similar results, but takes less time than the previous methods: 以下方法给出了类似的结果,但比以前的方法花费的时间更少:

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)

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

Time taken for previous approach : 3.46 ms ± 307 µ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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM