【问题标题】:Calculating returns from a dataframe with financial data使用财务数据计算数据框的回报
【发布时间】:2012-11-03 08:28:09
【问题描述】:

我有一个包含每月财务数据的数据框:

In [89]: vfiax_monthly.head()
Out[89]: 
            year  month  day       d   open  close   high    low  volume  aclose
2003-01-31  2003      1   31  731246  64.95  64.95  64.95  64.95       0   64.95
2003-02-28  2003      2   28  731274  63.98  63.98  63.98  63.98       0   63.98
2003-03-31  2003      3   31  731305  64.59  64.59  64.59  64.59       0   64.59
2003-04-30  2003      4   30  731335  69.93  69.93  69.93  69.93       0   69.93
2003-05-30  2003      5   30  731365  73.61  73.61  73.61  73.61       0   73.61

我正在尝试这样计算回报:

In [90]: returns = (vfiax_monthly.open[1:] - vfiax_monthly.open[:-1])/vfiax_monthly.open[1:]

但我只得到零:

In [91]: returns.head()
Out[91]: 
2003-01-31   NaN
2003-02-28     0
2003-03-31     0
2003-04-30     0
2003-05-30     0
Freq: BM, Name: open

我认为这是因为算术运算在索引上对齐,这使得 [1:][:-1] 无用。

我的解决方法是:

In [103]: returns = (vfiax_monthly.open[1:].values - vfiax_monthly.open[:-1].values)/vfiax_monthly.open[1:].values

In [104]: returns = pd.Series(returns, index=vfiax_monthly.index[1:])

In [105]: returns.head()
Out[105]: 
2003-02-28   -0.015161
2003-03-31    0.009444
2003-04-30    0.076362
2003-05-30    0.049993
2003-06-30    0.012477
Freq: BM

有没有更好的方法来计算回报?我不喜欢先转换为数组,然后再转换为 Series。

【问题讨论】:

    标签: pandas finance


    【解决方案1】:

    使用.shift 来移动数据帧/系列中值的索引位置,而不是切片。例如:

    returns = (vfiax_monthly.open - vfiax_monthly.open.shift(1))/vfiax_monthly.open.shift(1)
    

    这就是pct_change 在引擎盖下所做的事情。您还可以将其用于其他功能,例如:

    (3*vfiax_monthly.open + 2*vfiax_monthly.open.shift(1))/5
    

    您可能还想研究 rollingwindow 函数以进行其他类型的财务数据分析。

    【讨论】:

    • 这就是我要找的东西!
    • 我认为第一行应该是:returns = (vfiax_monthly.open - vfiax_monthly.open.shift(1))/vfiax_monthly.open.shift(1)
    【解决方案2】:

    最简单的方法是使用 DataFrame.pct_change() 方法。

    这是一个简单的例子

    In[1]: aapl = get_data_yahoo('aapl', start='11/1/2012', end='11/13/2012')
    
    In[2]: appl
    Out[2]: 
              Open    High     Low   Close    Volume  Adj Close
    Date                                                           
    2012-11-01  598.22  603.00  594.17  596.54  12903500     593.83
    2012-11-02  595.89  596.95  574.75  576.80  21406200     574.18
    2012-11-05  583.52  587.77  577.60  584.62  18897700     581.96
    2012-11-06  590.23  590.74  580.09  582.85  13389900     580.20
    2012-11-07  573.84  574.54  555.75  558.00  28344600     558.00
    2012-11-08  560.63  562.23  535.29  537.75  37719500     537.75
    2012-11-09  540.42  554.88  533.72  547.06  33211200     547.06
    2012-11-12  554.15  554.50  538.65  542.83  18421500     542.83
    2012-11-13  538.91  550.48  536.36  542.90  19033900     542.90
    
    In[3]: aapl.pct_change()
    Out[3]:
                    Open      High       Low     Close    Volume  Adj Close
    Date                                                                   
    2012-11-01       NaN       NaN       NaN       NaN       NaN        NaN
    2012-11-02 -0.003895 -0.010033 -0.032684 -0.033091  0.658945  -0.033090
    2012-11-05 -0.020759 -0.015378  0.004959  0.013558 -0.117186   0.013550
    2012-11-06  0.011499  0.005053  0.004311 -0.003028 -0.291453  -0.003024
    2012-11-07 -0.027769 -0.027423 -0.041959 -0.042635  1.116864  -0.038263
    2012-11-08 -0.023020 -0.021426 -0.036815 -0.036290  0.330747  -0.036290
    2012-11-09 -0.036049 -0.013073 -0.002933  0.017313 -0.119522   0.017313
    2012-11-12  0.025406 -0.000685  0.009237 -0.007732 -0.445323  -0.007732
    2012-11-13 -0.027502 -0.007250 -0.004251  0.000129  0.033244   0.000129
    

    【讨论】:

    • 我喜欢这个解决方案。但它特定于我的用例。如果我想计算每两个月之间的平均值(或没有内置 pandas 函数的复杂事物)怎么办:(vfiax_monthly.open[1:] - vfiax_monthly.open[:-1])/2
    • 您能否在原始帖子中添加一个“复杂的东西”示例?假设您有一个定期频率的DateTimeIndex,您总是可以使用df.resample 以另一个定期频率(例如每两个月)聚合数据,然后使用df.pct_change() 来获得回报。 pct_change() [参见 periods, freq] 也有各种选项,允许您指定应该使用多少数据点来计算回报(periods 默认为 1,这就是解决方案给出的原因与您的功能相同的答案)。
    • (vfiax_monthly.open[1:] + vfiax_monthly.open[:-1])/2 是一个例子,尽管可能存在某种窗口均值函数。但假设我需要:(3*vfiax_monthly.open[1:] + 2*vfiax_monthly.open[:-1])/5。现在我意识到结果索引的选择是任意的,所以我正在寻找的魔法函数可能不存在。
    • (vfiax_monthly.open[1:] - vfiax_monthly.open[:-1])/vfiax_monthly.open[1:] 不是百分比变化,而是投资回报。百分比变化是当前行除以前一行,相当于 vfiax_monthly.open[1:]/vfiax_monthly.open[:-1]-1 所以无论如何 pct_change() 都是错误的。
    【解决方案3】:

    在没有任何偏差的情况下计算前瞻性回报的最佳方法是使用内置函数pd.DataFrame.pct_change()。在您的情况下,您只需要使用此功能,因为您有月度数据,并且您正在寻找月度回报。

    例如,如果您想查看 6 个月的回报,您只需设置参数 df.pct_change(periods = 6),这将为您提供 6 个月的回报率。

    因为您的数据集相对较小,最简单的方法是对您需要计算数据的参数重新采样,然后再次使用pct_change() 函数。

    但是,由于log 的良好属性,通常使用该公式来计算收益(如果您计划计算收益系列的统计数据):

    你会这样实现:

    log_return = np.log(vfiax_monthly.open / vfiax_monthly.open.shift())

    【讨论】:

    • 这是金融专业人士的回答。
    【解决方案4】:

    还可以混合使用 pandas 系列的 diffshift 方法:

    retrun = vfiax_monthly.open.diff()/vfiax_monthly.open.shift(1)
    

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-20
      相关资源
      最近更新 更多