Strasmore Research
학습 Matt Connor작성자 Matt Connor

샤프지수 계산 시 무위험 수익률 적용 방법

샤프지수(Sharpe ratio) 산출 시 무위험 수익률(risk-free rate)은 시간 흐름에 따라 변합니다. 수익률 빈도와 국채 금리를 일치시키는 올바른 계산 절차와 단일 고정 금리를 사용할 때 발생하는 오류의 위험성을 상세히 설명합니다.

샤프지수(Sharpe ratio) 산출 시 무위험 수익률(risk-free rate)은 평가 대상인 위험을 감수하지 않고도 동일 기간 동안 얻을 수 있었던 수익을 의미합니다. 이는 수익률과 동일한 통화로 표시된 시계열 데이터로서, 기간별로 하나의 수치가 대응됩니다. 무위험 수익률의 빈도를 수익률 빈도와 일치시켜 기간별로 차감한 뒤, 마지막에 한 번만 연율화(annualize)해야 합니다.

이 절차를 생략하는 것이 발표된 샤프지수 상당수가 오류를 범하는 주된 이유입니다. 20년치 수익률 이력의 맨 위에서 숫자 하나(보통 이번 주 국채 금리)를 가져와 적용하면, 2009년과 2024년에 동일한 허들(hurdle)을 적용하는 꼴이 됩니다. 샤프지수 가이드에서는 이 지수가 무엇을 측정하는지 다룹니다. 본 페이지에서는 거의 아무도 문서화하지 않는 입력값에 대해 설명합니다.

무위험 수익률은 상수가 아닙니다

20년 동안 측정된 샤프지수는 금리 이력을 포괄합니다. 아래 패널은 3개월 만기 국채(Treasury bill) 금리를 사용하여 각 역년을 평균과 그 범위로 요약한 것입니다.

조회연도별 3개월 만기 국채 수익률(Treasury bill yield)
모든 수치 뒤에 숨겨진 정확한 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

연간 평균은 22년의 기간 동안 2005년에는 3.22%였고, 2026년에는 3.74%였습니다. 중요한 것은 이 두 지점 사이의 경로입니다. 금리는 바닥까지 떨어졌다가 10년 가까이 그 상태를 유지한 뒤 다시 상승했습니다. 저점과 고점 열은 단일 연도 내에서 금리가 얼마나 변동했는지를 보여주며, 이것이 바로 1년치 샤프지수를 구할 때도 단일 수치가 아닌 일치된 시계열이 필요한 이유입니다.

샤프지수에 적합한 무위험 수익률 선택

네 가지 속성이 선택 기준을 결정합니다.

  1. 짧은 만기. 측정 기간 동안 금리가 거의 확실해야 합니다. 3개월 만기 국채는 월간 데이터에 적합합니다. 반면 10년 만기 국채는 측정하는 달 동안 가격이 변동하므로 적합하지 않습니다.
  2. 수익률과 동일한 통화. 유로화 표시 전략은 유로화 국채 금리를 기준으로 평가해야 합니다.
  3. 수익률과 동일한 빈도. 국채 수익률은 연율로 표시되므로, 월간 수익률에서 차감하기 전에 연간 수치를 변환해야 합니다.
  4. 양측의 일관된 수익률 정의. 국채 수익률은 전체 수익률이므로, 배당을 제외한 전략 수익률을 비교하는 것은 적절하지 않습니다. 가격 수익률과 총수익률에서 이 차이를 다룹니다.

세 번째 항목인 변환에는 두 가지 관례가 있습니다. 단순 나눗셈은 연간 수치를 12로 나누는 방식입니다. 복리 방식은 1 더하기 연간 수익률의 12제곱근을 구하는 방식입니다. 가상의 5% 국채 금리를 적용하면 월간 수치는 각각 0.4167%와 0.4074%가 되며, 샘플의 매달 약 1베이시스포인트(bp)의 차이가 발생합니다. 본 페이지의 패널은 복리 방식을 사용합니다. 국채 수익률을 허들이 아닌 보유 자산으로 고려한다면 배당 수익률과 국채 수익률유휴 현금 운용처를 참고하십시오.

월간 초과 수익률 시계열 구축 방법

구축 과정은 기계적입니다. 매달 마지막 종가를 기준으로 월간 수익률을 산출하고, 해당 월의 국채 금리를 월간 수익률로 변환한 뒤 차감합니다. 그 결과 월별로 하나의 수치가 나오는 초과 수익률 시계열이 생성됩니다. 월간 수익률 측정 방법에서 수익률 산출 과정을 상세히 다룹니다.

