基于Pandas动态行的权益计算

时间:2014-07-03 20:49:18

标签: python pandas

我一直在靠墙试图找出这个问题的最佳方法。我在Excel中有一个SLOW backtester,我正在尝试移植到pandas。我以为我能够利用python的强大功能,而不仅仅是在python中重新创建Excel函数,但我被卡住了!

关键的挑战在于随着时间的推移,对多个和动态变化的仪器进行投资组合P& L计算。例如,根据标准,我想在前N个时期购买工具A和C.然后我想在接下来的N个时期使用B和C.等等。我想根据当前股权购买每种工具的比例金额(而不是每次购买100股股票)。

Excel,基于行的功能首先根据初始权益计算股票,然后根据“前一行”中可用的权益计算股票。类似于: IF(RebalancePeriod = TRUE,EquityFromPrevRow / CurrentSharePrice,PreviousRowShares)

尝试熊猫吃它。以下是示例输入:

import datetime as dt
import pandas as pd
from pandas import *

dates = date_range('1/1/2000', periods=6)
index=dates
data = {'A': pd.Series([20, 30, 10, 0, 0, 0], index=index)
    , 'B': pd.Series([0, 0, 0, 50, 51, 52], index=index)
    , 'C': pd.Series([11, 12, 20, 18, 17, 19], index=index)}

initial_capital = 5000.0

prices = pd.DataFrame(data, index=dates)

这不会让你走得太远,但这里是所需的输出。在这个例子中,我想通过在第4行(2000-01-04)从A到B交换来重新平衡工具,其中A = 0。

Prices          
            A   B   C
2000-01-01  20  0   11
2000-01-02  30  0   12
2000-01-03  10  0   20
2000-01-04  0   50  18
2000-01-05  0   51  17
2000-01-06  0   52  19

Shares (initial or current equity / price)          
            A       B       C
2000-01-01  250.0   0.0     454.5
2000-01-02  250.0   0.0     454.5
2000-01-03  250.0   0.0     454.5
2000-01-04  0.0     115.9   322.0
2000-01-05  0.0     115.9   322.0
2000-01-06  0.0     115.9   322.0


Equity (shares * price)             
            A       B       C       Total
2000-01-01  5,000.0 0.0     5,000.0 10,000.0
2000-01-02  7,500.0 0.0     5,454.5 12,954.5
2000-01-03  2,500.0 0.0     9,090.9 11,590.9
2000-01-04  0.0     5,795.5 5,795.5 11,590.9
2000-01-05  0.0     5,911.4 5,473.5 11,384.8
2000-01-06  0.0     6,027.3 6,117.4 12,144.7

我意识到这一点有很多。我感谢任何帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

只需遵循您在Excel中所做的相同想法,唯一的区别是应用于每一行的excel function现在表示为循环:

In [113]:

print prices
             A   B   C
2000-01-01  20   0  11
2000-01-02  30   0  12
2000-01-03  10   0  20
2000-01-04   0  50  18
2000-01-05   0  51  17
2000-01-06   0  52  19
In [114]:
swap=pd.Series([False,]*len(dates),index=dates, name='sawp')
swap[3]=True
total=pd.DataFrame({'A':0, 'B':0, 'C':0},index=dates)
total.ix[0]=[5000,5000,5000]
shares=total/prices
shares['swap']=swap
In [115]:
#the loop
for idx in range(1, len(shares)):
    if shares.ix[idx, 'swap']:
        shares.ix[idx, ['A','B','C']]=(shares.ix[idx-1, ['A','B','C']]*prices.ix[idx-1]).sum()/2/prices.ix[idx]
    else:
        shares.ix[idx, ['A','B','C']]=shares.ix[idx-1, ['A','B','C']]
In [116]:
#Get rid of the infinite numbers
shares[shares==np.inf]=0
In [117]:

print shares
              A           B           C   swap
2000-01-01  250    0.000000  454.545455  False
2000-01-02  250    0.000000  454.545455  False
2000-01-03  250    0.000000  454.545455  False
2000-01-04    0  115.909091  321.969697   True
2000-01-05    0  115.909091  321.969697  False
2000-01-06    0  115.909091  321.969697  False
In [118]:

print shares*prices
               A            B            C  swap
2000-01-01  5000     0.000000  5000.000000   NaN
2000-01-02  7500     0.000000  5454.545455   NaN
2000-01-03  2500     0.000000  9090.909091   NaN
2000-01-04     0  5795.454545  5795.454545   NaN
2000-01-05     0  5911.363636  5473.484848   NaN
2000-01-06     0  6027.272727  6117.424242   NaN
In [119]:
#Total asserts
print (shares*prices).sum(1)
2000-01-01    10000.000000
2000-01-02    12954.545455
2000-01-03    11590.909091
2000-01-04    11590.909091
2000-01-05    11384.848485
2000-01-06    12144.696970
Freq: D, dtype: float64