Skip to content
All library documents

Calculating a Sharpe Ratio from Excess Returns and Return Volatility

Code backtrader

Summary

The script demonstrates a basic Sharpe ratio calculation using two annual return inputs and a configurable risk-free rate. It subtracts the risk-free rate from each return, averages those excess returns, then divides by the standard deviation of the original returns. The calculation is implemented with helper functions for the arithmetic mean and standard deviation.

The example prints the inputs, average excess return, return standard deviation, and resulting ratio. It is a compact illustration rather than a complete performance-analysis method: it uses only two observations, does not annualize or otherwise adjust the ratio, and does not explain how the return series should be sampled. The risk-free rate is subtracted from both returns, while volatility is measured on the unadjusted returns. No empirical comparison or validation is provided.

Key ideas

  • The Sharpe ratio is calculated as mean excess return divided by return standard deviation.
  • The example applies one risk-free rate to each of two annual return inputs.
  • The script computes standard deviation from the supplied return observations.
  • The example does not address sampling frequency, annualization, or validation on a longer return history.

Tags

Full text
# sratio.py


```py
#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
###############################################################################
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import argparse
import itertools
import math
import operator
import sys


if sys.version_info.major == 2:
    map = itertools.imap


def average(x):
    return math.fsum(x) / len(x)


def variance(x):
    avgx = average(x)
    return list(map(lambda y: (y - avgx) ** 2, x))


def standarddev(x):
    return math.sqrt(average(variance(x)))


def run(pargs=None):
    args = parse_args(pargs)

    returns = [args.ret1, args.ret2]
    retfree = args.riskfreerate

    print('returns is:', returns, ' - retfree is:', retfree)

    # Directly from backtrader
    retfree = itertools.repeat(retfree)
    ret_free = map(operator.sub, returns, retfree)  # excess returns
    ret_free_avg = average(list(ret_free))  # mean of the excess returns
    print('returns excess mean:', ret_free_avg)
    retdev = standarddev(returns)  # standard deviation
    print('returns standard deviation:', retdev)
    ratio = ret_free_avg / retdev  # mean excess returns  / std deviation
    print('Sharpe Ratio is:', ratio)


def parse_args(pargs=None):
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description='Sample Sharpe Ratio')

    parser.add_argument('--ret1', required=False, action='store',
                        type=float, default=0.023286,
                        help=('Annual Return 1'))

    parser.add_argument('--ret2', required=False, action='store',
                        type=float, default=0.0257816485323,
                        help=('Annual Return 2'))

    parser.add_argument('--riskfreerate', required=False, action='store',
                        type=float, default=0.01,
                        help=('Risk free rate (decimal) for the Sharpe Ratio'))

    if pargs is not None:
        return parser.parse_args(pargs)

    return parser.parse_args()


if __name__ == '__main__':
    run()

```

Shown in full with attribution under the source's licence. Licence: GPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.