조회월간 수익률, 월간 무위험 수익률(risk-free rate) 및 초과 수익률, 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개월 동안 차감하면, 동일한 것을 측정한다고 주장하는 두 샤프지수 간의 전체 차이를 결정짓는 요소가 됩니다.

차감 후 연율화

시계열이 정렬된 후에는 두 가지 연산 순서가 가능하며, 결과는 서로 다릅니다. '초과 수익률 우선' 방식은 월간 수익률에서 월간 금리를 먼저 뺀 뒤 초과 수익률 시계열을 연율화합니다. '연율화 우선' 방식은 수익률을 연간 수치로 복리 계산하고, 국채 금리도 연간 수치로 복리 계산한 뒤 서로 뺍니다.

조회연율화된 위험 프리미엄(risk premium): 월간 차감 후 연율화 또는 각 항목별 연율화 후 차감
모든 수치 뒤에 숨겨진 정확한 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포인트의 차이를 보입니다. 모든 기간에서 '연율화 우선' 수치가 '초과 수익률 우선' 수치보다 높게 나타납니다. 이 차이를 만드는 것은 교차항(cross term)입니다. 수익률 시계열을 연간 수치로 복리 계산하면 위험 프리미엄 자체에 국채 수익률이 더해진 수익이 포함되는데, 이후 연율화된 국채 금리를 빼더라도 이 부분이 완전히 제거되지 않기 때문입니다. 교차항은 두 연율화 수치의 곱에 비례하므로, 국채 금리가 높을 때 차이가 가장 큽니다.

연율화에는 또 다른 갈래가 있습니다. 산술 연율화는 평균 월간 초과 수익률에 12를 곱합니다. 기하 연율화는 복리 계산을 통해 누적 결과를 재현하는 상수 연간 수익률을 구합니다. 가상의 2기간 동안 +50% 후 -33.3% 수익이 나면 원점으로 돌아옵니다. 산술 평균은 기간당 +8.35%이지만 기하 평균은 0%입니다. 본 패널은 복리 방식을 사용합니다. 한 가지 참고할 점은, 산술 연율화 하에서는 '평균 수익률의 12배'에서 '평균 국채 금리의 12배'를 빼는 것이 '평균 초과 수익률의 12배'와 대수적으로 동일하다는 것입니다. 이 관례 하에서는 차감 순서가 분자에 영향을 주지 않습니다. 그러나 금리 자체가 변동할 때 초과 수익률의 표준편차가 원본 수익률의 표준편차와 달라지므로 분모는 여전히 변합니다.

단일 고정 금리 적용의 비용

흔한 지름길은 현재의 국채 금리를 가져와 과거 전체 기간의 매 기간에서 빼는 것입니다. 아래 패널은 동일한 종료일을 가진 5개 기간에 대해 샤프지수를 두 가지 방식으로 계산합니다. 하나는 일치된 월간 시계열을 사용한 것이고, 다른 하나는 해당 기간 말의 국채 금리를 사용한 것입니다.

조회고정 금리 대비 매칭 금리 시리즈의 샤프 지수(Sharpe ratio)
모든 수치 뒤에 숨겨진 정확한 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만큼 차이가 납니다. 12개월 동안은 고정 금리가 해당 기간의 평균에서 크게 벗어날 여지가 적습니다. 20-year 기간에서는 0.18만큼 차이가 납니다. 일치된 시계열에서는 0.49, 고정 금리 적용 시에는 0.32입니다. 오차는 선택한 단일 금리와 실제로 적용된 평균 금리 사이의 거리에서 발생하며, 기간이 길어질수록 이 거리는 더 벌어질 수 있습니다. 이후의 모든 분석은 이 오차를 물려받게 되며, 변동성 타겟팅 및 포지션 사이징은 바로 이러한 입력값을 기반으로 작동합니다.

통화의 함정

