Pandas动态行基股票计算
我一直在绞尽脑汁,想弄清楚这个问题的最佳解决办法。我在Excel中有一个运行很慢的回测工具,现在想把它转到pandas上。我原以为可以利用Python的强大功能,而不仅仅是把Excel的功能重新做一遍,但我现在卡住了!
主要的挑战在于如何计算投资组合的盈亏,这涉及到多个不断变化的投资工具。例如,根据某些标准,我想在前N个时间段内购买A和C这两个工具。接着在接下来的N个时间段内使用B和C。以此类推。我想根据当前的资金比例购买每个工具,而不是每次都买100股之类的。
在Excel中,行基础的函数首先根据初始资金计算股票数量,然后根据“上一行”的可用资金进行计算。大致是这样的:IF(RebalancePeriod = TRUE, EquityFromPrevRow / CurrentSharePrice, PreviousRowShares)
我尝试把它转到pandas上。这是一些输入示例:
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年1月4日时,通过从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 个回答
1
只需遵循你在 Excel
中使用的相同思路,唯一的区别是,现在应用于每一行的 excel 函数
被表示为一个循环:
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