Python pandas时间序列w /层次索引和滚动/移位

时间:2014-04-06 10:48:14

标签: python pandas multi-index rolling-computation

挣扎着熊猫的滚动和转变的概念。有许多好的建议,包括在这个论坛中,但我很难将这些应用到我的场景中。

现在我在时间序列中使用传统的循环但是,花了8个小时来迭代超过150,000行,这是所有代码的大约3天的数据。有2个月的数据处理它可能无法完成我从休假回来后,没有提到电力切断的风险,此后我不得不重新开始这次没有等待休假。

我有以下15分钟股票价格时间序列(日期时间(时间戳)和股票代码的分层索引,唯一的原始列是closePrice):

                                     closePrice
    datetime               ticker
    2014-02-04 09:15:00    AAPL      xxx
                           EQIX      xxx
                           FB        xxx
                           GOOG      xxx
                           MSFT      xxx
    2014-02-04 09:30:00    AAPL      xxx
                           EQIX      xxx
                           FB        xxx
                           GOOG      xxx
                           MSFT      xxx
    2014-02-04 09:45:00    AAPL      xxx
                           EQIX      xxx
                           FB        xxx
                           GOOG      xxx
                           MSFT      xxx

我需要添加两列:

  1. 12sma,12天移动平均线。经过几个小时的搜索,最好的建议是使用rolling_mean,所以我试过了。但是考虑到我的TS结构它没有工作,即它在第一个MA的顶部工作是基于前12行计算的,而不管不同的股票价值。我如何根据索引进行平均,即首先是日期时间然后是自动收报机,所以我得到MA说AAPL?目前确实如此(AAPL + EQIX + FB + GOOG + MSFT + AAPL ......最多排第12行)/ 12
  2. 一旦我得到12sma列,我需要12ema列,12天指数MA。对于计算,每个股票代码的时间序列中的第一个值只是从同一行复制12sma值。随后,我需要来自同一行的closePrice和前一行的12ema,即过去的15分钟。我做了很长时间的研究似乎解决方案是滚动和移位的组合,但我无法弄清楚如何将它组合在一起。
  3. 任何帮助我都会感激不尽。

    感谢。

    修改

    感谢Jeff的提示,在交换和排序ix级别后,我能够使用rolling_mean()获得12sma,并努力在同一时间戳插入从12sma复制的第一个12ema值:

                                     close  12sma  12ema
        sec_code datetime
        AAPL     2014-02-05 11:45:00 113.0  NaN    NaN
                 2014-02-05 12:00:00 113.2  NaN    NaN
                 2014-02-05 13:15:00 112.9  NaN    NaN
                 2014-02-05 13:30:00 113.2  NaN    NaN
                 2014-02-05 13:45:00 113.0  NaN    NaN
                 2014-02-05 14:00:00 113.1  NaN    NaN
                 2014-02-05 14:15:00 113.3  NaN    NaN
                 2014-02-05 14:30:00 113.3  NaN    NaN
                 2014-02-05 14:45:00 113.3  NaN    NaN
                 2014-02-05 15:00:00 113.2  NaN    NaN
                 2014-02-05 15:15:00 113.2  NaN    NaN
                 2014-02-05 15:30:00 113.3  113.16 113.16
                 2014-02-05 15:45:00 113.3  113.19 NaN
                 2014-02-05 16:00:00 113.2  113.19 NaN
                 2014-02-06 09:45:00 112.6  113.16 NaN
                 2014-02-06 10:00:00 113.5  113.19 NaN
                 2014-02-06 10:15:00 113.8  113.25 NaN
                 2014-02-06 10:30:00 113.5  113.29 NaN
                 2014-02-06 10:45:00 113.7  113.32 NaN
                 2014-02-06 11:00:00 113.5  113.34 Nan
    

    我理解pandas有pandas.stats.moments.ewma,但我更喜欢使用我从一本书中得到的公式,该书目前需要收盘价和前一行12ema。

    所以,我试图从2月5日15:45及以后填写12ema专栏。我尝试使用函数apply()但是shift给出了一个错误:

        def f12ema(x):
            K = 2 / (12 + 1)
            return x['price_nom'] * K + x['12ema'].shift(-1) * (1-K)
    
        df1.apply(f12ema, axis=1)
    
        AttributeError: ("'numpy.float64' object has no attribute 'shift'", u'occurred at index 2014-02-05 11:45:00')
    

    我想到的另一种可能性是rolling_appy(),但这是我所不知道的。

1 个答案:

答案 0 :(得分:1)

创建一个包含您想要的时间的日期范围

In [47]: rng = date_range('20130102 09:30:00','20130105 16:00:00',freq='15T')

In [48]: rng = rng.take(rng.indexer_between_time('09:30:00','16:00:00'))

