Calculating a Sharpe Ratio from Excess Returns and Return Volatility
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.