【问题标题】:Logarithmic returns in pandas dataframe熊猫数据框中的对数回报
【发布时间】:2015-07-08 08:38:51
【问题描述】:

Python pandas 有一个 pct_change 函数,我用它来计算数据框中股票价格的回报:

ndf['Return']= ndf['TypicalPrice'].pct_change()

我正在使用以下代码来获得对数返回,但它给出的值与 pct.change() 函数完全相同:

ndf['retlog']=np.log(ndf['TypicalPrice'].astype('float64')/ndf['TypicalPrice'].astype('float64').shift(1))
#np is for numpy

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是使用.shift() 计算日志回报的一种方法。结果与pct_change()计算的总回报相似但不同。您可以上传您的示例数据的副本(保管箱共享链接)以重现您看到的不一致之处吗?

    import pandas as pd
    import numpy as np
    
    np.random.seed(0)
    df = pd.DataFrame(100 + np.random.randn(100).cumsum(), columns=['price'])
    df['pct_change'] = df.price.pct_change()
    df['log_ret'] = np.log(df.price) - np.log(df.price.shift(1))
    
    Out[56]: 
           price  pct_change  log_ret
    0   101.7641         NaN      NaN
    1   102.1642      0.0039   0.0039
    2   103.1429      0.0096   0.0095
    3   105.3838      0.0217   0.0215
    4   107.2514      0.0177   0.0176
    5   106.2741     -0.0091  -0.0092
    6   107.2242      0.0089   0.0089
    7   107.0729     -0.0014  -0.0014
    ..       ...         ...      ...
    92  101.6160      0.0021   0.0021
    93  102.5926      0.0096   0.0096
    94  102.9490      0.0035   0.0035
    95  103.6555      0.0069   0.0068
    96  103.6660      0.0001   0.0001
    97  105.4519      0.0172   0.0171
    98  105.5788      0.0012   0.0012
    99  105.9808      0.0038   0.0038
    
    [100 rows x 3 columns]
    

    【讨论】:

    • 我在 pct_change() 和 log_ret 中得到了很多完全相同的值,还有一些值略有不同。这是意料之中的吗?
    • @AmanArora 是的,这是预期的行为。当您的总回报很小(比如不到 1%)时,对数回报和总回报非常接近。它可以通过 0 附近的二阶泰勒展开在数学上证明。
    • @AmanArora 顺便说一句,对数回报具有随时间累加的期望属性(但不是对不同资产的累加),而当您计算加权平均投资组合回报时,总回报最合适(即对不同资产的累加,但不随时间累加)。
    • 这样计算log两次,而不是使用.diff()
    • @poulter7 .dif() 提供两行之间的绝对变化。还要注意np.log(df.price) - np.log(df.price.shift(1))等价于np.log(df.price / df.price.shift(1))(一次日志操作)
    【解决方案2】:

    对数返回只是 1 的自然对数加上算术返回。那么这个怎么样?

    df['pct_change'] = df.price.pct_change()
    df['log_return'] = np.log(1 + df.pct_change)
    

    更简洁,利用Ximix的建议:

    df['log_return'] = np.log1p(df.price.pct_change())
    

    【讨论】:

    • 也许你可以使用 np.log1p: df['log_return'] = np.log1p(df.pct_change)
    • 这在数学上肯定是不正确的“对数返回只是 1 的自然对数加上算术返回。”
    • 我做错了什么?或者,我意思要说什么?
    【解决方案3】:

    单行,只计算一次日志。 首先转换为对数空间,然后取 1 周期差异。

        np.diff(np.log(df.price))
    

    在 numpy 的早期版本中:

        np.log(df.price)).diff()
    

    【讨论】:

    • 它可以工作,但显示 PyLint 消息“'ndarray' 的实例没有 'diff' 成员”
    • 这突出了 numpy API 的一个变化,.diff() 在最新版本的 numpy 中的数组本身上不可用。相反, np.diff 是首选方法。更新了答案以反映这一点。
    【解决方案4】:

    结果可能看起来相似,但这仅仅是因为Taylor expansion for the logarithm。由于log(1 + x) ~ x,结果可能相似。

    然而,

    我正在使用以下代码来获得对数返回,但它给出的值与 pct.change() 函数完全相同。

    不完全正确。

    import pandas as pd
    
    df = pd.DataFrame({'p': range(10)})
    
    df['pct_change'] = df.pct_change()
    df['log_stuff'] = \
        np.log(df['p'].astype('float64')/df['p'].astype('float64').shift(1))
    df[['pct_change', 'log_stuff']].plot();
    

    【讨论】:

      【解决方案5】:

      @保尔特7: 我无法评论其他答案,所以我将其发布为新答案:小心

      np.log(df.price).diff() 
      

      因为这对于可能变为负数的指数以及风险因素(例如负利率。在这些情况下

      np.log(df.price/df.price.shift(1)).dropna()
      

      是首选,根据我的经验,通常是更安全的方法。它也只计算一次对数。

      您使用 +1 还是 -1 取决于您的时间序列的顺序。对降序使用 -1,对升序使用 +1 - 在这两种情况下,班次都会提供前一个日期的值。

      【讨论】:

      • 这很有趣,这里有两种方法,np.log(1+s.pct_change())np.log(s/s.shift(1)),它们是等价的,一旦序列进入负值区域,日志返回就开始变得有意义了。或np.log(s).diff())(np.log(s) - np.log(s.shift(1)),它们明确放弃负回报。
      猜你喜欢
      • 2023-03-11
      • 2020-03-12
      • 2018-05-13
      • 1970-01-01
      • 2022-07-22
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 2021-11-09
      相关资源
      最近更新 更多