DataFrame计算平均购买价格

问题描述:

我有一个有两列的数据框:数量和价格。DataFrame计算平均购买价格

df = pd.DataFrame([ 
[ 1, 5], 
[-1, 6], 
[ 2, 3], 
[-1, 2], 
[-1, 4], 
[ 1, 2], 
[ 1, 3], 
[ 1, 4], 
[-2, 5]], columns=['quantity', 'price']) 

df['amount'] = df['quantity'] * df['price'] 
df['cum_qty'] = df['quantity'].cumsum() 

我已经添加了两列新的数量和cum_qty(累计数量)。 现在数据框看起来是这样的(正数代表购买,负值代表卖出):

quantity price amount cum_qty 
0   1  5  5  1 
1  -1  6  -6  0 
2   2  3  6  2 
3  -1  2  -2  1 
4  -1  4  -4  0 
5   1  2  2  1 
6   1  3  3  2 
7   1  4  4  3 
8  -2  5  -10  1 

我想计算平均买入价。

每次cum_qty = 0时,qantity和amount都应重置为零。 所以我们看索引= [5,6,7]的行。 对于每一行,一个项目以价格2,3和4购买,这意味着我有3个[(2 + 3 + 4)/ 3]的平均价格的库存3。

在指数杀跌= 8已经发生(卖出交易不改变买入价),我会每一个在价格3

所以,基本上,我必须除以累积的所有累计买入金额后来自上一个非零的累计数量的数量。

如何计算与熊猫DataFrame的所有交易结果的手头购买?

+1

什么是您预期的输出?如果你正在谈论股票交易模拟,我会建议'for loop' – Wen

根据我的理解,您需要为每个交易圈买入价格,然后您可以试试这个。

df['new_index'] = df.cum_qty.eq(0).shift().cumsum().fillna(0.)#give back the group id for each trading circle.* 
df=df.loc[df.quantity>0]# kick out the selling action 
df.groupby('new_index').apply(lambda x:(x.amount.sum()/x.quantity.sum())) 

new_index 
0.0 5.0# 1st ave price 5 
1.0 3.0# 2nd ave price 3 
2.0 3.0# 3nd ave price 3 ps: this circle no end , your position still pos 1 
dtype: float64 

EDIT1为你额外要求

DF=df.groupby('new_index',as_index=False).apply(lambda x : x.amount.cumsum()/ x.cum_qty).reset_index() 
DF.columns=['Index','AvePrice'] 
DF.index=DF.level_1 
DF.drop(['level_0', 'level_1'],axis=1,inplace=True) 
pd.concat([df,DF],axis=1) 

Out[572]: 
     quantity price amount cum_qty new_index 0 
level_1             
0    1  5  5  1  0.0 5.0 
2    2  3  6  2  1.0 3.0 
5    1  2  2  1  2.0 2.0 
6    1  3  3  2  2.0 2.5 
7    1  4  4  3  2.0 3.0 
+0

谢谢你的答案。我更喜欢Wen的回答,但Jigl的回答也很好,也解决了这个问题。 – user3225309

+1

谢谢你的回答。我更喜欢Wen的回答,但Jigl的回答也很好,也解决了这个问题。 再次感谢您。现在,随着您提供的信息,我徘徊,可以计算每行的平均价格。 例如,在索引= 4的行中,没有任何东西在手。 – user3225309

+0

在索引为5的行中,价格为2时每个手头上有一个产生当前平均价格= 2。 在指数为6的行中,每个价格为3,这将设置平均价格为2 + 3/1 + 1 = 2,5。 在索引7的行中,每个价格为4,将设置平均价格为2 + 3 + 4/1 + 1 + 1 = 3. 是否可以创建一个新列每行都有一个平均价格? – user3225309

df[df['cum_qty'].map(lambda x: x == 0)].index 

将使你在这行你有0

df[df['cum_qty'].map(lambda x: x == 0)].index.max() 

一个cum_qty给你的最后一行0 cum_qty

start = df[df['cum_qty'].map(lambda x: x == 0)].index.max() + 1 
end = len(df) - 1 

给你开始和结束行数字,是你所指的范围

df['price'][start:end].sum()/df['quantity'][start:end].sum() 

给你在你给出的例子中所做的回答

如果你想知道cum_qty 0每次出现的这个值,那么你可以通过使用每一个的索引来应用开始/结束逻辑(我的结果第一行代码)。