【问题标题】:Calculate Daily Returns with Pandas DataFrame使用 Pandas DataFrame 计算每日收益
【发布时间】:2013-11-28 19:48:30
【问题描述】:

这是我的 Pandas 数据框:

prices = pandas.DataFrame([1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 
              1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42,
              1036.24, 1015.00, 1015.20])

这是我的daily_return 函数:

def daily_return(prices):
    return prices[:-1] / prices[1:] - 1

这是来自此函数的输出:

0    NaN
1      0
2      0
3      0
4      0
5      0
6      0
7      0
8      0
9      0
10     0
11     0
12     0
13     0
14   NaN

为什么我有这个输出?

【问题讨论】:

    标签: python python-3.x pandas


    【解决方案1】:

    我喜欢以上所有方法。但是,我们也可以这样做:

    daily_returns = (prices/prices.shift(1)) -1
    daily_returns.iloc[0,:] = 0
    

    *prices 是 pandas 数据框,daily_returns 将是 Series 对象。

    【讨论】:

      【解决方案2】:

      只是对@YaOzl 的回答的一点补充,以防有人会读到这个。 如果您的退货数据是包含多只股票的面板电子表格:

      >>> prices = pandas.DataFrame(
      {"StkCode":["StockA","StockA","StockA","StockA","StockA","StockB","StockB","StockB","StockB","StockB","StockC","StockC","StockC","StockC","StockC",], 
      "Price":[1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42, 1036.24, 1015.00, 1015.20]}
      )
      

      这给了你:

            Price StkCode
      0   1035.23  StockA
      1   1032.47  StockA
      2   1011.78  StockA
      3   1010.59  StockA
      4   1016.03  StockA
      5   1007.95  StockB
      6   1022.75  StockB
      7   1021.52  StockB
      8   1026.11  StockB
      9   1027.04  StockB
      10  1030.58  StockC
      11  1030.42  StockC
      12  1036.24  StockC
      13  1015.00  StockC
      14  1015.20  StockC
      

      那么您可以简单地将 .pct_change(k).groupby(StkCode) 结合使用。 而且它比使用迭代器快千倍...(我在我的数据集上进行了尝试,成功地将处理时间从 10 小时缩短到 20 秒!!

      >>> prices["Return"] = prices.groupby("StkCode")["Price"].pct_change(1)
      

      给你:

            Price StkCode    Return
      0   1035.23  StockA       NaN
      1   1032.47  StockA -0.002666
      2   1011.78  StockA -0.020039
      3   1010.59  StockA -0.001176
      4   1016.03  StockA  0.005383
      5   1007.95  StockB       NaN
      6   1022.75  StockB  0.014683
      7   1021.52  StockB -0.001203
      8   1026.11  StockB  0.004493
      9   1027.04  StockB  0.000906
      10  1030.58  StockC       NaN
      11  1030.42  StockC -0.000155
      12  1036.24  StockC  0.005648
      13  1015.00  StockC -0.020497
      14  1015.20  StockC  0.000197
      

      【讨论】:

        【解决方案3】:

        为什么不用pandas默认提供的非常方便的pct_change方法:

        import pandas as pd
        
        prices = pandas.DataFrame([1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 
                  1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42,
                  1036.24, 1015.00, 1015.20])
        
        daily_return = prices.pct_change(1) # 1 for ONE DAY lookback
        monthly_return = prices.pct_change(21) # 21 for ONE MONTH lookback
        annual_return = prices.pct_change(252) # 252 for ONE YEAR lookback
        

        原创 prices:

        print(prices)
                  0                                                                    
        0   1035.23                                                                    
        1   1032.47                                                                    
        2   1011.78                                                                    
        3   1010.59                                                                    
        4   1016.03                                                                    
        5   1007.95                                                                    
        6   1022.75                                                                    
        7   1021.52                                                                    
        8   1026.11                                                                    
        9   1027.04                                                                    
        10  1030.58                                                                    
        11  1030.42                                                                    
        12  1036.24                                                                    
        13  1015.00                                                                    
        14  1015.20                                                                    
        

        每日返回作为prices.pct_change(1)

        print(prices.pct_change(1))
                   0                                                                   
        0        NaN                                                                   
        1  -0.002666                                                                   
        2  -0.020039                                                                   
        3  -0.001176                                                                   
        4   0.005383                                                                   
        5  -0.007953                                                                   
        6   0.014683                                                                   
        7  -0.001203                                                                   
        8   0.004493                                                                   
        9   0.000906                                                                   
        10  0.003447                                                                   
        11 -0.000155                                                                   
        12  0.005648                                                                   
        13 -0.020497                                                                   
        14  0.000197 
        

        【讨论】:

        • 当你的数据是 asc. (2016-01-03、2016-01-02等)使用:df['Adj Close'].pct_change(-1)
        • 知道为什么 pct_change 的答案与刚刚做的略有不同:newValue - oldValue / newValue 例如 (1032.47 - 1035.23) / 1032.47 给出 -0.0026732 而不是 pct_change 给出的 -0.002666 答案?
        • 你必须除以层值,而不是最终值...正确答案是:(1032.47 - 1035.23) / 1035.23 = -0.002666
        • 我知道这是一个旧答案,但文档没有说明您在 pct_change 中使用的值,1 表示每日,21 表示每月,252 表示每年。您能否解释一下这是如何工作的,或者这些值是指该问题的特定时期?
        • @IshanSharma 这都是关于“context”的。当我们谈论股市时,1、21、252 是正确的时期,因为股市并非每天都在交易
        【解决方案4】:

        因为操作会对索引进行对齐,所以您可以将其中一个 DataFrame 转换为数组:

        prices[:-1].values / prices[1:] - 1
        

        prices[:-1] / prices[1:].values - 1
        

        取决于你想要的结果的索引。

        或者使用shift()方法:

        prices.shift(1) / prices - 1
        

        和:

        prices / prices.shift(1) - 1
        

        【讨论】:

        • shift 比下降到values 要好得多。
        • 小心;取决于您的价格数据如何按日期(asc、desc)排序,班次示例将是错误的。 prices / prices.shift(1) - 1 用于升序。 (Date,SPY,XOM 2012-07-02,136.51,84.79 2012-07-03,137.41,85.72) 等等
        • @mimoralea 所以降序是df['Adj Close'] / df['Adj Close'].shift(-1) - 1 对吧?!?
        猜你喜欢
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        相关资源
        最近更新 更多