[英]Iteratively testing the performance of portfolio weights in pandas
我有x 個(假設 x = 8)股票因子的投資組合,權重為w 。 我可以使用 function F(w) = p以均等加權的方式測試這些因素的性能,其中 output p是性能指標。 第一個測試的投資組合權重 df 如下所示:
weight
0 12.57
1 12.49
2 12.49
3 12.49
4 12.49
5 12.49
6 12.49
7 12.49
在我使用 100/8 四舍五入到兩位小數的地方,給第一個因素加上余數,如下所示:
pd.DataFrame(columns = ['weight'], data = [(100/factorsdf.shape[0] // 0.01 / 100)]*factorsdf.shape[0])
weights['weight'].iloc[0] = weights['weight'].iloc[0] + round(100 - (100/factorsdf.shape[0] // 0.01 / 100) * factorsdf.shape[0],2)
我現在要做的是迭代改進這些權重。 我想這樣做的方法是逐漸減去底部權重(索引 7)的一半權重(此處:12.49/2 = 6.245)並將其添加到上方權重(索引 6)。
incremental_weight = (100/factorsdf.shape[0] // 0.01 / 100)/2
因此,在第一次迭代中,我將測試同等權重的投資組合。
在下一次迭代中,我將測試:
weight
0 12.57
1 12.49
2 12.49
3 12.49
4 12.49
5 12.49
6 18.735
7 6.245
如果這不能改善指標p ,我將嘗試將其添加到 dataframe 中的下一個權重元素,如下所示:
weight
0 12.57
1 12.49
2 12.49
3 12.49
4 12.49
5 18.735
6 12.49
7 6.245
如果確實有所改善,我將再減去底部元素的 6.245,然后嘗試將其添加到上面的元素中。 如果這不能改善p ,我會嘗試將它添加到上面的那個,依此類推,直到我嘗試將它添加到所有其他元素。
之后,我將對底部元素上方的元素(索引為 6)執行相同的過程,減去 6.245 並將其迭代添加到其他元素。 等等。 直到不能再改進度量p 。
以相對有效的方式在 pandas 中對此進行編程的好方法是什么?
如果我完全理解以下內容(我在代碼中添加了注釋),則應該可以工作:
import pandas as pd; import numpy as np
# my random generated factor scores
factorsdf = pd.DataFrame({"Factor": np.random.randint(0, 100, 8)})
# weights evenly allocated (from your code)
weights = pd.DataFrame(columns = ['weight'], data = [(100/factorsdf.shape[0] // 0.01 / 100)]*factorsdf.shape[0])
weights['weight'].iloc[0] = weights['weight'].iloc[0] + round(100 - (100/factorsdf.shape[0] // 0.01 / 100) * factorsdf.shape[0],2)
# weight to increment by (from your code)
incremental_weight = (100/factorsdf.shape[0] // 0.01 / 100)/2
# the F(w) function: weights must be first, from np.apply_along_axis below
def F_w(weights, factorsdf):
# here it is just the dot product of the random factors and the weights.
p = np.dot(factorsdf, weights.T/100)
return p
# initial value of p
p = F_w(np.array(weights["weight"]), np.array(factorsdf["Factor"]))
print("p: ", p)
# rows above the weight that is being decreased
i = len(weights) - 1
# copy of weights to change
weights_c = weights.copy(deep=True)
# can't decrease the top weight, because none above to change
while i >= 1:
print("i: ", i)
# series with 0s everywhere except on row that will be decreasing the weight
dec = pd.Series([0]*(len(weights_c)-1) + [incremental_weight]).shift(-len(weights)+1+i).fillna(0)
# increment array has all possible options for increasing weights above
inc = np.identity(i)*incremental_weight
# row that is decreasing should not increase
inc = np.vstack([inc, [0]*inc.shape[1]])
# if other rows below have a weight (are not 0) then these won't increase either
while inc.shape[0] < len(weights_c):
inc = np.vstack([inc, [0]*inc.shape[1]])
# if weight will be below 0 then should move up, also if there is only one row left
if ((weights_c["weight"].sub(dec)<0).sum() > 0) or (inc.shape[0] == 1):
i -= 1
continue
# subtract the increment from the weight
weights_c["weight"] = weights_c["weight"].sub(dec)
# array of possible weightings when incrementing rows above
weights_arr = np.repeat(np.array(weights_c), inc.shape[1], axis=1) + inc
print("weights_arr: ", weights_arr)
print("weights_c: ", weights_c)
print("factorsdf: ", np.array(factorsdf).T[:, :weights_arr.shape[0]])
# return the p values for F(w) for all the possible variations
res = np.apply_along_axis(F_w, 0, weights_arr, np.array(factorsdf).T[:, :weights_arr.shape[0]])
# if any of these are greater than current p...
if res.max() > p:
# set new value of p
p = res.max()
# find which row the increment should be added to
x = res.argmax()
# add the increment to the correct row
weights_c["weight"].iloc[x] += incremental_weight
print("x: ", x)
# if not, move on
else:
weights_c["weight"] = weights_c["weight"].add(dec)
i -= 1
# if the bottom weight is 0, remove this row from calculations
if weights_c["weight"].iloc[-1] == 0:
weights_c = weights_c.iloc[:-1]
i -= 1
print("weights_c: ", weights_c)
# print final weightings and max value of p
print("weights_c: ", weights_c)
print("p: ", p)
它肯定可以稍微清理一下,刪除一些 while 循環,但這可能會給你一個很好的起點。
如您所見,我使用的 numpy 比 pandas 多得多,如果權重和因子是 arrays 開始,代碼會更少。
如果您有任何問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.