2014-07-03 54 views
3

我一直在試圖找出在這個問題上最好的方法我的頭撞牆。我在Excel中有一個SLOW backtester,我試圖將它移植到熊貓身上。我認爲我可以利用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) 

這並不讓你很遠,但這裏是需要的輸出。在這個例子中,我想通過在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

只要按照您在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 
+0

謝謝!似乎這是我需要的。不幸的是,有些東西並不適用於循環。我得到'KeyError:'swap'指向'if'語句。我認爲這是一個數據類型問題(即float vs bool),但調整不能解決錯誤。 – tkfbristol

+0

抱歉,編輯過的'[in] 114'中缺少'shares = total/prices'。這應該是問題。 –

+0

是的。很有幫助。似乎'if'情況總是會變成'真'。確認。過早的帖子。現在輸出: 'ABC交換 2000-01-01 250.000000 0.000000 454.545455 NaN的 2000年1月2日166.666667 0.000000 416.666667 NaN的 2000-01-03 500.000000 0.000000 250.000000 NaN的 2000年1月4日0.000000 100.000000 277.777778 NaN的 2000- 01-05 0.000000 98.039216 294.117647 NaN 2000-01-06 0.000000 96.153846 263.157895 NaN' 我想知道swap數據類型是否有問題?我試過這個:'swap = pd.Series(False,index = dates)'。 – tkfbristol