1

モデル化しようとしている単純な株式ポートフォリオ シミュレーションがありますが、いくつかの試みにもかかわらず、これをベクトル化する方法がわかりません。多分それは不可能ですが、誰かが考えているかどうかを知りたかったのです。

私の難点は、特定の日の株式は、2 日前のアカウントの値と株価の関数であるということです。ただし、1 日のアカウントの値は、前日のアカウントの値と今日の株式数および株価の変化の関数です。したがって、ベクトル化する方法が思いつかない株式とアカウントの値の間には前後の関係があるため、以下の唯一の解決策は以下の for ループです。

import pandas as pd
import numpy as np
stats = pd.DataFrame(index = range(0,10))

stats['Acct Val'] = 0.0
stats['Shares'] = 0.0
stats['Stock Px'] = pd.Series([23,25,24,26,22,23,25,25,26,24],index=stats.index)
# Wgt is the percentage of the account value that should be invested in the stock on a given day
stats['Wgt'] = pd.Series([0.5,0.5,0.5,0.5,0.3,0.4,0.4,0.2,0.2,0.0,],index=stats.index)
stats['Daily PNL'] = 0.0
# Start the account value at $10,000.00
stats.ix[0:1, 'Acct Val'] = 10000.0
stats.ix[0:1, 'Wgt'] = 0
for date_loc in range(2, len(stats.index)):
    # Keep shares the same unless 'wgt' column changes
    if stats.at[date_loc,'Wgt'] != stats.at[date_loc-1,'Wgt']:
        # Rebalanced shares are based on the acct value and stock price two days before
        stats.at[date_loc,'Shares'] = stats.at[date_loc-2,'Acct Val'] * stats.at[date_loc,'Wgt'] / stats.at[date_loc-2,'Stock Px']
    else:
        stats.at[date_loc,'Shares'] = stats.at[date_loc-1,'Shares']
    # Daily PNL is simply the shares owned on a day times the change in stock price from the previous day to the next
    stats.at[date_loc,'Daily PNL'] = stats.at[date_loc,'Shares'] * (stats.at[date_loc,'Stock Px'] - stats.at[date_loc-1,'Stock Px'])
    # Acct value is yesterday's acct value plus today's PNL
    stats.at[date_loc,'Acct Val'] = stats.at[date_loc-1,'Acct Val'] + stats.at[date_loc,'Daily PNL']


In [44]: stats
Out[44]:
       Acct Val      Shares  Stock Px  Wgt   Daily PNL
0  10000.000000    0.000000        23  0.0    0.000000
1  10000.000000    0.000000        25  0.0    0.000000
2   9782.608696  217.391304        24  0.5 -217.391304
3  10217.391304  217.391304        26  0.5  434.782609
4   9728.260870  122.282609        22  0.3 -489.130435
5   9885.451505  157.190635        23  0.4  157.190635
6  10199.832776  157.190635        25  0.4  314.381271
7  10199.832776   85.960448        25  0.2    0.000000
8  10285.793224   85.960448        26  0.2   85.960448
9  10285.793224    0.000000        24  0.0   -0.000000

In [45]:

編集: 2013 年 10 月 19 日午後 11 時 1 分:

foob​​arbecue のコードを使用してみましたが、そこに到達できませんでした:

import pandas as pd
import numpy as np
stats = pd.DataFrame(index = range(0,10))
stats['Acct Val'] = 10000.0
stats['Shares'] = 0.0
stats['Stock Px'] = pd.Series([23,25,24,26,22,23,25,25,26,24],index=stats.index)
# Wgt is the percentage of the account value that should be invested in the stock on a given day
stats['Wgt'] = pd.Series([0.5,0.5,0.5,0.5,0.3,0.4,0.4,0.2,0.2,0.0,],index=stats.index)
stats['Daily PNL'] = 0.0
# Start the account value at $10,000.00
#stats.ix[0:1, 'Acct Val'] = 10000.0
stats.ix[0:1, 'Wgt'] = 0

def function1(df_row):
    #[stuff you want to do when Wgt changed]
    df_row['Shares'] = df_row['Acct Val'] * df_row['Wgt2ahead'] / df_row['Stock Px']
    return df_row

def function2(df_row):
    #[stuff you want to do when Wgt did not change]
    df_row['Shares'] = df_row['SharesPrevious']
    return df_row

#Find where the Wgt column changes
stats['WgtChanged']=stats.Wgt.diff() <> 0 # changed ">" to "<>"
#Using boolean indexing, choose all rows where Wgt changed and apply a function
stats['Wgt2ahead'] = stats['Wgt'].shift(-2)
stats = stats.apply(lambda df_row: function1(df_row) if df_row['WgtChanged'] == True else df_row, axis=1)
stats['Shares'] = stats['Shares'].shift(2)
#Likewise, for rows where Wgt did not change
stats['SharesPrevious'] = stats['Shares'].shift(1)
stats = stats.apply(lambda df_row: function2(df_row) if df_row['WgtChanged'] == False else df_row, axis=1)
4

1 に答える 1

0
def function1(df_row):
    [stuff you want to do when Wgt changed]

def function2(df_row):
    [stuff you want to do when Wgt did not change]

#Find where the Wgt column changes
stats['WgtChanged']=stats.Wgt.diff() > 0
#Using boolean indexing, choose all rows where Wgt changed and apply a function
stats[stats['WgtChanged']].apply(function1, axis=1)
#Likewise, for rows where Wgt did not change
stats[~stats['WgtChanged']].apply(function2, axis=1)
于 2013-10-20T02:06:27.863 に答える