From eeb8db9a388c17deebe53b730cecc5b58ba5dc6d Mon Sep 17 00:00:00 2001 From: Jason Strimpel Date: Tue, 10 Jan 2017 14:13:10 +0800 Subject: [PATCH 1/3] Initial commit --- shrink_covariance_matrix.py | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 shrink_covariance_matrix.py diff --git a/shrink_covariance_matrix.py b/shrink_covariance_matrix.py new file mode 100644 index 0000000..9af9451 --- /dev/null +++ b/shrink_covariance_matrix.py @@ -0,0 +1,67 @@ +import numpy as np + + +def shrink_covariance_matrix(x, shrink=None): + """ + Shrinks towards constant correlation matrix + If shrink is specified then this const is used for shrinkage + + The notation follows Ledoit and Wolf (2004) + http://www.ledoit.net/honey_abstract.htm + This version: 06/2009 + + Parameters + ---------- + x : N x N sample covariance matrix of stock returns + shrink : given shrinkage intensity factor; if none, code calculates + + Returns + ------- + tuple : numpy.ndarray which contains the shrunk covariance matrix + : float shrinkage intensity factor + + """ + if x is None: + raise ValueError('No covariance matrix defined') + + if isinstance(x, pandas.DataFrame): + cov = x.as_matrix() + elif isinstance(x, np.ndarray): + cov = x + else: + raise ValueError('Covariance matrix passed must be numpy.ndarray or pandas.DataFrame') + + if shrink is not None: + shrinkage = shrink + + [t, n] = np.shape(cov) + meanx = cov.mean(axis=0) + cov = cov - np.tile(meanx, (t, 1)) + + sample = (1.0 / t) * np.dot(cov.T, cov) + + var = np.diag(sample) + sqrtvar = np.sqrt(var) + + a = np.tile(sqrtvar, (n, 1)) + rho = (sum(sum(sample / (a * a.T))) - n) / (n*(n-1)) + + prior = rho * (a * a.T) + prior[np.eye(t, n)==1] = var + + # Frobenius-norm of matrix cov, sqrt(sum(diag(dot(cov.T, cov)))) + c = np.linalg.norm(sample-prior, 'fro')**2 + y = cov**2.0 + p = np.dot((1.0 / t), sum(sum(np.dot(y.T, y))))-sum(sum(sample**2.0)) + rdiag = np.dot((1.0 / t), sum(sum(y**2.0))) - sum(var**2.0) + v = np.dot((cov**3.0).T, cov) / t - ((var*sample).T) + v[np.eye(t, n)==1] = 0.0 + roff = sum(sum(v * (a / a.T))) + r = rdiag + np.dot(rho, roff) + + # compute shrinkage constant + k = (p - r) / c + shrinkage = max(0.0, min(1.0, k/t)) + sigma = np.dot(shrinkage, prior) + np.dot((1 - shrinkage), sample) + + return sigma, shrinkage From 6683188e03201817745b0b7b9088e10aec581093 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 10 Jan 2017 14:20:44 +0800 Subject: [PATCH 2/3] PEP8: Cleaned up variable order and spacing --- shrink_covariance_matrix.py | 129 ++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/shrink_covariance_matrix.py b/shrink_covariance_matrix.py index 9af9451..7af1a02 100644 --- a/shrink_covariance_matrix.py +++ b/shrink_covariance_matrix.py @@ -1,67 +1,70 @@ import numpy as np +import pandas def shrink_covariance_matrix(x, shrink=None): - """ - Shrinks towards constant correlation matrix - If shrink is specified then this const is used for shrinkage - - The notation follows Ledoit and Wolf (2004) - http://www.ledoit.net/honey_abstract.htm - This version: 06/2009 - - Parameters - ---------- - x : N x N sample covariance matrix of stock returns - shrink : given shrinkage intensity factor; if none, code calculates - - Returns - ------- - tuple : numpy.ndarray which contains the shrunk covariance matrix - : float shrinkage intensity factor - - """ - if x is None: - raise ValueError('No covariance matrix defined') - - if isinstance(x, pandas.DataFrame): - cov = x.as_matrix() - elif isinstance(x, np.ndarray): - cov = x - else: - raise ValueError('Covariance matrix passed must be numpy.ndarray or pandas.DataFrame') - - if shrink is not None: - shrinkage = shrink - - [t, n] = np.shape(cov) - meanx = cov.mean(axis=0) - cov = cov - np.tile(meanx, (t, 1)) - - sample = (1.0 / t) * np.dot(cov.T, cov) - - var = np.diag(sample) - sqrtvar = np.sqrt(var) - - a = np.tile(sqrtvar, (n, 1)) - rho = (sum(sum(sample / (a * a.T))) - n) / (n*(n-1)) - - prior = rho * (a * a.T) - prior[np.eye(t, n)==1] = var - - # Frobenius-norm of matrix cov, sqrt(sum(diag(dot(cov.T, cov)))) - c = np.linalg.norm(sample-prior, 'fro')**2 - y = cov**2.0 - p = np.dot((1.0 / t), sum(sum(np.dot(y.T, y))))-sum(sum(sample**2.0)) - rdiag = np.dot((1.0 / t), sum(sum(y**2.0))) - sum(var**2.0) - v = np.dot((cov**3.0).T, cov) / t - ((var*sample).T) - v[np.eye(t, n)==1] = 0.0 - roff = sum(sum(v * (a / a.T))) - r = rdiag + np.dot(rho, roff) - - # compute shrinkage constant - k = (p - r) / c - shrinkage = max(0.0, min(1.0, k/t)) - sigma = np.dot(shrinkage, prior) + np.dot((1 - shrinkage), sample) - - return sigma, shrinkage + """ + Shrinks towards constant correlation matrix + If shrink is specified then this const is used for shrinkage + + The notation follows Ledoit and Wolf (2004) + http://www.ledoit.net/honey_abstract.htm + This version: 06/2009 + + Parameters + ---------- + x : N x N sample covariance matrix of stock returns + shrink : given shrinkage intensity factor; if none, code calculates + + Returns + ------- + tuple : numpy.ndarray which contains the shrunk covariance matrix + : float shrinkage intensity factor + + """ + + if x is None: + raise ValueError('No covariance matrix defined') + + if isinstance(x, pandas.DataFrame): + cov = x.as_matrix() + elif isinstance(x, np.ndarray): + cov = x + else: + raise ValueError('Covariance matrix passed must be numpy.ndarray') + + [t, n] = np.shape(cov) + meanx = cov.mean(axis=0) + cov = cov - np.tile(meanx, (t, 1)) + + sample = (1.0 / t) * np.dot(cov.T, cov) + + var = np.diag(sample) + sqrtvar = np.sqrt(var) + + a = np.tile(sqrtvar, (n, 1)) + rho = (sum(sum(sample / (a * a.T))) - n) / (n * (n - 1)) + + prior = rho * (a * a.T) + prior[np.eye(t, n) == 1] = var + + # Frobenius-norm of matrix cov, sqrt(sum(diag(dot(cov.T, cov)))) + c = np.linalg.norm(sample - prior, 'fro') ** 2 + y = cov ** 2.0 + p = np.dot((1.0 / t), sum(sum(np.dot(y.T, y)))) - sum(sum(sample ** 2.0)) + rdiag = np.dot((1.0 / t), sum(sum(y ** 2.0))) - sum(var ** 2.0) + v = np.dot((cov ** 3.0).T, cov) / t - (var * sample).T + v[np.eye(t, n) == 1] = 0.0 + roff = sum(sum(v * (a / a.T))) + r = rdiag + np.dot(rho, roff) + + # compute shrinkage constant + if shrink: + shrinkage = shrink + else: + k = (p - r) / c + shrinkage = max(0.0, min(1.0, k / t)) + + sigma = np.dot(shrinkage, prior) + np.dot((1 - shrinkage), sample) + + return sigma, shrinkage From 2544b1a7b6eb72049f3ff9b811efe9588b471209 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 10 Jan 2017 14:30:55 +0800 Subject: [PATCH 3/3] PEP8: Added some extra new lines --- shrink_covariance_matrix.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/shrink_covariance_matrix.py b/shrink_covariance_matrix.py index 7af1a02..97ca620 100644 --- a/shrink_covariance_matrix.py +++ b/shrink_covariance_matrix.py @@ -35,26 +35,26 @@ def shrink_covariance_matrix(x, shrink=None): [t, n] = np.shape(cov) meanx = cov.mean(axis=0) - cov = cov - np.tile(meanx, (t, 1)) + cov = cov - np.tile(meanx, (t, 1.)) - sample = (1.0 / t) * np.dot(cov.T, cov) + sample = (1. / t) * np.dot(cov.T, cov) var = np.diag(sample) sqrtvar = np.sqrt(var) - a = np.tile(sqrtvar, (n, 1)) - rho = (sum(sum(sample / (a * a.T))) - n) / (n * (n - 1)) + a = np.tile(sqrtvar, (n, 1.)) + rho = (sum(sum(sample / (a * a.T))) - n) / (n * (n - 1.)) prior = rho * (a * a.T) - prior[np.eye(t, n) == 1] = var + prior[np.eye(t, n) == 1.] = var # Frobenius-norm of matrix cov, sqrt(sum(diag(dot(cov.T, cov)))) - c = np.linalg.norm(sample - prior, 'fro') ** 2 - y = cov ** 2.0 - p = np.dot((1.0 / t), sum(sum(np.dot(y.T, y)))) - sum(sum(sample ** 2.0)) - rdiag = np.dot((1.0 / t), sum(sum(y ** 2.0))) - sum(var ** 2.0) - v = np.dot((cov ** 3.0).T, cov) / t - (var * sample).T - v[np.eye(t, n) == 1] = 0.0 + c = np.linalg.norm(sample - prior, 'fro') ** 2. + y = cov ** 2. + p = np.dot((1. / t), sum(sum(np.dot(y.T, y)))) - sum(sum(sample ** 2.)) + rdiag = np.dot((1. / t), sum(sum(y ** 2.))) - sum(var ** 2.) + v = np.dot((cov ** 3.).T, cov) / t - (var * sample).T + v[np.eye(t, n) == 1.] = 0. roff = sum(sum(v * (a / a.T))) r = rdiag + np.dot(rho, roff) @@ -63,8 +63,8 @@ def shrink_covariance_matrix(x, shrink=None): shrinkage = shrink else: k = (p - r) / c - shrinkage = max(0.0, min(1.0, k / t)) + shrinkage = max(0., min(1., k / t)) - sigma = np.dot(shrinkage, prior) + np.dot((1 - shrinkage), sample) + sigma = np.dot(shrinkage, prior) + np.dot((1. - shrinkage), sample) return sigma, shrinkage