问题描述
我有一个 df 列,其中包含每日收益行的行情,并且索引是日期时间索引
SPY IWM TLT
2016-01-04 0.914939 0.998960 1.014094
2016-01-05 1.014062 1.002650 1.002819
2016-01-06 0.991911 0.999906 1.014441
2016-01-07 0.937087 0.995280 1.014140
2016-01-08 1.005388 0.999147 0.995572
I have initial weights for each ticker on day one
SPY 50
IWM 25
TLT 25
Each weight has a band
SPY = 40,60
IWM = 20,30
TLT = 20,30
数据帧每天持续 5 年。第一天,我想计算原始重量乘以当天的回报。对于那天之后的每一天,我想计算当天的回报(即前一天的价值乘以该天的回报)并每天检查三者中任何一个的权重是否在带外。每天的权重是该股票代码的值/该天值的总和。如果其中一个代码权重连续 5 天违反区间,我想重新平衡所有三个权重,第二天的行应该是原始权重除以前几天的投资组合价值。
Example SPY IWM TLT PortValue SPYW IWMW TLTW
XX Date 51.45 27.25 21.54 100.24 51.3 27.18 21.4 No Rebal,nextday*prevday
XX Date 59 29 15 103 57 28 14.5 Rebal,next day below
NEXT DAY 50/103*ret 25/103*ret 25/103*ret
我什么都试过了。 lambda 函数、np.where、for 循环、if 语句、上述所有内容的嵌套变体。我无法在第一天绕过索引的 bool 测试,并使其在剩余的日子里工作,其中下一行取决于前一行的计算,而不是日期时间索引位置
解决方法
有趣的问题。以下内容应该可以工作 - 显然,进行了许多修改以反映您的实际数据。请注意,这完全忽略了日期时间索引,因为它提供信息并且不会影响结果:
portfolio = [50,25,25] #starting amount of each investment in the portfolio
allocations =[.50,.25,.25] #base allocations among the portfolio investments
tickers = list(df3.columns.values)
bands = [[.4,.6],[.20,.30],.30]] #permissible bands for each investment/ticker
violations = {ticker:0 for ticker in tickers} #initialize a violations counter for each ticker
#start iterating through each day in the dataframe:
for i,row in df.iterrows():
yields = row.to_list() #extract the daily yields
portfolio = [investment*yld for investment,yld in zip(portfolio,yields) ] #recalculate the new value of each investment
weights = [investment/sum(portfolio)for investment in portfolio] #recalculate the new relative weight of each investment
for weight,band in zip(weights,bands):
ticker = tickers[weights.index(weight)] #for each ticker -
#check if it's outside its permitted band
if weight<band[0] or weight>band[1]:
violations[ticker] +=1 #if it is,increment its specific violations counter
else:
violations[ticker]=0 #if not,reset the counter to zero,to account for non-consecutive violations
if violations[ticker] == 5: #5 consecutive violations detected....
portfolio = [sum(portfolio)*allocation for allocation in allocations] #rebalance the portofolio