如何计算 pandas 的年回报率

问题描述 投票:0回答:2

所以我一直在研究 SP500 年回报率,并使用从我的 quandl 订阅中下载的信息。我已经使用 resample() 和 pct_change() 来研究数据,但由于某种原因,我的结果没有达到预期。

sp500_df = quandl.get("MULTPL/SP500_REAL_PRICE_MONTH", authtoken="YOUR OWN AUTH KEY")
sp500_Y_ret_df = sp500_df['Value'].resample('Y').mean().pct_change().dropna()

标普 500 指数 2008 年底回报率的预期值应为 -38.5%,但出于某种原因我的代码显示 -17%?如果出于某种原因您无法访问数据,我可以为数据提供一个 .csv 文件。感谢一百万的帮助。

sp500_Y_ret_df.loc['2008-12-31']

输出:

-0.17319465450687388

过去20年:

sp500_Y_ret_df.tail(20)

输出:

2001-12-31   -0.164631
2002-12-31   -0.164795
2003-12-31   -0.032081
2004-12-31    0.173145
2005-12-31    0.067678
2006-12-31    0.085836
2007-12-31    0.126625
2008-12-31   -0.173195
2009-12-31   -0.224552
2010-12-31    0.203406
2011-12-31    0.113738
2012-12-31    0.087221
2013-12-31    0.190603
2014-12-31    0.175436
2015-12-31    0.067610
2016-12-31    0.014868
2017-12-31    0.170363
2018-12-31    0.121093
2019-12-31    0.065247
2020-12-31    0.061747
Freq: A-DEC, Name: Value, dtype: float64

使用随机数据:

aapl_df = pd.DataFrame({ 
'ticker':np.repeat( ['aapl'], 2500 ),
'date':pd.date_range('1/1/2011', periods=2500, freq='D'),
'price':(np.random.randn(2500).cumsum() + 10) }).set_index('date')
aapl_df.head()

date        
2011-01-01  aapl    9.011290
2011-01-02  aapl    9.092603
2011-01-03  aapl    9.139830
2011-01-04  aapl    7.782112
2011-01-05  aapl    8.316270

如前所述使用“最后”产生了更接近的结果,但不确定这是否纯粹是运气

aapl_Y_ret_df = aapl_df['price'].resample('Y').last()
aapl_Y_ret_df.tail()

输出

    date
2013-12-31    18.535328
2014-12-31    15.201832
2015-12-31    36.040411
2016-12-31    42.272464
2017-12-31    20.421079
Freq: A-DEC, Name: price, dtype: float64

--

aapl_Y_ret_df = aapl_df['price'].resample('Y').last().pct_change()
aapl_Y_ret_df.tail()
date
2013-12-31    0.569359
2014-12-31   -0.179846
2015-12-31    1.370794
2016-12-31    0.172918
2017-12-31   -0.516918
Freq: A-DEC, Name: price, dtype: float64
python pandas finance quandl
2个回答
2
投票
  • 这回答了如何计算
    'Adj Close'
    的年度百分比变化的问题,这正是 OP 想要的。
  • 通过找到
    Close
    Adj Close
    的每日百分比变化,然后
    sum
    并乘以100来计算年回报。
  • 使用
    groupby
    按年获取值。
  • df['Adj Close'].resample('Y').mean()
    返回每年
    'Adj Close'
    值的平均值,这不是确定年度回报的方法。
    • 2007 年至 2008 年平均收盘价的百分比变化为
      -17.4%
      。这不是回报。
import yfinance as yf
import pandas as pd

# load S&P 500 data
df = yf.download('^gspc', start='2000-01-01', end='2020-01-01').reset_index()

# display(df)
        Date         High          Low         Open        Close      Volume    Adj Close
0 2000-01-03  1478.000000  1438.359985  1469.250000  1455.219971   931800000  1455.219971
1 2000-01-04  1455.219971  1397.430054  1455.219971  1399.420044  1009000000  1399.420044
2 2000-01-05  1413.270020  1377.680054  1399.420044  1402.109985  1085500000  1402.109985
3 2000-01-06  1411.900024  1392.099976  1402.109985  1403.449951  1092300000  1403.449951
4 2000-01-07  1441.469971  1400.729980  1403.449951  1441.469971  1225200000  1441.469971

# groupby year and determine the daily percent change by year, and add it as a column to df
df['pct_ch'] = df.groupby(df.Date.dt.year)['Adj Close'].apply(pd.Series.pct_change)

# groupby year and aggregate sum of pct_ch to get the yearly return
yearly_pct_ch = df.groupby(df.Date.dt.year)['pct_ch'].sum().mul(100).reset_index().rename(columns={'pct_ch': 'cum_pct_ch_year'})

# display(yearly_pct_ch)
    Date  cum_pct_ch_year
0   2000        -7.274088
1   2001        -8.890805
2   2002       -23.811947
3   2003        21.552072
4   2004         9.535574
5   2005         4.295586
6   2006        11.626670
7   2007         4.860178
8   2008       -38.702107
9   2009        21.622674
10  2010        12.052038
11  2011         1.575069
12  2012        11.840560
13  2013        24.012739
14  2014        12.320664
15  2015         0.501799
16  2016        11.494988
17  2017        17.127082
18  2018        -5.822426
19  2019        26.031938

-1
投票

认可的答案实际上是错误的答案。说到财务数据,也需要一点数学知识。

假设您有每日回报。要计算年回报率,您实际上应该将日回报率复合起来。

例如,假设您在第 1 天投资了 10 美元。接下来两天的收益分别是10%和10%

  1. 您在第 1 天结束时的最终价值将是 10 美元的 10%,即 11 美元。
  2. 您在第 2 天结束时的最终价值将为 11 美元的 10%,即 12.1 美元。
  3. 退货为 2.1 美元。

现在,如果你简单地总结回报值,你会得到错误的答案。 10% + 10% = 20%。并且,10 美元的 20% 是 2 美元。这是作者在上面的回答中提出的建议,这是错误的。

相反,请按照以下步骤操作:

  1. 通过将每日回报除以 100 来标准化每日回报,即
    10%/100 = 0.1
    .
  2. 在标准日回报率上加 1,即
    1 + 0.1
    。您将分别获得 1.1 和 1.1,用于 2 天的回报。
  3. 乘以所有每日回报即
    1.1 * 1.1 = 1.21
    .
  4. 从乘积中减去 1 即
    1.21 - 1 = 0.21
    .
  5. 将值乘以 100 即
    0.21*100 = 21%
    .

这是您在 2 天后的最后一次返回。让我们检查一下:10 美元的 21% 是 2.1 美元。

熊猫代码:

# only if needed
df['daily_returns'] /= 100.0

daily_returns_compounded = df['daily_returns'] + 1

annual_return = daily_returns_compounded.prod()

annual_return -= - 1

# only if needed
annual_return *= 100 

如果你有多年的数据,使用groupby()

© www.soinside.com 2019 - 2024. All rights reserved.