将Postgres中的金融数据转换为Pandas DataFrame以用于Zipline

6 投票
1 回答
1490 浏览
提问于 2025-04-17 13:37

我刚接触Pandas和Zipline,正在学习如何使用它们(以及如何用我手头的数据)。如果能给我一些建议,即使不是完整的解决方案,我也会非常感激。我尝试了很多方法,离目标也很近,但遇到了索引问题,具体是Exception: Reindexing only valid with uniquely valued Index objects。我使用的是[Pandas 0.10.0,Python 2.7]

我想把我在Postgres中拥有的成千上万只股票的月度收益数据,从以下这种形式转换:

ticker_symbol :: String, monthly_return :: Float, date :: Timestamp

例如:

AAPL, 0.112, 28/2/1992
GS, 0.13, 30/11/1981
GS, -0.23, 22/12/1981

注意:报告的频率是每月一次,但这里会有很多NaN数据,因为我手头的6000多家公司并不会同时存在。

…转换成下面描述的形式,这正是Zipline运行其回测器所需要的格式。(我觉得是这样。Zipline的回测器能否轻松处理这样的按月数据?我知道它可以,但有没有什么建议呢?)


下面是一个DataFrame(时间序列?这个怎么说?),是我需要的格式:

> data:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 2268 entries, 1993-01-04 00:00:00+00:00 to 2001-12-31 00:00:00+00:00
Data columns:
AA      2268  non-null values
AAPL    2268  non-null values
GE      2268  non-null values
IBM     2268  non-null values
JNJ     2268  non-null values
KO      2268  non-null values
MSFT    2268  non-null values
PEP     2268  non-null values
SPX     2268  non-null values
XOM     2268  non-null values
dtypes: float64(10)

下面是一个时间序列,格式也是我需要的。

> data.AAPL:

Date
1993-01-04 00:00:00+00:00    73.00
1993-01-05 00:00:00+00:00    73.12
...

2001-12-28 00:00:00+00:00    36.15
2001-12-31 00:00:00+00:00    35.55
Name: AAPL, Length: 2268

注意,这里没有收益数据,而是价格数据。它们经过Zipline的load_from_yahoo(不过,从源代码来看,实际上是通过Pandas中的函数)进行了调整,考虑了股息、拆分等,所以这些价格数据和我的收益数据之间是有对应关系的(除了初始价格),所以这里没有问题。

(编辑:如果你想让我写出我已有的代码,或者附上我的iPython笔记本或一个gist,请告诉我;我只是觉得这可能没什么帮助,但如果需要,我当然可以做到。)

1 个回答

3

我觉得你可能是在设置日期作为索引的时候太早了。我的建议是,先把日期和公司名称一起设置为索引,然后你可以把公司名称“展开”,再进行“重采样”。

可以这样做:

In [11]: df1
Out[11]: 
  ticker_symbol  monthly_return                date
0          AAPL           0.112 1992-02-28 00:00:00
1            GS           0.130 1981-11-30 00:00:00
2            GS          -0.230 1981-12-22 00:00:00

df2 = df2.set_index(['date','ticker_symbol'])
df3 = df2.unstack(level=1)
df4 = df.resample('M')

In [14]: df2
Out[14]: 
                          monthly_return
date       ticker_symbol                
1992-02-28 AAPL                    0.112
1981-11-30 GS                      0.130
1981-12-22 GS                     -0.230

In [15]: df3
Out[15]: 
               monthly_return      
ticker_symbol            AAPL    GS
date                               
1981-11-30                NaN  0.13
1981-12-22                NaN -0.23
1992-02-28              0.112   NaN

In [16]: df4
Out[16]: 
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 124 entries, 1981-11-30 00:00:00 to 1992-02-29 00:00:00
Freq: M
Data columns:
(monthly_return, AAPL)    1  non-null values
(monthly_return, GS)      2  non-null values
dtypes: float64(2)

撰写回答