Add the information ratio to risk metrics.

Calculates relative to the benchmark returns.
This commit is contained in:
Ryan Day
2013-01-31 18:25:36 -05:00
committed by Eddie Hebert
parent e43dfef65d
commit 4d56f57468
2 changed files with 85 additions and 0 deletions
+40
View File
@@ -367,6 +367,46 @@ class Risk(unittest.TestCase):
for x in self.metrics_06.year_periods],
[-0.524])
def test_algorithm_information_06(self):
self.assertEqual([round(x.information, 3)
for x in self.metrics_06.month_periods],
[0.131,
-0.11,
-0.067,
0.144,
0.298,
-0.391,
0.106,
-0.034,
-0.058,
0.068,
0.09,
-0.125])
self.assertEqual([round(x.information, 3)
for x in self.metrics_06.three_month_periods],
[-0.013,
-0.006,
0.113,
-0.012,
-0.02,
-0.11,
0.01,
-0.005,
0.03,
0.009])
self.assertEqual([round(x.information, 3)
for x in self.metrics_06.six_month_periods],
[-0.013,
-0.013,
-0.003,
-0.002,
-0.013,
-0.042,
0.009])
self.assertEqual([round(x.information, 3)
for x in self.metrics_06.year_periods],
[-0.002])
def dtest_algorithm_beta_06(self):
self.assertEqual([round(x.beta, 3)
for x in self.metrics_06.month_periods],
+45
View File
@@ -37,6 +37,9 @@ Risk Report
| sharpe | The sharpe ratio based on the _algorithm_ (rather |
| | than the static portfolio) returns. |
+-----------------+----------------------------------------------------+
| information | The information ratio based on the _algorithm_ |
| | (rather than the static portfolio) returns. |
+-----------------+----------------------------------------------------+
| beta | The _algorithm_ beta to the benchmark. |
+-----------------+----------------------------------------------------+
| alpha | The _algorithm_ alpha to the benchmark. |
@@ -55,6 +58,7 @@ Risk Report
import logbook
import datetime
import math
import itertools
from collections import OrderedDict
import bisect
import numpy as np
@@ -145,6 +149,7 @@ class RiskMetricsBase(object):
self.treasury_period_return = self.choose_treasury()
self.sharpe = self.calculate_sharpe()
self.sortino = self.calculate_sortino()
self.information = self.calculate_information()
self.beta, self.algorithm_covariance, self.benchmark_variance, \
self.condition_number, self.eigen_values = self.calculate_beta()
self.alpha = self.calculate_alpha()
@@ -167,6 +172,7 @@ class RiskMetricsBase(object):
'benchmark_period_return': self.benchmark_period_returns,
'sharpe': self.sharpe,
'sortino': self.sortino,
'information': self.information,
'beta': self.beta,
'alpha': self.alpha,
'excess_return': self.excess_return,
@@ -196,6 +202,7 @@ class RiskMetricsBase(object):
"algorithm_volatility",
"sharpe",
"sortino",
"information",
"algorithm_covariance",
"benchmark_variance",
"beta",
@@ -265,6 +272,23 @@ class RiskMetricsBase(object):
return ((self.algorithm_period_returns - mar) / dr)
def calculate_information(self):
"""
http://en.wikipedia.org/wiki/Information_ratio
"""
relative_returns = [
r - b
for r, b
in itertools.izip(self.algorithm_returns, self.benchmark_returns)]
relative_deviation = np.std(relative_returns, ddof=1)
if relative_deviation < 0.000001 or np.isnan(relative_deviation):
return 0.0
return np.mean(relative_returns) / relative_deviation
def calculate_beta(self):
"""
@@ -450,6 +474,7 @@ class RiskMetricsIterative(RiskMetricsBase):
self.benchmark_period_returns = []
self.sharpe = []
self.sortino = []
self.information = []
self.beta = []
self.alpha = []
self.max_drawdown = 0
@@ -501,6 +526,7 @@ algorithm_returns ({algo_count}) in range {start} : {end}"
self.alpha.append(self.calculate_alpha())
self.sharpe.append(self.calculate_sharpe())
self.sortino.append(self.calculate_sortino())
self.information.append(self.calculate_information())
self.max_drawdown = self.calculate_max_drawdown()
def to_dict(self):
@@ -518,6 +544,7 @@ algorithm_returns ({algo_count}) in range {start} : {end}"
'benchmark_period_return': self.benchmark_period_returns[-1],
'sharpe': self.sharpe[-1],
'sortino': self.sortino[-1],
'information': self.information[-1],
'beta': self.beta[-1],
'alpha': self.alpha[-1],
'excess_return': self.excess_returns[-1],
@@ -548,6 +575,7 @@ algorithm_returns ({algo_count}) in range {start} : {end}"
"algorithm_volatility",
"sharpe",
"sortino",
"information",
"algorithm_covariance",
"benchmark_variance",
"beta",
@@ -648,6 +676,23 @@ algorithm_returns ({algo_count}) in range {start} : {end}"
return ((self.algorithm_period_returns[-1] - mar) /
dr)
def calculate_information(self):
"""
http://en.wikipedia.org/wiki/Information_ratio
"""
relative_returns = [
r - b
for r, b
in itertools.izip(self.algorithm_returns, self.benchmark_returns)]
relative_deviation = np.std(relative_returns, ddof=1)
if relative_deviation < 0.000001 or np.isnan(relative_deviation):
return 0.0
return np.mean(relative_returns) / relative_deviation
def calculate_alpha(self):
"""
http://en.wikipedia.org/wiki/Alpha_(investment)