【问题标题】:calculating stock returns from a dataframe with stacked prices从具有堆叠价格的数据框中计算股票收益
【发布时间】:2020-01-28 14:01:47
【问题描述】:

我有一个包含三列的数据框,如下所示。

  stock    date         price
  abc      2020-01-20   102.3
  efg      2020-01-20   36.2
  xyz      2020-01-20   341
  abc      2020-01-21   102.3
  efg      2020-01-21   34.3
  xyz      2020-01-21   321
  abc      2020-01-22   104.1
  efg      2020-01-22   35.2
  xyz      2020-01-22   318

我想计算每只股票的每日收益,所以最终得到一个如下所示的数据框(请注意,我没有在这里计算收益,我只是放了一些随机数,显然不会有收益20 日),

返回

股票一天的收益定义如下,

21 日股票 efg 的回报 =(21 日价格 / 20 日价格)- 1

stock    date         return
  abc      2020-01-21   0
  efg      2020-01-21   -0.23
  xyz      2020-01-21   -1.53
  abc      2020-01-22   0.86
  efg      2020-01-22   0.15
  xyz      2020-01-22   -0.18

我已经尝试了下面的代码,

df_ret = pd.pivot_table(df_ret, values='price', index=['stock'], columns = 'date')   
df_ret = df_ret.transpose()
rets = df_ret.pct_change()
rets = rets.transpose()

rets 有正确的数据,但我需要上面第二个表格中显示的格式的数据。我不确定这样做的最佳方式?

更新

df = df_ret.assign(ret = df_ret.groupby('stock')['price'].pct_change())

通过使用上面的行,我得到下面的结果。它接近正确,但 904000 的 22 日的值应该是 nan。

   stock    date        price           ret
   903600   2020-01-22  11741.189956    nan
   903600   2020-01-23  11678.197357    -0.005365094955116612
   903600   2020-01-24  11683.808897    0.00048051422907646746
   903600   2020-01-27  11683.808897    0.0
   904000   2020-01-22  2017.933988    -0.8272880012169546
   904000   2020-01-23  1993.986017    -0.011867569079271667
   904000   2020-01-24  2012.609294    0.009339722967576014
   904000   2020-01-27  1975.147341   -0.01861362417021617

【问题讨论】:

  • 您希望返回作为差异还是百分比变化?
  • 请百分比变化,pct_chnage() 给出正确答案
  • @Parfait 道歉,非常正确,我现在已经定义了一个回报

标签: python pandas dataframe


【解决方案1】:

只需groupby + pct_change 工作:

final = df.assign(return_ = df.groupby('stock')['price'].pct_change())

  stock       date  price   return_
0   abc 2020-01-20  102.3       NaN
1   efg 2020-01-20   36.2       NaN
2   xyz 2020-01-20  341.0       NaN
3   abc 2020-01-21  102.3  0.000000
4   efg 2020-01-21   34.3 -0.052486
5   xyz 2020-01-21  321.0 -0.058651
6   abc 2020-01-22  104.1  0.017595
7   efg 2020-01-22   35.2  0.026239
8   xyz 2020-01-22  318.0 -0.009346

【讨论】:

  • 感谢您的回答,我可以看到它适用于我发布的测试数据。在我的实际真实数据栏上,第一行是 nan,第 20 行的其他值实际上有一个值。我是否遗漏了什么,即我需要先对数据进行排序吗?
  • 谢谢,刚刚完成了排序。它关闭但仍然不太有效。我已经更新了我的帖子,说明了原因
  • @mHelpMe 我刚刚获取了更新的数据,我在 22 日收到了 NaN 的 904000,如预期的那样,尝试使用编辑后的数据,您会看到相同的结果
  • 是的,你是对的。奇怪的是,在我的真实数据集中它不起作用。就像它没有正确分组或其他东西一样
  • @mHelpMe 嗯,可能会尝试剥离 stock 列以防它有前导或尾随空格,但不确定是否真的,因为此解决方案有效并且理想情况下应该有效
【解决方案2】:

我会这样做:

import pandas as pd
data = {'stock':['abc','efg','xyz','abc','efg','xyz','abc','efg','xyz'],'date':['2020-01-20','2020-01-20','2020-01-20','2020-01-21','2020-01-21','2020-01-21','2020-01-22','2020-01-22','2020-01-22'],'price':[101,202,303,102,242,403,204,420,422]}
df = pd.DataFrame(data)
df['return'] = df.groupby('stock')['price'].pct_change()
df = df.dropna(how='any')
print(df)

输出:

  stock        date  price    return
3   abc  2020-01-21    102  0.009901
4   efg  2020-01-21    242  0.198020
5   xyz  2020-01-21    403  0.330033
6   abc  2020-01-22    204  1.000000
7   efg  2020-01-22    420  0.735537
8   xyz  2020-01-22    422  0.047146

【讨论】:

    【解决方案3】:

    假设 df_ret 没有索引,我会取消堆叠并重新堆叠。

    df_ret.set_index(['date', 'stock'], inplace=True)
    df_ret = df_ret.unstack(axis=0,level='stock')
    rets = df_ret.pct_change()
    rets=rets.stack()
    rets.reset_index(inplace=True)
    

    【讨论】:

      【解决方案4】:

      试试这个简单的解决方案:

      df['change_in_pct'] = (df.price - df.price.shift(1)) /df.price
      

      【讨论】:

        猜你喜欢
        • 2020-06-30
        • 2019-09-27
        • 2023-04-01
        • 1970-01-01
        • 2019-10-27
        • 2018-12-04
        • 1970-01-01
        • 1970-01-01
        • 2018-08-10
        相关资源
        最近更新 更多