Strasmore Research
آموزش Matt Connorتوسط Matt Connor

نحوه محاسبه نرخ بدون ریسک در نسبت شارپ

نرخ بدون ریسک در نسبت شارپ متغیر است. برای دقت در محاسبات باید بازدهی اسناد خزانه را با فرکانس بازدهی‌ها هماهنگ کرد. استفاده از یک نرخ ثابت در طول زمان منجر به خطای محاسباتی می‌شود.

نرخ بدون ریسک در نسبت شارپ (Sharpe ratio)، بازدهی است که می‌توانستید در همان بازه زمانی، بدون پذیرش ریسکی که در حال ارزیابی آن هستید، کسب کنید. این نرخ یک سری زمانی است که در هر دوره یک مقدار دارد و با ارزِ بازدهی‌ها بیان می‌شود. فرکانس آن را با فرکانس بازدهی‌ها هماهنگ کنید و دوره به دوره از آن کسر نمایید. سالانه‌سازی را تنها یک‌بار، در پایان کار انجام دهید.

نادیده گرفتن این رویه، منشأ خطای اکثر نسبت‌های شارپ منتشرشده است. برداشتن یک عدد واحد از ابتدای یک تاریخچه بازدهی بیست‌ساله — که معمولاً نرخ فعلی اسناد خزانه (Treasury bill) در هفته جاری است — باعث می‌شود سال 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

میانگین سالانه در 2005 برابر با 3.22% و در 2026 برابر با 3.74% بوده است که در طول 22 سال تقویمی محاسبه شده است. مسیر بین این دو عدد، بخش مهم ماجراست. این خط به کف می‌رسد، برای نزدیک به یک دهه در آنجا می‌ماند و سپس دوباره صعود می‌کند. ستون‌های کمینه و بیشینه نشان می‌دهند که نرخ در طول یک سال تا چه حد جابه‌جا شده است؛ به همین دلیل است که حتی برای نسبت شارپ یک‌ساله نیز به یک سری زمانی هماهنگ نیاز است، نه فقط یک نرخ واحد.

کدام نرخ بدون ریسک در نسبت شارپ جای می‌گیرد

چهار ویژگی تعیین‌کننده انتخاب نرخ هستند:

  1. سررسید کوتاه. نرخ باید در طول یک دوره اندازه‌گیری، تقریباً قطعی باشد. اسناد سه‌ماهه برای محاسبات ماهانه مناسب هستند. اوراق ده ساله چنین نیستند، زیرا قیمت آن‌ها در طول ماهی که در حال اندازه‌گیری آن هستید، تغییر می‌کند.
  2. ارزِ بازدهی. استراتژی‌هایی که با یورو قیمت‌گذاری می‌شوند، باید با اسناد خزانه یورویی سنجیده شوند.
  3. فرکانس بازدهی. بازده اسناد خزانه به‌صورت نرخ سالانه بیان می‌شود و یک نرخ سالانه باید پیش از اعمال بر بازده ماهانه، به نرخ ماهانه تبدیل شود.
  4. تعریف یکسان بازده در هر دو سو. بازده یک سند خزانه، کل بازده آن است؛ بنابراین بازده استراتژی که سود سهام (dividend) را حذف کرده باشد، در جایگاه یکسانی اندازه‌گیری نمی‌شود. بازده قیمتی در برابر بازده کل این شکاف را بررسی می‌کند.

برای تبدیل در بند سوم، دو قرارداد رایج وجود دارد. تقسیم ساده، نرخ سالانه را بر دوازده تقسیم می‌کند. ترکیب (Compounding)، ریشه دوازدهمِ یک به‌علاوه نرخ سالانه را محاسبه می‌کند. برای یک سند خزانه فرضی 5 درصدی، این دو روش به ترتیب 0.4167٪ و 0.4074٪ برای یک ماه به دست می‌دهند؛ تفاوتی در حدود یک واحد پایه (basis point) که در هر ماه از نمونه تکرار می‌شود. پنل‌های اینجا از روش ترکیب استفاده می‌کنند. اگر بازده اسناد خزانه برای شما به‌عنوان یک دارایی جذاب است تا یک معیار سنجش، بازده سود سهام در برابر بازده خزانه‌داری و محل پارک نقدینگی راکد این موضوع را پوشش می‌دهند.

