Exemple #1
0
def test_linear_model_gmm_kernel_smoke(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors)
    res = mod.fit(cov_type="kernel", disp=10)
    get_all(res)
    str(res._cov_est)
    res._cov_est.__repr__()
    str(res._cov_est.config)
Exemple #2
0
def test_linear_model_gmm_smoke_risk_free(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
    res = mod.fit(cov_type="robust", disp=10)
    get_all(res)
    str(res._cov_est)
    res._cov_est.__repr__()
    str(res._cov_est.config)
Exemple #3
0
def test_linear_model_gmm_moments_jacobian(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors)
    res = mod.fit(cov_type="robust", disp=0, debiased=False)
    params = np.r_[res.betas.values.ravel(),
                   res.risk_premia.values.ravel(),
                   mod.factors.ndarray.mean(0), ]
    mod_mom = mod._moments(params[:, None], True)

    mom = []
    p = mod.portfolios.ndarray
    f = mod.factors.ndarray
    n = f.shape[0]
    fc = np.c_[np.ones((n, 1)), f]
    mu = f.mean(0)[None, :]
    lam = res.risk_premia.values[None, :]
    x = f - mu + lam
    b = res.betas.values
    for i in range(p.shape[1]):
        eps = p[:, i:(i + 1)] - x @ b[[i]].T
        for j in range(fc.shape[1]):
            mom.append(eps * fc[:, [j]])
    mom.append(f - mu)
    mom_arr = np.hstack(tuple(mom))

    mod_jac = mod._jacobian(params, True)
    jac = np.zeros((mom_arr.shape[1], params.shape[0]))
    nport, nf = p.shape[1], f.shape[1]
    # 1,1
    jac[:(nport * (nf + 1)), :nport * nf] = np.kron(np.eye(nport),
                                                    fc.T @ x / n)
    # 1, 2
    col = []
    for i in range(nport):
        col.append(fc.T @ np.ones((n, 1)) @ b[[i]] / n)
    col = np.vstack(tuple(col))
    jac[:(nport * (nf + 1)), nport * nf:nport * nf + nf] = col
    # 1, 3
    col = []
    for i in range(nport):
        col.append(-fc.T @ np.ones((n, 1)) @ b[[i]] / n)
    col = np.vstack(tuple(col))
    jac[:(nport * (nf + 1)), -nf:] = col
    # 2,2
    jac[-nf:, -nf:] = np.eye(nf)

    assert_allclose(mom_arr, mod_mom)
    assert_allclose(jac, mod_jac)

    me = mom_arr - mom_arr.mean(0)[None, :]
    s = me.T @ me / n
    s = (s + s.T) / 2
    cov = np.linalg.inv(jac.T @ np.linalg.inv(s) @ jac) / n
    cov = (cov + cov.T) / 2
    assert_allclose(np.diag(cov), np.diag(res.cov), rtol=5e-3)
    get_all(res)
Exemple #4
0
def test_linear_model_time_series(data):
    mod = TradedFactorModel(data.portfolios, data.factors)
    mod.fit()
    res = mod.fit()
    get_all(res)
    all_params = []
    all_tstats = []
    nobs, nport = data.portfolios.shape
    nf = data.factors.shape[1]
    e = np.zeros((nobs, (nport * (nf + 1))))
    x = np.zeros((nobs, (nport * (nf + 1))))
    factors = sm.add_constant(data.factors)
    loc = 0
    for i in range(data.portfolios.shape[1]):
        if isinstance(data.portfolios, pd.DataFrame):
            p = data.portfolios.iloc[:, i:(i + 1)]
        else:
            p = data.portfolios[:, i:(i + 1)]
        ols_res = _OLS(p, factors).fit(cov_type='robust', debiased=True)
        all_params.extend(list(ols_res.params))
        all_tstats.extend(list(ols_res.tstats))
        x[:, loc:(loc + nf + 1)] = factors
        e[:, loc:(loc + nf + 1)] = ols_res.resids.values[:, None]
        loc += nf + 1
        cov = res.cov.values[(nf + 1) * i:(nf + 1) * (i + 1),
                             (nf + 1) * i:(nf + 1) * (i + 1)]
        ols_cov = ols_res.cov.values

        assert_allclose(cov, ols_cov)
    assert_allclose(res.params.values.ravel(), np.array(all_params))
    assert_allclose(res.tstats.values.ravel(), np.array(all_tstats))
    assert_allclose(res.risk_premia, np.asarray(factors).mean(0)[1:])

    xpxi_direct = np.eye((nf + 1) * nport + nf)
    f = np.asarray(factors)
    fpfi = np.linalg.inv(f.T @ f / nobs)
    nfp1 = nf + 1
    for i in range(nport):
        st, en = i * nfp1, (i + 1) * nfp1
        xpxi_direct[st:en, st:en] = fpfi
    f = np.asarray(factors)[:, 1:]
    xe = np.c_[x * e, f - f.mean(0)[None, :]]
    xeex_direct = xe.T @ xe / nobs
    cov = xpxi_direct @ xeex_direct @ xpxi_direct / (nobs - nfp1)
    assert_allclose(cov, res.cov.values)

    alphas = np.array(all_params)[0::nfp1][:, None]
    alpha_cov = cov[0:(nfp1 * nport):nfp1, 0:(nfp1 * nport):nfp1]
    stat_direct = float(alphas.T @ np.linalg.inv(alpha_cov) @ alphas)
    assert_allclose(res.j_statistic.stat, stat_direct)
    assert_allclose(1.0 - stats.chi2.cdf(stat_direct, nport),
                    res.j_statistic.pval)
Exemple #5
0
def test_linear_model_gmm_kernel_bandwidth_smoke(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors)
    res = mod.fit(cov_type="kernel", bandwidth=10, disp=10)
    get_all(res)
Exemple #6
0
def test_linear_model_gmm_smoke_iterate(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors)
    res = mod.fit(cov_type="robust", disp=5, steps=20)
    get_all(res)
Exemple #7
0
def test_linear_model_gmm_cue_smoke(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
    res = mod.fit(cov_type="robust", disp=10, use_cue=True)
    get_all(res)
Exemple #8
0
def test_linear_model_parameters_risk_free_gls(data):
    mod = LinearFactorModel(data.portfolios, data.factors, risk_free=True)
    p = mod.portfolios.ndarray
    sigma = np.cov(p.T)
    val, vec = np.linalg.eigh(sigma)
    sigma_m12 = vec @ np.diag(1.0 / np.sqrt(val)) @ vec.T
    sigma_inv = np.linalg.inv(sigma)

    mod = LinearFactorModel(data.portfolios,
                            data.factors,
                            risk_free=True,
                            sigma=sigma)
    assert 'using GLS' in str(mod)
    res = mod.fit()
    f = mod.factors.ndarray
    p = mod.portfolios.ndarray
    n = f.shape[0]
    moments = np.zeros(
        (n, p.shape[1] * (f.shape[1] + 1) + f.shape[1] + 1 + p.shape[1]))
    fc = np.c_[np.ones((n, 1)), f]
    betas = lstsq(fc, p)[0]
    eps = p - fc @ betas
    loc = 0
    for i in range(eps.shape[1]):
        for j in range(fc.shape[1]):
            moments[:, loc] = eps[:, i] * fc[:, j]
            loc += 1
    bc = np.c_[np.ones((p.shape[1], 1)), betas[1:, :].T]
    lam = lstsq(sigma_m12 @ bc, sigma_m12 @ p.mean(0)[:, None])[0]
    pricing_errors = p - (bc @ lam).T

    for i in range(lam.shape[0]):
        lam_error = pricing_errors @ sigma_inv @ bc[:, [i]]
        moments[:, loc] = lam_error.squeeze()
        loc += 1
    alphas = p.mean(0)[:, None] - bc @ lam
    moments[:, loc:] = pricing_errors - alphas.T
    mod_moments = mod._moments(eps, bc, lam, alphas, pricing_errors)

    assert_allclose(res.betas, bc[:, 1:])
    assert_allclose(res.risk_premia, lam.squeeze())
    assert_allclose(res.alphas, alphas.squeeze())
    assert_allclose(moments, mod_moments)

    m = moments.shape[1]
    jac = np.eye(m)
    block1 = p.shape[1] * (f.shape[1] + 1)
    # 1,1

    jac[:block1, :block1] = np.kron(np.eye(p.shape[1]), fc.T @ fc / n)
    # 2, 1
    loc = 0
    nport, nf = p.shape[1], f.shape[1]
    block2 = block1 + nf + 1
    bct = sigma_inv @ bc
    at = sigma_inv @ alphas
    for i in range(nport):
        block = np.zeros((nf + 1, nf + 1))
        for j in range(nf + 1):  # rows
            for k in range(1, nf + 1):  # cols
                block[j, k] = bct[i][j] * lam[k]
                if j == k:
                    block[j, k] -= at[i]
        jac[block1:block2, loc:loc + nf + 1] = block
        loc += nf + 1
    # 2, 2
    jac[block1:block2, block1:block2] = bc.T @ sigma_inv @ bc
    # 3,1
    block = np.zeros((nport, nport * (nf + 1)))
    row = col = 0
    for i in range(nport):
        for j in range(nf + 1):
            if j != 0:
                block[row, col] = lam[j]
            col += 1
        row += 1
    jac[-nport:, :(nport * (nf + 1))] = block
    # 3, 2
    jac[-nport:, (nport * (nf + 1)):(nport * (nf + 1)) + nf + 1] = bc
    # 3, 3: already done since eye
    mod_jac = mod._jacobian(bc, lam, alphas)
    assert_allclose(mod_jac[:block1], jac[:block1])
    assert_allclose(mod_jac[block1:block2, :block1],
                    jac[block1:block2, :block1])
    assert_allclose(mod_jac[block1:block2, block1:block2], jac[block1:block2,
                                                               block1:block2])
    assert_allclose(mod_jac[block1:block2, block2:], jac[block1:block2,
                                                         block2:])
    assert_allclose(mod_jac[block2:], jac[block2:])

    s = moments.T @ moments / (n - (nf + 1))
    ginv = np.linalg.inv(jac)
    cov = ginv @ s @ ginv.T / n
    order = np.zeros((nport, nf + 1), dtype=np.int64)
    order[:, 0] = np.arange(block2, block2 + nport)
    for i in range(nf):
        order[:, i + 1] = (nf + 1) * np.arange(nport) + (i + 1)
    order = np.r_[order.ravel(), block1:block2]
    cov = cov[order][:, order]
    cov = (cov + cov.T) / 2
    assert_allclose(cov, res.cov)

    acov = cov[:block1:(nf + 1), :block1:(nf + 1)]
    jstat = float(alphas.T @ np.linalg.pinv(acov) @ alphas)
    assert_allclose(res.cov.values[:block1:(nf + 1), :block1:(nf + 1)], acov)
    assert_allclose(res.j_statistic.stat, jstat, rtol=1e-1)
    assert_allclose(res.j_statistic.pval,
                    1 - stats.chi2(nport - nf - 1).cdf(jstat),
                    rtol=1e-2)

    get_all(res)
Exemple #9
0
def test_linear_model_parameters(data):
    mod = LinearFactorModel(data.portfolios, data.factors)
    res = mod.fit()
    f = mod.factors.ndarray
    p = mod.portfolios.ndarray
    n = f.shape[0]
    moments = np.zeros(
        (n, p.shape[1] * (f.shape[1] + 1) + f.shape[1] + p.shape[1]))
    fc = np.c_[np.ones((n, 1)), f]
    betas = lstsq(fc, p)[0]
    eps = p - fc @ betas
    loc = 0
    for i in range(eps.shape[1]):
        for j in range(fc.shape[1]):
            moments[:, loc] = eps[:, i] * fc[:, j]
            loc += 1
    b = betas[1:, :].T
    lam = lstsq(b, p.mean(0)[:, None])[0]
    pricing_errors = p - (b @ lam).T
    for i in range(lam.shape[0]):
        lam_error = (p - (b @ lam).T) @ b[:, [i]]
        moments[:, loc] = lam_error.squeeze()
        loc += 1
    alphas = pricing_errors.mean(0)[:, None]
    moments[:, loc:] = pricing_errors - alphas.T
    mod_moments = mod._moments(eps, b, lam, alphas, pricing_errors)

    assert_allclose(res.betas, b)
    assert_allclose(res.risk_premia, lam.squeeze())
    assert_allclose(res.alphas, alphas.squeeze())
    assert_allclose(moments, mod_moments)

    m = moments.shape[1]
    jac = np.eye(m)
    block1 = p.shape[1] * (f.shape[1] + 1)
    # 1,1

    jac[:block1, :block1] = np.kron(np.eye(p.shape[1]), fc.T @ fc / n)
    # 2, 1
    loc = 0
    nport, nf = p.shape[1], f.shape[1]
    block2 = block1 + nf
    for i in range(nport):
        block = np.zeros((nf, nf + 1))
        for j in range(nf):  # rows
            for k in range(1, nf + 1):  # cols
                block[j, k] = b[i][j] * lam[k - 1]
                if j + 1 == k:
                    block[j, k] -= alphas[i]
        jac[block1:block2, loc:loc + nf + 1] = block
        loc += nf + 1
    # 2, 2
    jac[block1:block2, block1:block2] = b.T @ b
    # 3,1
    block = np.zeros((nport, nport * (nf + 1)))
    row = col = 0
    for i in range(nport):
        for j in range(nf + 1):
            if j != 0:
                block[row, col] = lam[j - 1]
            col += 1
        row += 1
    jac[-nport:, :(nport * (nf + 1))] = block
    # 3, 2
    jac[-nport:, (nport * (nf + 1)):(nport * (nf + 1)) + nf] = b
    # 3, 3: already done since eye
    mod_jac = mod._jacobian(b, lam, alphas)
    assert_allclose(mod_jac[:block1], jac[:block1])
    assert_allclose(mod_jac[block1:block2, :block1],
                    jac[block1:block2, :block1])
    assert_allclose(mod_jac[block1:block2, block1:block2], jac[block1:block2,
                                                               block1:block2])
    assert_allclose(mod_jac[block1:block2, block2:], jac[block1:block2,
                                                         block2:])
    assert_allclose(mod_jac[block2:], jac[block2:])

    s = moments.T @ moments / (n - (nf + 1))
    ginv = np.linalg.inv(jac)
    cov = ginv @ s @ ginv.T / n
    order = np.zeros((nport, nf + 1), dtype=np.int64)
    order[:, 0] = np.arange(block2, block2 + nport)
    for i in range(nf):
        order[:, i + 1] = (nf + 1) * np.arange(nport) + (i + 1)
    order = np.r_[order.ravel(), block1:block2]
    cov = cov[order][:, order]
    cov = (cov + cov.T) / 2
    assert_allclose(cov, res.cov)

    acov = cov[:block1:(nf + 1), :block1:(nf + 1)]
    jstat = float(alphas.T @ np.linalg.pinv(acov) @ alphas)
    assert_allclose(res.j_statistic.stat, jstat)
    assert_allclose(res.j_statistic.pval,
                    1 - stats.chi2(nport - nf).cdf(jstat))

    get_all(res)

    res = LinearFactorModel(data.portfolios,
                            data.factors).fit(cov_type='kernel',
                                              debiased=False)
    std_mom = moments / moments.std(0)[None, :]
    mom = std_mom.sum(1)
    bw = kernel_optimal_bandwidth(mom)
    w = kernel_weight_bartlett(bw, n - 1)
    s = _cov_kernel(moments, w)
    cov = ginv @ s @ ginv.T / n
    cov = cov[order][:, order]
    cov = (cov + cov.T) / 2
    assert_allclose(cov, res.cov)
Exemple #10
0
def test_linear_model_gmm_smoke_risk_free(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
    res = mod.fit(cov_type='robust', disp=10)
    get_all(res)
Exemple #11
0
def test_linear_model_gmm_smoke(data):
    mod = LinearFactorModelGMM(data.portfolios, data.factors)
    res = mod.fit(cov_type='robust', disp=5)
    get_all(res)