Strasmore Research
学习 Matt Connor作者: Matt Connor

夏普比率中的无风险利率怎么选

了解无风险利率为何随时间变化,如何将国库券收益率匹配到回报频率,以及使用单一固定利率会让夏普比率付出什么代价。

夏普比率中的无风险利率,是指在不承担被评估风险的情况下,在相同期间内本可获得的回报。它是一组时间序列,每个期间对应一个数值,并以回报所使用的货币计价。其频率应与回报频率一致,并逐期相减。只在最后进行一次年化。

大多数已发布的夏普比率,错误都出在跳过了这一步。有人从二十年的回报历史中直接取一个数,通常是本周国库券的收益率,却让2009年和2024年面对同样的门槛利率。我们的夏普比率指南介绍该比率衡量的内容。本页讨论的是几乎没有人记录的输入数据。

无风险利率不是常数

覆盖二十年的夏普比率,实际跨越了一段利率历史。下图采用三个月期国库券,将每个日历年的数据汇总为平均值及其波动范围。

查询按日历年列示的三个月期国库券收益率
每个数字背后的完整 SQL
SELECT
    toString(toYear(date))                  AS year,
    round(avg(toFloat64(yield_3_month)), 2) AS avg_bill_pct,
    round(min(toFloat64(yield_3_month)), 2) AS low_bill_pct,
    round(max(toFloat64(yield_3_month)), 2) AS high_bill_pct
FROM global_markets.treasury_yields
WHERE date >= '2005-01-01'
  AND yield_3_month IS NOT NULL
GROUP BY year
ORDER BY year
Run this yourself

年度平均值在3.22%达到2005,在3.74%达到2026,覆盖22个日历年。两点之间的路径才是关键。利率先降至底部,在近十年时间里维持低位,随后重新上升。最低值和最高值两列显示了利率在单个年度内的波动幅度。这也是为什么即使是一年期夏普比率,也应使用匹配的利率序列,而不是单一报价。

夏普比率应采用哪种无风险利率

四项特征决定了选择。

  1. 短期限。该利率在一个测量期间内必须接近确定。三个月期国库券适合月度计算。十年期国债则不适合,因为其价格会在测量月份内波动。
  2. 与回报相同的货币。以欧元计价的策略,应与欧元国库券进行比较。
  3. 与回报相同的频率。国库券收益率通常按年报价,因此在用于月度回报之前,必须先将年度报价转换为月度利率。
  4. 两边采用可比的回报定义。国库券收益率代表其全部回报。因此,不包含股息的策略回报并未在同一口径下进行比较。价格回报与总回报介绍这一差异。

第三点涉及两种常见转换方法。简单除法是将年度报价除以十二。复利法则是取一加年度利率的十二次方根。在假设国库券收益率为5%的情况下,两种方法得出的月度利率分别为0.4167%和0.4074%。每月相差约一个基点,并会在整个样本期间反复出现。本文图表采用复利法。如果您将国库券利息视为持有收益,而不是门槛利率,股息率与国债收益率闲置现金的配置方式对此有详细说明。

如何构建月度超额回报序列

构建过程是机械性的:取每个月的最后收盘价,计算当月回报;将当月国库券报价转换为月度利率;然后进行相减。最终得到的是超额回报序列,每个月对应一个数值。月度回报的计算方法详细介绍了回报部分。

查询2020至2024年月度回报、月度无风险利率及超额回报
每个数字背后的完整 SQL
WITH
    monthly_px AS
    (
        SELECT
            toStartOfMonth(date)           AS m,
            argMax(toFloat64(close), date) AS month_close
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'SPY'
          AND date >= '2019-12-01'
          AND date <  '2025-01-01'
        GROUP BY m
    ),
    prior_px AS
    (
        SELECT
            addMonths(m, 1) AS m,
            month_close     AS prev_close
        FROM monthly_px
    ),
    monthly_rf AS
    (
        SELECT
            toStartOfMonth(date)                                       AS m,
            pow(1 + avg(toFloat64(yield_3_month)) / 100, 1.0 / 12) - 1 AS rf_month
        FROM global_markets.treasury_yields
        WHERE date >= '2019-12-01'
          AND date <  '2025-01-01'
          AND yield_3_month IS NOT NULL
        GROUP BY m
    )
SELECT
    toString(cur.m)                                                      AS month,
    round(100 * (cur.month_close / prv.prev_close - 1), 2)               AS spy_ret_pct,
    round(100 * rf.rf_month, 3)                                          AS rf_pct,
    round(100 * (cur.month_close / prv.prev_close - 1 - rf.rf_month), 2) AS excess_pct
FROM monthly_px AS cur
INNER JOIN prior_px AS prv ON prv.m = cur.m
INNER JOIN monthly_rf AS rf ON rf.m = cur.m
ORDER BY cur.m
Run this yourself

这些是SPY的收盘价,因此回报列是未计股息的价格回报。图中首个月份的无风险利率为0.128%,最后一个月为0.359%。与波动幅度达到数个百分点的股票月度回报相比,无风险利率序列看起来只是四舍五入误差。在60个月的相减计算中,它却构成了两个声称衡量同一对象的夏普比率之间的全部差异。