چگونه یک سری بازده مازاد ماهانه بسازیم

ساختار کار مکانیکی است: آخرین قیمت بسته شدن هر ماه را بگیرید، بازده ماهانه را محاسبه کنید، نرخ اسناد خزانه آن ماه را به نرخ ماهانه تبدیل کنید و سپس کسر کنید. خروجی، یک سری بازده مازاد (excess return) است، یک عدد برای هر ماه. چگونه بازده‌های ماهانه اندازه‌گیری می‌شوند بخش بازده را با جزئیات بررسی می‌کند.

پرس‌وجوبازده ماهانه، نرخ بهره بدون ریسک ماهانه و مازاد بازده، ۲۰۲۰ تا ۲۰۲۴
کد دقیق 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 واحد اختلاف دارند. عدد حاصل از «اول سالانه‌سازی» در هر بازه‌ای در اینجا، بالاتر از «اول مازاد» قرار می‌گیرد. آنچه آن‌ها را جدا می‌کند، یک «جمله متقاطع» (cross term) است: ترکیب کردن یک سری بازده به یک عدد سالانه، شامل کسب نرخ اسناد خزانه روی خودِ صرف ریسک (risk premium) است و کسر کردن نرخ سالانه اسناد خزانه در انتها، هرگز آن بخش را حذف نمی‌کند. این جمله متقاطع با حاصل‌ضرب دو عدد سالانه مقیاس می‌شود، بنابراین زمانی که نرخ اسناد خزانه بالاست، بیشترین فاصله را دارد.

سالانه‌سازی یک دوراهی دیگر هم دارد. سالانه‌سازی حسابی، میانگین مازاد ماهانه را در دوازده ضرب می‌کند. سالانه‌سازی هندسی، دوره‌ها را ترکیب می‌کند: نرخ سالانه ثابتی که نتیجه تجمعی را بازتولید می‌کند. یک دوره فرضی دو مرحله‌ای با 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 در نرخ ثابت. خطا با فاصله بین نرخ انتخابی شما و میانگین نرخ واقعی که حاکم بوده، ردیابی می‌شود و این فاصله با طولانی‌تر شدن بازه، فضای بیشتری برای باز شدن دارد. هر چیزی که در ادامه می‌آید این خطا را به ارث می‌برد و هدف‌گذاری نوسان و تعیین اندازه موقعیت دقیقاً بر اساس چنین ورودی‌هایی عمل می‌کند.

تله ارزی

استراتژی‌ای که با یک ارز درآمد دارد و با اسناد خزانه ارز دیگری سنجیده می‌شود، عددی تولید می‌کند که در هیچ‌کدام معنای دقیقی ندارد. بازده مازاد را درون یک ارز محاسبه کنید: بازده یورویی در برابر اسناد یورویی، بازده ین در برابر اسناد ین. استراتژی‌های پوشش ریسک (Hedged) تله دومی دارند. پوشش ارزی بر اساس نرخ‌های فوروارد قیمت‌گذاری می‌شود و امتیازات فوروارد به تفاوت نرخ بهره بین دو ارز نزدیک است که بخشی از نرخ داخلی را از قبل درون بازده خارجیِ پوشش‌داده‌شده قرار می‌دهد. کسر کردن اسناد خزانه خارجی علاوه بر آن، به معنای کسر کردن دوبرابرِ نرخ است. ارز را در کنار نرخ ذکر کنید تا ابهام برطرف شود.

نرخ را در کنار نسبت منتشر کنید

نسبت شارپی که بدون منبع نرخ بدون ریسک و فرکانس آن نقل شود، توسط هیچ‌کس قابل راستی‌آزمایی نیست. دو میز معاملاتی می‌توانند از یک جریان بازدهی یکسان، اعداد 0.8 و 1.1 را محاسبه کنند و هر دو درست بگویند، چرا که از سری نرخ‌های متفاوت و قراردادهای تبدیل متفاوت استفاده کرده‌اند. چهار مورد باید همراه عدد باشد: ابزاری که نرخ از آن آمده، فرکانس آن، قرارداد تبدیل و بازه دقیق. این تفاوت بین عددی است که خواننده می‌تواند حسابرسی کند و عددی که خواننده باید از روی ایمان بپذیرد.

