예제 #1
0
def test_logit(simulated_problem: SimulatedProblemFixture, method: str,
               center_moments: bool, W_type: str, se_type: str) -> (None):
    """Test that Logit estimates are the same as those from the the linearmodels package."""
    _, simulation_results, problem, _, _ = simulated_problem
    product_data = simulation_results.product_data

    # skip more complicated simulations
    if problem.K2 > 0 or problem.K3 > 0 or problem.H > 0:
        return

    # solve the problem
    results1 = problem.solve(method=method,
                             center_moments=center_moments,
                             W_type=W_type,
                             se_type=se_type)

    # compute the delta from the logit problem
    delta = np.log(product_data.shares)
    for t in problem.unique_market_ids:
        shares_t = product_data.shares[product_data.market_ids == t]
        delta[product_data.market_ids == t] -= np.log(1 - shares_t.sum())

    # configure covariance options
    W_options = {
        'clusters': product_data.clustering_ids
    } if W_type == 'clustered' else {}
    se_options = {
        'clusters': product_data.clustering_ids
    } if se_type == 'clustered' else {}

    # monkey-patch a problematic linearmodels method that shouldn't be called but is anyways
    linearmodels.IVLIML._estimate_kappa = lambda _: 1

    # solve the problem with linearmodels
    model = linearmodels.IVGMM(delta,
                               exog=None,
                               endog=problem.products.X1,
                               instruments=problem.products.ZD,
                               center=center_moments,
                               weight_type=W_type,
                               **W_options)
    results2 = model.fit(iter_limit=1 if method == '1s' else 2,
                         cov_type=se_type,
                         **se_options)

    # test that results are essentially identical
    for key1, key2 in [('beta', 'params'), ('xi', 'resids'),
                       ('beta_se', 'std_errors')]:
        values1 = getattr(results1, key1)
        values2 = np.c_[getattr(results2, key2)]
        np.testing.assert_allclose(values1,
                                   values2,
                                   atol=1e-10,
                                   rtol=1e-8,
                                   err_msg=key1)
예제 #2
0
def test_logit(
        simulated_problem: SimulatedProblemFixture, method: str, center_moments: bool, W_type: str, se_type: str) -> (
        None):
    """Test that Logit estimates are the same as those from the the linearmodels package."""
    _, simulation_results, problem, _, _ = simulated_problem
    product_data = simulation_results.product_data

    # skip more complicated simulations
    if problem.K2 > 0 or problem.K3 > 0 or problem.H > 0:
        return pytest.skip("This simulation cannot be tested against linearmodels.")

    # solve the problem
    results1 = problem.solve(method=method, center_moments=center_moments, W_type=W_type, se_type=se_type)

    # compute the delta from the logit problem
    delta = np.log(product_data.shares)
    for t in problem.unique_market_ids:
        shares_t = product_data.shares[product_data.market_ids == t]
        delta[product_data.market_ids == t] -= np.log(1 - shares_t.sum())

    # configure covariance options
    W_options = {'clusters': product_data.clustering_ids} if W_type == 'clustered' else {}
    se_options = {'clusters': product_data.clustering_ids} if se_type == 'clustered' else {}

    # monkey-patch a problematic linearmodels method that shouldn't be called but is anyways
    linearmodels.IVLIML._estimate_kappa = lambda _: 1

    # solve the problem with linearmodels
    model = linearmodels.IVGMM(
        delta, exog=None, endog=problem.products.X1, instruments=problem.products.ZD, center=center_moments,
        weight_type=W_type, **W_options
    )
    results2 = model.fit(iter_limit=1 if method == '1s' else 2, cov_type=se_type, **se_options)

    # test that results are essentially identical (unadjusted second stage standard errors will be different because
    #   linearmodels still constructs a S matrix)
    for key1, key2 in [('beta', 'params'), ('xi', 'resids'), ('beta_se', 'std_errors')]:
        if not (se_type == 'unadjusted' and key1 == 'beta_se'):
            values1 = getattr(results1, key1)
            values2 = np.c_[getattr(results2, key2)]
            np.testing.assert_allclose(values1, values2, atol=1e-10, rtol=1e-8, err_msg=key1)

    # test that test statistics in the second stage (when they make sense) are essentially identical
    if method == '2s' and se_type != 'unadjusted':
        nonconstant = (problem.products.X1[0] != problem.products.X1).any(axis=0)
        F1 = results1.run_wald_test(results1.parameters[nonconstant], np.eye(results1.parameters.size)[nonconstant])
        J1 = results1.run_hansen_test()
        F2 = results2.f_statistic.stat
        J2 = results2.j_stat.stat
        np.testing.assert_allclose(F1, F2, atol=1e-10, rtol=1e-8)
        np.testing.assert_allclose(J1, J2, atol=1e-10, rtol=1e-8)