@@ -786,3 +786,68 @@ def test_system_r2_direct():
786
786
assert_allclose (ref , res .system_rsquared .mcelroy )
787
787
ref = reference_berndt (res .resids , y )
788
788
assert_allclose (ref , res .system_rsquared .berndt , atol = 1e-3 , rtol = 1e-3 )
789
+
790
+
791
+ def direct_gls (eqns , scale ):
792
+ y = []
793
+ x = []
794
+ for key in eqns :
795
+ y .append (eqns [key ]["dependent" ])
796
+ x .append (eqns [key ]["exog" ])
797
+ y = scale * np .vstack (y )
798
+ from scipy .sparse import csc_matrix
799
+
800
+ n , k = x [0 ].shape
801
+ _x = csc_matrix ((len (x ) * n , len (x ) * k ))
802
+ for i , val in enumerate (x ):
803
+ _x [i * n : (i + 1 ) * n , i * k : (i + 1 ) * k ] = val
804
+ from scipy .sparse .linalg import inv as spinv
805
+
806
+ b = spinv (_x .T @ _x ) @ (_x .T @ y )
807
+ e = y - _x @ b
808
+ e = e .reshape ((- 1 , n )).T
809
+ sigma = e .T @ e / n
810
+ omega_inv = np .kron (np .linalg .inv (sigma ), np .eye (n ))
811
+ b_gls = np .linalg .inv (_x .T @ omega_inv @ _x ) @ (_x .T @ omega_inv @ y )
812
+ xpx = _x .T @ omega_inv @ _x / n
813
+ xpxi = np .linalg .inv (xpx )
814
+ e = y - _x @ b_gls
815
+ xe = (_x .T @ omega_inv ).T * e
816
+ _xe = np .zeros ((n , len (x ) * k ))
817
+ for i in range (len (x )):
818
+ _xe += xe [i * n : (i + 1 ) * n ]
819
+ xeex = _xe .T @ _xe / n
820
+ cov = xpxi @ xeex @ xpxi / n
821
+ return b_gls , cov , xpx , xeex , _xe
822
+
823
+
824
+ @pytest .mark .parametrize ("method" , ["ols" , "gls" ])
825
+ @pytest .mark .parametrize ("cov_type" , ["unadjusted" , "robust" , "hac" , "clustered" ])
826
+ def test_tvalues_homogeneity (method , cov_type ):
827
+ eqns = generate_data (k = 3 )
828
+ mod = SUR (eqns )
829
+ kwargs = {}
830
+
831
+ base = direct_gls (eqns , 1 )
832
+ base_tstat = np .squeeze (base [0 ]) / np .sqrt (np .diag (base [1 ]))
833
+ base_100 = direct_gls (eqns , 1 / 100 )
834
+ base_100_tstat = np .squeeze (base_100 [0 ]) / np .sqrt (np .diag (base_100 [1 ]))
835
+ assert_allclose (base_tstat , base_100_tstat )
836
+
837
+ if cov_type == "hac" :
838
+ kwargs ["bandwidth" ] = 1
839
+ elif cov_type == "clustered" :
840
+ key0 = list (eqns .keys ())[0 ]
841
+ nobs = eqns [key0 ]["dependent" ].shape [0 ]
842
+ rs = np .random .RandomState (231823 )
843
+ kwargs ["clusters" ] = rs .randint (0 , nobs // 5 , size = (nobs , 1 ))
844
+ res0 = mod .fit (method = method , cov_type = cov_type , ** kwargs )
845
+ for key in eqns :
846
+ eqns [key ]["dependent" ] = eqns [key ]["dependent" ] / 100.0
847
+
848
+ mod = SUR (eqns )
849
+ res1 = mod .fit (method = method , cov_type = cov_type , ** kwargs )
850
+ assert_allclose (res0 .tstats , res1 .tstats )
851
+ if cov_type == "robust" and method == "gls" :
852
+ assert_allclose (res0 .tstats , base_tstat )
853
+ assert_allclose (res1 .tstats , base_100_tstat )
0 commit comments