3、收益率计算:简单收益率 vs 对数收益率,为什么量化分析中常用对数收益率?

说到收益率计算,这其实是量化分析里最基础、也最容易踩坑的地方。我刚开始做回测那会儿,就吃过简单收益率的亏。当时回测结果看起来漂亮得很,结果一细算,时间加总时全对不上。嗯,今天咱们就把这个事儿彻底聊透。

3.1 两种收益率,到底差在哪儿?

先看定义。说白了,简单收益率就是你赚了多少钱,除以你投入的本金。而对数收益率,是取价格比值的自然对数。

公式长这样:

简单收益率:R_simple = (P_t - P_{t-1}) / P_{t-1}
对数收益率:R_log = ln(P_t / P_{t-1})

举个例子。假设某资产昨天价格100元,今天涨到110元。

  • 简单收益率 = (110 - 100) / 100 = 10%
  • 对数收益率 = ln(110 / 100) ≈ 9.53%

你看,数值上差了一点点。但别小看这点差异,在长期回测里,它会越滚越大。

3.2 为什么量化圈都爱用对数收益率?

我个人习惯用对数收益率,原因有三点。这可不是拍脑袋,是实打实的数学优势。

第一:时间可加性

这是最核心的一点。简单收益率不能直接相加,你想想看:

  • 第一天涨10%,第二天跌10%。简单收益率加起来是0%,但实际你亏了1%。
  • 对数收益率呢?ln(1.1) + ln(0.9) ≈ 0.0953 - 0.1054 = -0.0101,正好对应实际亏损。

我在项目中遇到过,有人用简单收益率算累计收益,结果回测曲线和实际净值对不上。查了半天,问题就出在这儿。

核心结论:对数收益率可以跨时间直接相加,简单收益率不行。

第二:分布更接近正态

金融资产的价格通常不是正态分布的,但收益率呢?

简单收益率有下限(最多亏-100%),上限却可以无限大。这种不对称性让统计建模很麻烦。而对数收益率,取值范围是整个实数轴,左右对称,更接近正态分布。

说白了,你用对数收益率做回归、做风险模型,数学性质好得多。

第三:跨资产可比性

假设你有两只股票,A从10元涨到11元,B从100元涨到110元。

  • 简单收益率:A涨10%,B涨10% — 看起来一样
  • 对数收益率:A是ln(11/10)≈9.53%,B也是ln(110/100)≈9.53%

这里两者一致。但如果你做多资产组合,不同资产价格差异很大时,对数收益率的统计特性更稳定。

3.3 什么时候该用简单收益率?

别以为对数收益率万能。我建议你记住这个原则:

场景 推荐用哪种 原因
计算组合收益率 简单收益率 组合收益率是各资产收益率的加权平均,简单收益率更直观
时间序列分析 对数收益率 可加性、正态性、统计建模方便
风险度量(VaR等) 对数收益率 分布假设更合理
向客户汇报业绩 简单收益率 客户能听懂“我赚了10%”
我的小技巧:内部计算全用对数收益率,最后展示结果时转成简单收益率。这样既保证了数学严谨性,又让报告好理解。

3.4 代码实现:两种收益率计算

来,直接上代码。这是我在实际回测框架里用的函数:

import numpy as np
import pandas as pd

def calculate_returns(prices, method='log'):
    """
    计算收益率序列
    
    参数:
        prices: 价格序列 (Series或DataFrame)
        method: 'log' 或 'simple'
    
    返回:
        收益率序列
    """
    if method == 'log':
        # 对数收益率
        returns = np.log(prices / prices.shift(1))
    elif method == 'simple':
        # 简单收益率
        returns = prices.pct_change()
    else:
        raise ValueError("method 必须是 'log' 或 'simple'")
    
    # 去掉第一行的NaN
    return returns.dropna()

# 示例
prices = pd.Series([100, 102, 101, 105, 110],
                   index=pd.date_range('2024-01-01', periods=5))

log_ret = calculate_returns(prices, 'log')
simple_ret = calculate_returns(prices, 'simple')

print("对数收益率:")
print(log_ret)
print("\n简单收益率:")
print(simple_ret)
避坑指南:我曾经在回测框架里直接用简单收益率累加,结果累计收益算出来比实际高了3%。后来发现是时间加总的问题。记住:计算累计收益时,一定要用对数收益率相加,或者用简单收益率做复利计算((1+R1)*(1+R2)...-1)。

3.5 两者转换:一个实用技巧

有时候你需要来回切换。转换公式很简单:

# 简单收益率 → 对数收益率
log_return = np.log(1 + simple_return)

# 对数收益率 → 简单收益率
simple_return = np.exp(log_return) - 1

这个转换在构建多资产组合时特别有用。我一般这样处理:

  1. 各资产收益率统一用对数形式计算
  2. 做统计分析、建模
  3. 需要展示或计算组合收益时,转回简单形式

3.6 一张图看懂核心逻辑

下面这张SVG图,把两种收益率的区别和应用场景梳理清楚了:

收益率计算:核心逻辑对比 简单收益率 对数收益率 公式: (P_t - P_{t-1}) / P_{t-1} 范围: [-1, +∞) 时间不可加 公式: ln(P_t / P_{t-1}) 范围: (-∞, +∞) 时间可加 ✓ 适用场景 适用场景 • 组合收益率加权计算 • 向客户汇报业绩 • 单期收益展示 • 时间序列分析 • 风险度量 (VaR) • 统计建模与回归

这张图把核心逻辑说得很清楚了。简单收益率适合单期、展示场景;对数收益率适合建模、分析场景。两者不是谁替代谁,而是各司其职。

3.7 我的建议

如果你刚开始做量化回测,我建议你:

  • 默认用对数收益率做内部计算和建模
  • 只在展示和组合加权时转成简单收益率
  • 写代码时封装好转换函数,避免手算出错

记住一句话:对数收益率是给机器和模型看的,简单收益率是给人看的。搞清楚这个,你的回测框架就稳了一半。

一句话总结:量化分析用对数收益率,因为时间可加、分布对称、统计性质好。但别迷信它,该用简单收益率的时候也别犹豫。

专注资料整理