在Python中计算复合的返回系列

时间:2011-04-01 14:50:45

标签: python list-comprehension time-series pandas

问候所有,我有两个系列的数据:每日原始股票价格回报(正或负浮动)和交易信号(买= 1,卖= -1,无交易= 0)。

原始价格回报只是今天价格的对数除以昨天的价格:

log(p_today / p_yesterday)

一个例子:

raw_return_series = [ 0.0063 -0.0031 0.0024 ..., -0.0221 0.0097 -0.0015]

交易信号系列如下:

signal_series = [-1. 0. -1. -1. 0. 0. -1. 0. 0. 0.]

根据交易信号获得每日回报:

daily_returns = [raw_return_series[i] * signal_series[i+1] for i in range(0, len(signal_series)-1)]

这些每日回报可能如下所示:

[0.0, 0.00316, -0.0024, 0.0, 0.0, 0.0023, 0.0, 0.0, 0.0] # results in daily_returns; notice the 0s

我需要使用daily_returns系列来计算复合回报系列。但是,鉴于daily_returns系列中有0个值,我需要将“通过时间”的最后一个非零复合返回到下一个非零复合返回。

例如,我像这样计算复合回报(注意我随着时间的推移“向后”):

compound_returns = [(((1 + compounded[i + 1]) * (1 + daily_returns[i])) - 1) for i in range(len(compounded) - 2, -1, -1)]

以及结果列表:

[0.0, 0.0, 0.0023, 0.0, 0.0, -0.0024, 0.0031, 0.0] # (notice the 0s)

我的目标是将最后的非零回报继续累积这些复合回报。也就是说,由于索引i处的返回取决于索引i + 1处的返回,因此索引i + 1处的返回应该是非零的。每次列表理解在daily_return系列中遇到零时,它基本上都会重新启动。

3 个答案:

答案 0 :(得分:8)

有一个名为pandas的奇妙模块是由AQR(对冲基金)的一个人编写的,擅长这样的计算......你需要的是一种处理“缺​​失数据”的方法。如上所述,基础知识是使用scipy或numpy的nan(不是数字)功能;但是,即使这些库也不会使财务计算变得更容易......如果你使用pandas,你可以将你不想考虑的数据标记为nan,然后任何未来的计算都会拒绝它,同时对其他数据执行正常操作。

我在我的交易平台上使用pandas大约8个月......我希望我早点开始使用它。

Wes(作者)在pyCon 2010上发表了关于模块功能的演讲......请参阅幻灯片和视频on the pyCon 2010 webpage。在该视频中,他演示了如何获得每日回报,在回报矩阵(在几分之一秒内),时间戳/图表数据上运行1000次线性回归...所有这些都是通过此模块完成的。结合psyco,这是一个财务分析工具的野兽。

它处理的另一件好事是横截面数据...所以你可以抓住每日收盘价,滚动价格等等......然后按时间戳计算每一个,并获得所有这些类似于python字典的东西(参见pandas.DataFrame类)...然后你可以像下面那样访问数据片段:

close_prices['stdev_5d']

有关计算滚动stdev的更多信息,请参阅the pandas rolling moments doc

由于我的分析要求,Wes已经不遗余力地使用cython加速模块了,尽管我会承认我正在考虑升级我的服务器(一个较旧的Xeon)。

编辑STRIMP的问题: 在将代码转换为使用pandas数据结构之后,我仍然不清楚你是如何在pandas数据框中索引数据以及复合函数处理缺失数据的要求(或者就此而言,返回0.0的条件......或者如果您在熊猫中使用NaN ..)。我将演示使用我的数据索引...随机挑选一天...... df是一个数据框,其中包含ES期货报价...每秒索引...缺少的报价用{{填写1}}。 DataFrame索引是numpy.nan个对象,由datetime模块的时区对象偏移。

pytz

举一个简单的例子说明如何计算一个连续回报的列(在>>> df.info <bound method DataFrame.info of <class 'pandas.core.frame.DataFrame'> Index: 86400 entries , 2011-03-21 00:00:00-04:00 to 2011-03-21 23:59:59-04:00 etf 18390 non-null values etfvol 18390 non-null values fut 29446 non-null values futvol 23446 non-null values ... >>> # ET is a pytz object... >>> et <DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD> >>> # To get the futures quote at 9:45, eastern time... >>> df.xs(et.localize(dt.datetime(2011,3,21,9,45,0)))['fut'] 1291.75 >>> 中),该列在10分钟前引用该报价(并填写缺失的刻度),我会这样做:

pandas.TimeSeries

在这种情况下不需要lambda,只需在600秒前将值列分开。那个>>> df['fut'].fill(method='pad')/df['fut'].fill(method='pad').shift(600) 部分是因为我的数据每秒被索引。

HTH, \麦克

答案 1 :(得分:3)

这个问题的累积回归部分在Wes McKinney出色的“Python for Data Analysis”一书第339页中讨论,并使用Pandas的cumprod()从计算出的价格变化中创建一个重新计算/索引的累积回报。

书中的例子:

import pandas.io.data as web

price = web.get_data_yahoo('AAPL', '2011-01-01')['Adj Close']

returns = price.pct_change()

ret_index = (1 + returns).cumprod()

ret_index[0] = 1 # Set first value to 1

答案 2 :(得分:1)

想象一下,我有一个DataMatrix收盘价,一些指标值,以及这样的交易信号:

 >>> data_matrix
                        close          dvi            signal
 2008-01-02 00:00:00    144.9          0.6504         -1             
 2008-01-03 00:00:00    144.9          0.6603         -1             
 2008-01-04 00:00:00    141.3          0.7528         -1             
 2008-01-07 00:00:00    141.2          0.8226         -1             
 2008-01-08 00:00:00    138.9          0.8548         -1             
 2008-01-09 00:00:00    140.4          0.8552         -1             
 2008-01-10 00:00:00    141.3          0.846          -1             
 2008-01-11 00:00:00    140.2          0.7988         -1             
 2008-01-14 00:00:00    141.3          0.6151         -1             
 2008-01-15 00:00:00    138.2          0.3714         1   

我使用该信号根据交易信号创建一个返回的DataMatrix:

>>> get_indicator_returns()

                   indicator_returns    
2008-01-02 00:00:00    NaN            
2008-01-03 00:00:00    0.000483       
2008-01-04 00:00:00    0.02451        
2008-01-07 00:00:00    0.0008492      
2008-01-08 00:00:00    0.01615        
2008-01-09 00:00:00    -0.01051       
2008-01-10 00:00:00    -0.006554      
2008-01-11 00:00:00    0.008069       
2008-01-14 00:00:00    -0.008063      
2008-01-15 00:00:00    0.02201 

我最终做的是:

def get_compounded_indicator_cumulative(self):

    indicator_dm = self.get_indicator_returns()
    dates = indicator_dm.index

    indicator_returns = indicator_dm['indicator_returns']
    compounded = array(zeros(size(indicator_returns)))

    compounded[1] = indicator_returns[1]

    for i in range(2, len(indicator_returns)):

        compounded[i] = (1 + compounded[i-1]) * (1 + indicator_returns[i]) - 1

    data = {
        'compounded_returns': compounded
    }

    return DataMatrix(data, index=dates)

由于某些原因,我真的很难与这个... ...

我正在将所有价格系列转换为PyTables。到目前为止看起来很有希望。