یادداشت‌های داده و قابلیت بازتولید

سری نرخ در هر پنل، اسناد خزانه سه‌ماهه از منحنی بازده روزانه خزانه‌داری است که در هر ماه تقویمی میانگین‌گیری شده و به‌عنوان ریشه دوازدهمِ یک به‌علاوه نرخ سالانه، به نرخ ماهانه تبدیل شده است. بازده‌ها قیمت‌های بسته شدن ماهانه SPY هستند، فقط بازده قیمتی، بدون سود سهام. نسبت‌ها از انحراف معیار نمونه بازده‌های مازاد ماهانه و ریشه دوم دوازده برای سالانه‌سازی استفاده می‌کنند. دو پنل آخر از بازه‌هایی استفاده می‌کنند که به یک تاریخ مشترک ختم می‌شوند و ستون نرخ ثابت، میانگین نرخ اسناد خزانه در ماه پایانی آن بازه را می‌گیرد. هر رقمی در متن بالا از پنل کنار آن استخراج شده است.

پرسش‌های متداول

در نسبت شارپ از چه نرخ بدون ریسکی استفاده کنم؟

یک سند خزانه دولتی کوتاه‌مدت با همان ارزِ بازدهی‌ها، که به همان فرکانس بازدهی‌ها تبدیل شده باشد. برای بازده‌های ماهانه دلاری، این یعنی اسناد خزانه یک‌ماهه یا سه‌ماهه. سررسیدهای طولانی‌تر در طول دوره اندازه‌گیری ریسک قیمت دارند که آن‌ها را به‌عنوان یک مؤلفه بدون ریسک رد می‌کند.

آیا می‌توانم نرخ فعلی اسناد خزانه را از یک تاریخچه بازدهی طولانی کسر کنم؟

این رایج‌ترین اشتباه در نسبت‌های شارپ منتشرشده است. در بازه 20-year بالا، نرخ ثابت پایان بازه و سری ماهانه هماهنگ، روی بازده‌های یکسان، نتایجی با اختلاف 0.18 تولید می‌کنند.

آیا نرخ بدون ریسک را قبل از کسر کردن سالانه کنم؟

خیر. نرخ سالانه اسناد خزانه را به فرکانس بازدهی تبدیل کنید، دوره به دوره کسر کنید و سپس سری مازاد را در پایان یک‌بار سالانه کنید. سالانه‌سازی جداگانه هر بخش و کسر کردن آن‌ها در انتها، یک جمله متقاطع در پاسخ باقی می‌گذارد.

نرخ بدون ریسک چقدر نسبت شارپ را تغییر می‌دهد؟

تقریباً به اندازه تغییر در نرخ تقسیم بر نوسان سالانه. در یک استراتژی فرضی با نوسان سالانه 15٪، تفاوت 4 درصدی در نرخ فرض‌شده، نسبت را حدود 0.27 تغییر می‌دهد که فاصله بین یک سابقه عملکرد معمولی و یک سابقه درخشان است.

تفاوت سالانه‌سازی حسابی و هندسی چیست؟

سالانه‌سازی حسابی، میانگین مازاد دوره را در تعداد دوره‌های یک سال ضرب می‌کند. سالانه‌سازی هندسی، دوره‌ها را به نرخ ثابتی ترکیب می‌کند که نتیجه تجمعی را بازتولید می‌کند. در هر دوره، عدد هندسی در سطح یا زیر عدد حسابی قرار می‌گیرد و فاصله بین آن‌ها با افزایش نوسان بیشتر می‌شود.


هر پنل در اینجا حاوی کد SQL تولیدکننده آن است، بنابراین سری نرخ و بازه هر دو قابل مشاهده هستند. برای اجرای همین ساختار روی یک تیکر دیگر یا بازه تاریخی دیگر، آن را به زبان ساده در ترمینال Strasmore درخواست کنید.

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