这里的主要思想是根据美元而不是比率来工作。如果您跟踪ibm和福特股票的数量以及相对美元价值,则可以将重新平衡的标准表示为
mask = (df['ratio'] >= 1+tol) | (df['ratio'] <= 1-tol)
比率等于
df['ratio'] = df['ibm value'] / df['ford value']
和
df['ibm value'],
df['ford value']代表实际美元价值。
import datetime as DTimport numpy as npimport pandas as pdimport pandas.io.data as PIDdef setup_df(): df1 = PID.get_data_yahoo("IBM", start=DT.datetime(1970, 1, 1), end=DT.datetime.today()) df1.rename(columns={'Adj Close': 'ibm'}, inplace=True) df2 = PID.get_data_yahoo("F", start=DT.datetime(1970, 1, 1), end=DT.datetime.today()) df2.rename(columns={'Adj Close': 'ford'}, inplace=True) df = df1.join(df2.ford, how='inner') df = df[['ibm', 'ford']] df['sh ibm'] = 0 df['sh ford'] = 0 df['ibm value'] = 0 df['ford value'] = 0 df['ratio'] = 0 return dfdef invest(df, i, amount): """ Invest amount dollars evenly between ibm and ford starting at ordinal index i. This modifies df. """ c = dict([(col, j) for j, col in enumerate(df.columns)]) halfvalue = amount/2 df.iloc[i:, c['sh ibm']] = halfvalue / df.iloc[i, c['ibm']] df.iloc[i:, c['sh ford']] = halfvalue / df.iloc[i, c['ford']] df.iloc[i:, c['ibm value']] = ( df.iloc[i:, c['ibm']] * df.iloc[i:, c['sh ibm']]) df.iloc[i:, c['ford value']] = ( df.iloc[i:, c['ford']] * df.iloc[i:, c['sh ford']]) df.iloc[i:, c['ratio']] = ( df.iloc[i:, c['ibm value']] / df.iloc[i:, c['ford value']])def rebalance(df, tol, i=0): """ Rebalance df whenever the ratio falls outside the tolerance range. This modifies df. """ c = dict([(col, j) for j, col in enumerate(df.columns)]) while True: mask = (df['ratio'] >= 1+tol) | (df['ratio'] <= 1-tol) # ignore prior locations where the ratio falls outside tol range mask[:i] = False try: # Move i one index past the first index where mask is True # Note that this means the ratio at i will remain outside tol range i = np.where(mask)[0][0] + 1 except IndexError: break amount = (df.iloc[i, c['ibm value']] + df.iloc[i, c['ford value']]) invest(df, i, amount) return dfdf = setup_df()tol = 0.05invest(df, i=0, amount=100)rebalance(df, tol)df['portfolio value'] = df['ibm value'] + df['ford value']df['ibm weight'] = df['ibm value'] / df['portfolio value']df['ford weight'] = df['ford value'] / df['portfolio value']print df['ibm weight'].min()print df['ibm weight'].max()print df['ford weight'].min()print df['ford weight'].max()# This shows the rows which trigger rebalancingmask = (df['ratio'] >= 1+tol) | (df['ratio'] <= 1-tol)print(df.loc[mask])