先相减,再年化

在序列对齐后,有两种计算顺序,但结果并不相同。先计算超额回报:从月度回报中减去月度利率,再将超额回报序列年化。先年化:先将回报复合为年度数值,再将国库券回报复合为年度数值,最后用前者减去后者。

查询年化风险溢价:先减去月度值,或先分别年化
每个数字背后的完整 SQL
WITH
    monthly_px AS
    (
        SELECT
            toStartOfMonth(date)           AS m,
            argMax(toFloat64(close), date) AS month_close
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'SPY'
          AND date >= '2004-12-01'
          AND date <  '2025-01-01'
        GROUP BY m
    ),
    prior_px AS
    (
        SELECT
            addMonths(m, 1) AS m,
            month_close     AS prev_close
        FROM monthly_px
    ),
    monthly_rf AS
    (
        SELECT
            toStartOfMonth(date)                                       AS m,
            pow(1 + avg(toFloat64(yield_3_month)) / 100, 1.0 / 12) - 1 AS rf_month
        FROM global_markets.treasury_yields
        WHERE date >= '2004-12-01'
          AND date <  '2025-01-01'
          AND yield_3_month IS NOT NULL
        GROUP BY m
    ),
    excess AS
    (
        SELECT
            cur.m                                             AS m,
            cur.month_close / prv.prev_close - 1              AS ret,
            rf.rf_month                                       AS rf_month,
            cur.month_close / prv.prev_close - 1 - rf.rf_month AS exc
        FROM monthly_px AS cur
        INNER JOIN prior_px AS prv ON prv.m = cur.m
        INNER JOIN monthly_rf AS rf ON rf.m = cur.m
    )
SELECT
    concat(toString(intDiv(count(), 12)), '-year')            AS horizon,
    round(100 * (exp(12 * avg(log(1 + exc))) - 1), 2)         AS excess_first_pct,
    round(100 * ((exp(12 * avg(log(1 + ret))) - 1)
               - (exp(12 * avg(log(1 + rf_month))) - 1)), 2)  AS annualize_first_pct,
    round(100 * ((exp(12 * avg(log(1 + ret))) - 1)
               - (exp(12 * avg(log(1 + rf_month))) - 1)
               - (exp(12 * avg(log(1 + exc))) - 1)), 3)       AS gap_pct
FROM excess
CROSS JOIN (SELECT arrayJoin([1, 3, 5, 10, 20]) AS years) AS hz
WHERE m >= subtractYears(toDate('2025-01-01'), years)
GROUP BY years
ORDER BY years
Run this yourself

20-year期间内,先计算超额回报的方法得出年化6.49%,另一种顺序得出6.59%,两者相差0.099个百分点。在1-year期间内,两种计算结果相差0.814个百分点。在本文各个期间内,先年化的方法所得数值都高于先计算超额回报的方法。差异来自交叉项:将回报序列复合为年度数值时,会在风险溢价之上继续赚取国库券利率;之后再减去年化国库券利率,并不会把这部分收益剔除。交叉项与两个年化数值的乘积相关,因此国库券收益率越高,差异越大。

年化还存在第二种分歧。算术年化是将月度超额回报均值乘以十二。几何年化则进行复合,求出能够重现累计结果的恒定年度利率。假设有两个期间,回报先为+50%,再为-33.3%,最终恰好回到起点。算术平均值为每期+8.35%,几何平均值则为零。本文图表采用复利法。有一点值得注意:在算术年化下,月度平均回报乘以十二,再减去月度平均国库券利率乘以十二,在代数上等同于月度平均超额回报乘以十二。在这一约定下,相减顺序不会改变分子。但分母仍会变化,因为当利率本身发生变化时,超额回报的标准差将不同于原始回报的标准差。

单一固定利率会如何改变结果

常见的简化方法,是取当前国库券收益率,并从历史中的每个期间回报里都减去该利率。下图在五个结束日期相同的期间内,分别用两种方法计算夏普比率:一次采用匹配的月度利率序列,另一次采用该期间结束时有效的国库券收益率。

查询匹配利率序列与单一固定利率的夏普比率
每个数字背后的完整 SQL
WITH
    monthly_px AS
    (
        SELECT
            toStartOfMonth(date)           AS m,
            argMax(toFloat64(close), date) AS month_close
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'SPY'
          AND date >= '2004-12-01'
          AND date <  '2025-01-01'
        GROUP BY m
    ),
    prior_px AS
    (
        SELECT
            addMonths(m, 1) AS m,
            month_close     AS prev_close
        FROM monthly_px
    ),
    monthly_rf AS
    (
        SELECT
            toStartOfMonth(date)                                       AS m,
            pow(1 + avg(toFloat64(yield_3_month)) / 100, 1.0 / 12) - 1 AS rf_month
        FROM global_markets.treasury_yields
        WHERE date >= '2004-12-01'
          AND date <  '2025-01-01'
          AND yield_3_month IS NOT NULL
        GROUP BY m
    ),
    excess AS
    (
        SELECT
            cur.m                                AS m,
            cur.month_close / prv.prev_close - 1 AS ret,
            rf.rf_month                          AS rf_month
        FROM monthly_px AS cur
        INNER JOIN prior_px AS prv ON prv.m = cur.m
        INNER JOIN monthly_rf AS rf ON rf.m = cur.m
    )
