Skip to content

Commit 8f6f908

Browse files
committed
TST: Add direct moment and jacobian test of GMM
Test GMM moment condtiions and jacobian
1 parent bc1dd96 commit 8f6f908

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

linearmodels/asset_pricing/model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ def fit(self, center=True, use_cue=False, steps=2, disp=10, max_iter=1000,
752752
df=self.factors.shape[1], **cov_config)
753753

754754
full_vcv = cov_est.cov
755+
self._testing = {'s': cov_est.s}
755756
sel = slice((n * k), (n * k + k + nrf))
756757
rp = params[sel]
757758
rp_cov = full_vcv[sel, sel]
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import numpy as np
2+
import pytest
3+
from numpy.testing import assert_allclose
4+
5+
from linearmodels.asset_pricing.model import LinearFactorModelGMM
6+
from linearmodels.tests.asset_pricing._utility import generate_data, get_all
7+
8+
9+
@pytest.fixture(params=['numpy', 'pandas'])
10+
def data(request):
11+
return generate_data(nportfolio=10, output=request.param)
12+
13+
14+
def test_linear_model_gmm_moments_jacobian(data):
15+
mod = LinearFactorModelGMM(data.portfolios, data.factors)
16+
res = mod.fit(cov_type='robust', disp=0, debiased=False)
17+
params = np.r_[res.betas.values.ravel(),
18+
res.risk_premia.values.ravel(),
19+
mod.factors.ndarray.mean(0)]
20+
mod_mom = mod._moments(params[:, None], True)
21+
22+
mom = []
23+
p = mod.portfolios.ndarray
24+
f = mod.factors.ndarray
25+
n = f.shape[0]
26+
fc = np.c_[np.ones((n, 1)), f]
27+
mu = f.mean(0)[None, :]
28+
lam = res.risk_premia.values[None, :]
29+
x = f - mu + lam
30+
b = res.betas.values
31+
for i in range(p.shape[1]):
32+
eps = p[:, i:(i + 1)] - x @ b[[i]].T
33+
for j in range(fc.shape[1]):
34+
mom.append(eps * fc[:, [j]])
35+
mom.append(f - mu)
36+
mom = np.hstack(tuple(mom))
37+
38+
mod_jac = mod._jacobian(params, True)
39+
jac = np.zeros((mom.shape[1], params.shape[0]))
40+
nport, nf = p.shape[1], f.shape[1]
41+
# 1,1
42+
jac[:(nport * (nf + 1)), :nport * nf] = np.kron(np.eye(nport), fc.T @ x / n)
43+
# 1, 2
44+
col = []
45+
for i in range(nport):
46+
col.append(fc.T @ np.ones((n, 1)) @ b[[i]] / n)
47+
col = np.vstack(tuple(col))
48+
jac[:(nport * (nf + 1)), nport * nf:nport * nf + nf] = col
49+
# 1, 3
50+
col = []
51+
for i in range(nport):
52+
col.append(-fc.T @ np.ones((n, 1)) @ b[[i]] / n)
53+
col = np.vstack(tuple(col))
54+
jac[:(nport * (nf + 1)), -nf:] = col
55+
# 2,2
56+
jac[-nf:, -nf:] = np.eye(nf)
57+
58+
assert_allclose(mom, mod_mom)
59+
assert_allclose(jac, mod_jac)
60+
61+
me = mom - mom.mean(0)[None, :]
62+
s = me.T @ me / n
63+
s = (s + s.T) / 2
64+
cov = np.linalg.inv(jac.T @ np.linalg.inv(s) @ jac) / n
65+
cov = (cov + cov.T) / 2
66+
assert_allclose(np.diag(cov), np.diag(res.cov), rtol=5e-3)
67+
get_all(res)
68+
69+
70+
@pytest.mark.skip
71+
def test_linear_model_gmm_smoke_iterate(data):
72+
mod = LinearFactorModelGMM(data.portfolios, data.factors)
73+
res = mod.fit(cov_type='robust', disp=5, steps=20)
74+
get_all(res)
75+
76+
77+
@pytest.mark.skip
78+
def test_linear_model_gmm_smoke_risk_free(data):
79+
mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
80+
res = mod.fit(cov_type='robust', disp=10)
81+
get_all(res)
82+
83+
84+
@pytest.mark.skip
85+
def test_linear_model_gmm_kernel_smoke(data):
86+
mod = LinearFactorModelGMM(data.portfolios, data.factors)
87+
res = mod.fit(cov_type='kernel', disp=10)
88+
get_all(res)
89+
90+
91+
@pytest.mark.skip
92+
def test_linear_model_gmm_kernel_bandwidth_smoke(data):
93+
mod = LinearFactorModelGMM(data.portfolios, data.factors)
94+
res = mod.fit(cov_type='kernel', bandwidth=10, disp=10)
95+
get_all(res)
96+
97+
98+
@pytest.mark.skip
99+
def test_linear_model_gmm_cue_smoke(data):
100+
mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
101+
res = mod.fit(cov_type='robust', disp=10, use_cue=True)
102+
get_all(res)

0 commit comments

Comments
 (0)