한 통화로 수익을 내고 다른 통화의 국채 금리를 기준으로 평가하는 전략은 어느 쪽으로도 의미 있는 수치를 산출하지 못합니다. 초과 수익률은 동일 통화 내에서 계산해야 합니다. 유로화 수익률은 유로화 국채 금리와, 엔화 수익률은 엔화 국채 금리와 비교하십시오. 헤지 전략에는 두 번째 함정이 있습니다. 통화 헤지는 선도환율(forward)을 기준으로 가격이 결정되는데, 선도 포인트는 두 통화 간의 금리 차이를 반영하므로 이미 국내 금리의 일부가 헤지된 해외 수익률에 포함되어 있습니다. 여기에 해외 국채 금리를 추가로 차감하면 동일한 금리를 이중으로 차감하는 셈이 됩니다. 금리 옆에 통화를 명시하면 이러한 모호함은 사라집니다.

샤프지수와 함께 금리 정보 공개

무위험 수익률의 출처와 빈도가 명시되지 않은 샤프지수는 누구도 검증할 수 없습니다. 두 운용팀이 동일한 수익률 흐름을 가지고도 서로 다른 금리 시계열과 변환 관례를 사용하여 각각 0.8과 1.1이라는 결과를 낼 수 있으며, 둘 다 맞을 수 있습니다. 수치와 함께 다음 네 가지 항목을 반드시 기재해야 합니다. 금리의 기초가 된 상품, 빈도, 변환 관례, 그리고 정확한 기간입니다. 이것이 독자가 검증할 수 있는 수치와 맹목적으로 믿어야 하는 수치의 차이입니다.

데이터 참고 및 재현성

모든 패널의 금리 시계열은 일간 국채 수익률 곡선에서 추출한 3개월 만기 국채 금리를 각 역월 내에서 평균한 것이며, 연간 수치에 1 더하기의 12제곱근을 취해 월간 금리로 변환했습니다. 수익률은 SPY 월말 종가 기준이며 배당이 제외된 가격 수익률입니다. 지수는 월간 초과 수익률의 표본 표준편차를 사용하며 연율화를 위해 12의 제곱근을 곱했습니다. 마지막 두 패널은 공통 종료일을 가진 기간을 사용하며, 고정 금리 열은 해당 기간 마지막 달의 평균 국채 금리를 사용합니다. 본문의 모든 수치는 옆 패널에서 도출되었습니다.

FAQ

샤프지수 산출 시 어떤 무위험 수익률을 사용해야 합니까?

수익률과 동일한 통화로 표시된 단기 국채 금리를 사용하며, 수익률과 동일한 빈도로 변환해야 합니다. USD 월간 수익률의 경우 1개월 또는 3개월 만기 국채가 적합합니다. 만기가 긴 채권은 측정 기간 동안 가격 변동 위험이 따르므로 무위험 자산으로 부적합합니다.

긴 수익률 이력에서 오늘의 국채 금리를 차감해도 됩니까?

이는 발표된 샤프지수에서 가장 흔한 실수입니다. 위 20-year 기간 동안, 기간 말 고정 금리를 사용한 경우와 일치된 월간 시계열을 사용한 경우 동일한 수익률에 대해 0.18만큼의 차이가 발생합니다.

무위험 수익률을 차감하기 전에 연율화해야 합니까?

아닙니다. 연간 국채 금리를 수익률 빈도에 맞게 변환하여 기간별로 차감한 뒤, 마지막에 초과 수익률 시계열을 한 번만 연율화하십시오. 각 항목을 별도로 연율화한 후 차감하면 결과값에 교차항이 남게 됩니다.

무위험 수익률이 샤프지수에 얼마나 영향을 미칩니까?

대략 '금리 변화폭을 연율화된 변동성으로 나눈 값'만큼 영향을 줍니다. 연율화 변동성이 15%인 가상의 전략에서 가정 금리가 4% 차이 나면 샤프지수는 약 0.27만큼 변하며, 이는 평범한 성과와 뛰어난 성과를 가르는 차이입니다.

산술 연율화와 기하 연율화의 차이는 무엇입니까?

산술 연율화는 평균 기간 초과 수익률에 연간 기간 수를 곱합니다. 기하 연율화는 복리 계산을 통해 누적 결과를 재현하는 상수 연간 수익률을 구합니다. 기간별로 보면 기하 수치는 산술 수치와 같거나 낮으며, 변동성이 커질수록 두 수치 간의 차이는 벌어집니다.


본 페이지의 모든 패널에는 해당 데이터를 생성한 SQL이 포함되어 있어 금리 시계열과 기간을 확인할 수 있습니다. 다른 티커나 다른 기간에 대해 동일한 분석을 수행하려면 Strasmore 터미널에서 평이한 영어로 요청하십시오.

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