SELECT
    concat(toString(intDiv(count(), 12)), '-year')                             AS horizon,
    round(sqrt(12) * avg(ret - rf_month) / stddevSamp(ret - rf_month), 2)      AS sharpe_matched_rf,
    round(sqrt(12) * avg(ret - rf_fixed) / stddevSamp(ret - rf_fixed), 2)      AS sharpe_fixed_rf,
    round(abs(sqrt(12) * avg(ret - rf_month) / stddevSamp(ret - rf_month)
            - sqrt(12) * avg(ret - rf_fixed) / stddevSamp(ret - rf_fixed)), 2) AS abs_gap
FROM excess
CROSS JOIN
(
    SELECT pow(1 + avg(toFloat64(yield_3_month)) / 100, 1.0 / 12) - 1 AS rf_fixed
    FROM global_markets.treasury_yields
    WHERE date >= '2024-12-01'
      AND date <  '2025-01-01'
      AND yield_3_month IS NOT NULL
) AS fixed_rate
CROSS JOIN (SELECT arrayJoin([1, 3, 5, 10, 20]) AS years) AS hz
WHERE m >= subtractYears(toDate('2025-01-01'), years)
GROUP BY years
ORDER BY years
Run this yourself

1-year期间内,两种结果相差0.07。在十二个月期间内,固定利率与该期间自身的平均利率之间几乎没有足够时间形成明显差异。在20-year期间内,两者相差0.18个百分点:匹配序列得出0.49,固定利率得出0.32。误差取决于所选单一利率与实际适用平均利率之间的距离。期间越长,该距离越有可能扩大。所有后续计算都会继承这一误差,而波动率目标与头寸规模正是基于这类输入数据运行的。

货币陷阱

如果策略以一种货币赚取回报,却与另一种货币的国库券进行比较,所得数值对任何一方都缺乏明确意义。应在同一货币内部计算超额回报:欧元回报对应欧元国库券,日元回报对应日元国库券。对冲策略还存在第二个陷阱。货币对冲的定价基于远期汇率,而远期点通常接近两种货币之间的利率差。这意味着,部分本币利率已经包含在对冲后的外币回报中。如果再减去外币国库券利率,就会将同一利率重复计算。将货币名称与利率一同注明,就能消除歧义。

将利率与比率一同披露

如果不注明无风险利率的来源和频率,夏普比率就无法被他人核验。两家交易台可以基于完全相同的回报序列计算出0.8和1.1,而且都可能是正确的,因为它们采用了不同的利率序列和不同的转换约定。该数值应同时披露四项信息:利率所对应的工具、利率频率、转换约定以及确切的计算期间。这决定了读者能否审计该数值,而不是只能盲目接受。

数据说明与可复现性

每个图表中的利率序列,均为每日国债收益率曲线中的三个月期国库券收益率,并按每个日历月取平均值,再按照一加年度报价的十二次方根转换为月度利率。回报采用SPY月末收盘价计算,仅为价格回报,不包含股息。比率使用月度超额回报的样本标准差,并以十二的平方根进行年化。最后两个图表使用共同结束日期的计算期间,固定利率列采用该期间最后一个月的平均国库券报价。上文每个数字均来自其旁边的图表。

常见问题

夏普比率应采用哪种无风险利率?

应采用与回报使用相同货币的短期限政府国库券,并将其转换为与回报相同的频率。对于月度美元回报,这意味着采用一个月期或三个月期美国国库券。较长期限在测量期间内存在价格风险,因此不符合无风险回报部分的要求。

可以从长期回报历史中减去今天的国库券收益率吗?

这是已发布夏普比率中最常见的错误。在上文的20-year期间内,固定的期末利率与匹配的月度利率序列,基于完全相同的回报,所得结果相差0.18

应在相减前先将无风险利率年化吗?

不应这样做。应先将年度国库券报价转换为回报对应的频率,逐期相减,然后在最后将超额回报序列年化。分别将两部分年化后再相减,会使交叉项留在结果中。

无风险利率会使夏普比率发生多大变化?

大致等于利率变化除以年化波动率。假设某策略的年化波动率为15%,假设利率相差4%,则夏普比率将变化约0.27。这足以拉开普通业绩记录与广受赞誉的业绩记录之间的距离。

算术年化与几何年化有什么区别?

算术年化是将每期超额回报均值乘以一年中的期数。几何年化则将各期回报进行复合,求出能够重现累计结果的恒定利率。按每期计算,几何结果不高于算术结果;波动率越高,两者之间的差距越大。


本文每个图表都附有生成该图表的SQL,因此利率序列和计算期间均清晰可见。如需将相同方法应用于其他ticker或其他历史区间,请用自然语言在Strasmore终端中提出请求。

#sharpe ratio#risk-free rate#excess returns#annualization#performance measurement