In [49]: rng
Out[49]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-02 09:30:00, ..., 2013-01-05 16:00:00]
Length: 108, Freq: None, Timezone: None

创建一个类似于你的框架(2000代码x日期)

In [50]: df = DataFrame(np.random.randn(len(rng)*2000,1),columns=['close'],index=MultiIndex.from_product([rng,range(2000)],names=['date','ticker']))

对级别进行重新排序,使其为索引的自动收录器x日期,SORT IT !!!!

In [51]: df = df.swaplevel('ticker','date').sortlevel()

In [52]: df
Out[52]: 
                               close
ticker date                         
0      2013-01-02 09:30:00  0.840767
       2013-01-02 09:45:00  1.808101
       2013-01-02 10:00:00 -0.718354
       2013-01-02 10:15:00 -0.484502
       2013-01-02 10:30:00  0.563363
       2013-01-02 10:45:00  0.553920
       2013-01-02 11:00:00  1.266992
       2013-01-02 11:15:00 -0.641117
       2013-01-02 11:30:00 -0.574673
       2013-01-02 11:45:00  0.861825
       2013-01-02 12:00:00 -1.562111
       2013-01-02 12:15:00 -0.072966
       2013-01-02 12:30:00  0.673079
       2013-01-02 12:45:00  0.766105
       2013-01-02 13:00:00  0.086202
       2013-01-02 13:15:00  0.949205
       2013-01-02 13:30:00 -0.381194
       2013-01-02 13:45:00  0.316813
       2013-01-02 14:00:00 -0.620176
       2013-01-02 14:15:00 -0.193126
       2013-01-02 14:30:00 -1.552111
       2013-01-02 14:45:00  1.724429
       2013-01-02 15:00:00 -0.092393
       2013-01-02 15:15:00  0.197763
       2013-01-02 15:30:00  0.064541
       2013-01-02 15:45:00 -1.574853
       2013-01-02 16:00:00 -1.023979
       2013-01-03 09:30:00 -0.079349
       2013-01-03 09:45:00 -0.749285
       2013-01-03 10:00:00  0.652721
       2013-01-03 10:15:00 -0.818152
       2013-01-03 10:30:00  0.674068
       2013-01-03 10:45:00  2.302714
       2013-01-03 11:00:00  0.614686

                                 ...

[216000 rows x 1 columns]

通过自动收录器分组。为每个ticker返回一个DataFrame,它是rolling_mean和ewma的应用程序。请注意,有许多选项可用于控制此操作,例如窗口,您可以使它不会包裹天数等等。

In [53]: df.groupby(level='ticker')['close'].apply(lambda x: concat({ 'spma' : pd.rolling_mean(x,3), 'ema' : pd.ewma(x,3) }, axis=1))
Out[53]: 
                                 ema      spma
ticker date                                   
0      2013-01-02 09:30:00  0.840767       NaN
       2013-01-02 09:45:00  1.393529       NaN
       2013-01-02 10:00:00  0.480282  0.643504
       2013-01-02 10:15:00  0.127447  0.201748
       2013-01-02 10:30:00  0.270334 -0.213164
       2013-01-02 10:45:00  0.356580  0.210927
       2013-01-02 11:00:00  0.619245  0.794758
       2013-01-02 11:15:00  0.269100  0.393265
       2013-01-02 11:30:00  0.041032  0.017067
       2013-01-02 11:45:00  0.258476 -0.117988
       2013-01-02 12:00:00 -0.216742 -0.424986
       2013-01-02 12:15:00 -0.179622 -0.257750
       2013-01-02 12:30:00  0.038741 -0.320666
       2013-01-02 12:45:00  0.223881  0.455406
       2013-01-02 13:00:00  0.188995  0.508462
       2013-01-02 13:15:00  0.380972  0.600504
       2013-01-02 13:30:00  0.188987  0.218071
       2013-01-02 13:45:00  0.221125  0.294942
       2013-01-02 14:00:00  0.009907 -0.228185
       2013-01-02 14:15:00 -0.041013 -0.165496
       2013-01-02 14:30:00 -0.419688 -0.788471
       2013-01-02 14:45:00  0.117299 -0.006936

       2013-01-04 10:00:00 -0.060415  0.341013
       2013-01-04 10:15:00  0.074068  0.604611
       2013-01-04 10:30:00 -0.108502  0.440256
       2013-01-04 10:45:00 -0.514229 -0.636702
                                 ...       ...

[216000 rows x 2 columns]

相当好的性能,因为它基本上是在代码上循环。

In [54]: %timeit df.groupby(level='ticker')['close'].apply(lambda x: concat({ 'spma' : pd.rolling_mean(x,3), 'ema' : pd.ewma(x,3) }, axis=1))
1 loops, best of 3: 2.1 s per loop
相关问题