econmethods 3.0.6.2__tar.gz → 3.1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/PKG-INFO +2 -9
- econmethods-3.1.0.0/README.md +17 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods/Lib.py +251 -14
- econmethods-3.1.0.0/econmethods/__init__.py +3 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods.egg-info/PKG-INFO +2 -9
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods.egg-info/requires.txt +1 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/setup.py +4 -6
- econmethods-3.0.6.2/README.md +0 -6
- econmethods-3.0.6.2/econmethods/__init__.py +0 -3
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods/CADF_Crit_Values.xlsx +0 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods.egg-info/SOURCES.txt +0 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods.egg-info/dependency_links.txt +0 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/econmethods.egg-info/top_level.txt +0 -0
- {econmethods-3.0.6.2 → econmethods-3.1.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: econmethods
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.1.0.0
|
|
4
4
|
Summary: A python package implementing various econometrical tests and estimators
|
|
5
5
|
Home-page: https://github.com/NaturionBG/econmethods
|
|
6
6
|
Author: NaturionBG
|
|
@@ -14,19 +14,12 @@ Requires-Dist: statsmodels>=0.14.5
|
|
|
14
14
|
Requires-Dist: numpy>=2.3.5
|
|
15
15
|
Requires-Dist: pandas>=2.3.3
|
|
16
16
|
Requires-Dist: scipy>=1.16.3
|
|
17
|
+
Requires-Dist: dask>=2025.9.1
|
|
17
18
|
Dynamic: author
|
|
18
19
|
Dynamic: author-email
|
|
19
20
|
Dynamic: classifier
|
|
20
|
-
Dynamic: description
|
|
21
21
|
Dynamic: home-page
|
|
22
22
|
Dynamic: license
|
|
23
23
|
Dynamic: requires-dist
|
|
24
24
|
Dynamic: requires-python
|
|
25
25
|
Dynamic: summary
|
|
26
|
-
|
|
27
|
-
* econmethods
|
|
28
|
-
|
|
29
|
-
A library made specifically for an econometrics project.
|
|
30
|
-
Contains implementations of various estimators and tests.
|
|
31
|
-
|
|
32
|
-
The library is not made by a professional, hence, the implemented methods may require a very scecific data struture.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# <b>econmethods</b>
|
|
2
|
+
|
|
3
|
+
# A library made specifically for an econometrics project.
|
|
4
|
+
<h1>Contains:</h1>
|
|
5
|
+
<ul>
|
|
6
|
+
<li>The one-way CIPS test, accessible via the CipsTest class.</li>
|
|
7
|
+
<li>The two-way Hausman test, accessible via the Hausman class</li>
|
|
8
|
+
<li>A universal class for estimating a first-order Error Correction Model, accessible via the FECM class. Hyperparameters include:</li>
|
|
9
|
+
<ol>
|
|
10
|
+
<li> turn on/off automatic recursive removal of insignificant coefficients. The significance level is set by the user.</li>
|
|
11
|
+
<li> turn on/off the addition of constants for both the long-run model and the short-run model.</li>
|
|
12
|
+
<li> choose the kind of effects for the long run model (RE/FE), choose the ECM estimation strategy (MG, CCEP, CCEMG)</li>
|
|
13
|
+
<li> augment with a trend (if exists in the user's data), choose the variables that make up the cointegrating vector, or add static variables into the ECM estimation, if economic theory suggests that such insertion is plausible. Such variables will be inserted into the estimation in their original levels (or log-levels), not in their first differences. </li>
|
|
14
|
+
</ol>
|
|
15
|
+
<li>The Cross-Sectional Dependence test, accessible via the CDTest class.</li>
|
|
16
|
+
<li>The Slope Homogeneity F-test, accessible via the SlopeHomogeneityF class.</li>
|
|
17
|
+
</ul>
|
|
@@ -7,14 +7,15 @@ from math import floor
|
|
|
7
7
|
import importlib.resources as resources
|
|
8
8
|
from statsmodels.regression.mixed_linear_model import MixedLM
|
|
9
9
|
from statsmodels.stats.diagnostic import het_goldfeldquandt
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, Literal
|
|
11
|
+
import dask
|
|
11
12
|
|
|
12
13
|
def read_critical_values(sheet: str) -> pd.DataFrame:
|
|
13
14
|
xlsx_path = resources.files("econmethods") / "CADF_Crit_Values.xlsx"
|
|
14
15
|
df = pd.read_excel(xlsx_path, sheet_name=sheet, index_col=0)
|
|
15
16
|
return df
|
|
16
17
|
|
|
17
|
-
class
|
|
18
|
+
class CIPS:
|
|
18
19
|
'''
|
|
19
20
|
Implementation of the standard Cross-Sectionally Augmented Dickey-Fuller
|
|
20
21
|
procedure to test for non-stationarity I(1) in panel data. Works only with a linear trend.
|
|
@@ -25,7 +26,7 @@ class CipsTest:
|
|
|
25
26
|
PARAMETERS:
|
|
26
27
|
----------
|
|
27
28
|
------
|
|
28
|
-
- *df*: A
|
|
29
|
+
- *df*: A standard Pandas DataFrame containing panelized data. \n
|
|
29
30
|
Ensure that the DataFrame contains the following columns in this exact order: \n
|
|
30
31
|
0 - a column of spatial units. Must contain homogenous data, e.g. only countries, companies, regions, etc. \n
|
|
31
32
|
1 - temporal column. Must contain homogenous data, e.g. only years, months, quarters, etc. \n
|
|
@@ -36,7 +37,7 @@ class CipsTest:
|
|
|
36
37
|
|
|
37
38
|
- *trend*: State whether your ADF model has a trend or not. Will be used to determine the test critical value.
|
|
38
39
|
|
|
39
|
-
- *poly_trend*: State whether your target variable has a
|
|
40
|
+
- *poly_trend*: State whether your target variable has a distinct polynomial trend. \n
|
|
40
41
|
If a value bigger than 1 is entered, the test will detrend the target variable to get a robust result.
|
|
41
42
|
|
|
42
43
|
- *intercept*: State whether ADF model has an intercept or not. Will be used to determine the test critical value.
|
|
@@ -45,14 +46,14 @@ class CipsTest:
|
|
|
45
46
|
the test will choose the best lag amount from 1 to n_lags based on AIC (Akaike Information Criterion)
|
|
46
47
|
|
|
47
48
|
- *level*: Value of significance to conduct the test at (in %%). Only 5 and 1% are allowed.
|
|
48
|
-
- *log_target*: Specify whether the test shall
|
|
49
|
+
- *log_target*: Specify whether the test shall apply a natural logarithm to your target variable. Defaults to True.
|
|
49
50
|
-----------------------------
|
|
50
51
|
RETURNS:
|
|
51
52
|
--
|
|
52
|
-
via instance.verdict() -> None
|
|
53
|
+
+ **via instance.verdict() -> None**: Prints the verdict of the test based on the parameters set by the user.
|
|
53
54
|
'''
|
|
54
55
|
def __init__(self, df: pd.DataFrame, T: int, N: int, trend: bool = False, poly_trend: int = 1, intercept: bool = False, n_lags: int = 2, level: int = 5, log_target: bool = True) -> None:
|
|
55
|
-
|
|
56
|
+
CIPS.__build_tables()
|
|
56
57
|
self.__df = df
|
|
57
58
|
self.__L = 1
|
|
58
59
|
self.__T = T
|
|
@@ -98,19 +99,19 @@ class CipsTest:
|
|
|
98
99
|
def get_table(self) -> pd.DataFrame:
|
|
99
100
|
if not self.__trend and not self.__C:
|
|
100
101
|
if self.__alpha == 0.01:
|
|
101
|
-
return
|
|
102
|
+
return CIPS.NTNC_1P
|
|
102
103
|
else:
|
|
103
|
-
return
|
|
104
|
+
return CIPS.NTNC_5P
|
|
104
105
|
if not self.__trend and self.__C:
|
|
105
106
|
if self.__alpha == 0.01:
|
|
106
|
-
return
|
|
107
|
+
return CIPS.NTC_1P
|
|
107
108
|
else:
|
|
108
|
-
return
|
|
109
|
+
return CIPS.NTC_5P
|
|
109
110
|
if self.__trend and self.__C:
|
|
110
111
|
if self.__alpha == 0.01:
|
|
111
|
-
return
|
|
112
|
+
return CIPS.TC_1P
|
|
112
113
|
else:
|
|
113
|
-
return
|
|
114
|
+
return CIPS.TC_5P
|
|
114
115
|
|
|
115
116
|
def get_critical_value(self) -> float:
|
|
116
117
|
dct = {}
|
|
@@ -187,7 +188,6 @@ class CipsTest:
|
|
|
187
188
|
def __del__(self) -> None:
|
|
188
189
|
pass
|
|
189
190
|
|
|
190
|
-
|
|
191
191
|
class Hausman:
|
|
192
192
|
'''
|
|
193
193
|
Implementation of the Hausman procedure to test whether it is more feasible to used random effects against fixed effects.
|
|
@@ -790,3 +790,240 @@ class SlopeHomogeneityF:
|
|
|
790
790
|
def __del__(self) -> None:
|
|
791
791
|
pass
|
|
792
792
|
|
|
793
|
+
def compute_adf_moments(T: int, mode: Literal['n', 'c', 'ct'] = 'n', simulation_count: int = 50_000, lag_depth: int = 1, seed: int = 42, chunksize: int = 500, dask_scheduler: Literal['threads', 'processes', 'synchronous'] = 'processes') -> dict:
|
|
794
|
+
'''
|
|
795
|
+
IPS test backbone function for computing the ADF distribution Variance and Mean for correction.
|
|
796
|
+
---
|
|
797
|
+
PARAMETERS:
|
|
798
|
+
---
|
|
799
|
+
+ **T:** the amount of time periods in your data.
|
|
800
|
+
+ **mode:** choose from **["n", "c", "ct"]** for No augmentation, Augmentation with a Const., Augmentation with a const. and a Linear Trend. *Defaults to "n"*.
|
|
801
|
+
+ **simulation_count:** the amount of Monte-Carlo replications. *Defaults to 50_000, as suggested by Im, Pesaran, Shin (2003)*.
|
|
802
|
+
+ **lag_depth:** the depth of the dy lag. At lag_depth = 0 the regression becomes the DF regression. *Defaults to 1*.
|
|
803
|
+
+ **seed:** input the random seed for NumPy. *Defaults to 42.*
|
|
804
|
+
+ **chunksize:** the function utilizes Dask for parallel computation. Each worker computes (chunksize) t-statistics. For the default simulation_count = 50_000, changing this parameter is ill-advised. *Defaults to 500*.
|
|
805
|
+
+ **scheduler:** the function utilizes Dask for parallel computation. This parameter sets a scheduler from **["threads", "processes", "synchronous"]**. Generally, setting a scheduler other than "processes" is ill-advised, if said scheduler is supported by the system. *Defaults to "processes"*.
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
RETURNS:
|
|
809
|
+
---
|
|
810
|
+
+ **a dictionary of structure: {"E":mean_of_t_statistic, "Var":variance_of_t_statistic}**. Both statistics represent the INDIVIDUAL ADF/DF t-statistics under H0: beta_i = 0
|
|
811
|
+
|
|
812
|
+
'''
|
|
813
|
+
|
|
814
|
+
dask_scheduler = dask_scheduler.lower()
|
|
815
|
+
|
|
816
|
+
mode = mode.lower()
|
|
817
|
+
|
|
818
|
+
assert mode in ['n', 'c', 'ct']
|
|
819
|
+
assert dask_scheduler in ['threads', 'processes', 'synchronous']
|
|
820
|
+
|
|
821
|
+
@dask.delayed
|
|
822
|
+
def get_t(deltas_chunk: np.ndarray, lag_depth: int, T: int, mode: str) -> list[float]:
|
|
823
|
+
|
|
824
|
+
container = []
|
|
825
|
+
|
|
826
|
+
for j in range(deltas_chunk.shape[0]):
|
|
827
|
+
deltas = deltas_chunk[j, :]
|
|
828
|
+
y = np.concatenate([[0.0], np.cumsum(deltas)])
|
|
829
|
+
target = np.concatenate([[np.nan], deltas])
|
|
830
|
+
|
|
831
|
+
adf = pd.DataFrame(np.concatenate([target.reshape(-1, 1), y.reshape(-1, 1)], axis=1), columns=['dy', 'y'])
|
|
832
|
+
|
|
833
|
+
for lag in range(0, lag_depth+1):
|
|
834
|
+
if lag == 0:
|
|
835
|
+
adf['y_(t-1)'] = adf['y'].shift(1)
|
|
836
|
+
else:
|
|
837
|
+
adf[f'dy_(t-{lag})'] = adf['dy'].shift(lag)
|
|
838
|
+
|
|
839
|
+
adf = adf.drop(columns = ['y'])
|
|
840
|
+
|
|
841
|
+
if 't' in mode:
|
|
842
|
+
adf['t'] = np.arange(-lag_depth, T+1)
|
|
843
|
+
|
|
844
|
+
if 'c' in mode:
|
|
845
|
+
adf = sm.add_constant(adf)
|
|
846
|
+
|
|
847
|
+
adf = adf.iloc[lag_depth+1:, :].reset_index(drop=True)
|
|
848
|
+
|
|
849
|
+
t = sm.OLS(adf.loc[:, 'dy'], adf.drop(columns='dy')).fit().tvalues['y_(t-1)']
|
|
850
|
+
container.append(t)
|
|
851
|
+
|
|
852
|
+
return container
|
|
853
|
+
|
|
854
|
+
all_deltas = np.random.default_rng(seed=seed).standard_normal(size=(simulation_count, T + lag_depth))
|
|
855
|
+
|
|
856
|
+
t_container = [get_t(all_deltas[i:i+chunksize, :], lag_depth, T, mode) for i in range(0, simulation_count, chunksize)]
|
|
857
|
+
|
|
858
|
+
out = np.concatenate(dask.compute(*t_container, scheduler=dask_scheduler))
|
|
859
|
+
return {'E': float(out.mean()), 'Var':float(out.var(ddof=1))}
|
|
860
|
+
|
|
861
|
+
class IPS:
|
|
862
|
+
'''
|
|
863
|
+
Implementation of the Im-Pesaran-Shin (2003)
|
|
864
|
+
procedure to test for non-stationarity I(1) in panel data.
|
|
865
|
+
----
|
|
866
|
+
The hypotheses are as follows:
|
|
867
|
+
- *H0*: The Target variable is I(1)
|
|
868
|
+
- *H1*: The Target variable is I(0)\n
|
|
869
|
+
- *Rejection is left-tailed*
|
|
870
|
+
PARAMETERS:
|
|
871
|
+
----------
|
|
872
|
+
------
|
|
873
|
+
- *df*: A standard Pandas DataFrame containing panelized data. \n
|
|
874
|
+
Ensure that the DataFrame contains the following columns in this exact order: \n
|
|
875
|
+
0 - a column of spatial units. Must contain homogenous data, e.g. only countries, companies, regions, etc. \n
|
|
876
|
+
1 - temporal column. Must contain homogenous data, e.g. only years, months, quarters, etc. \n
|
|
877
|
+
2 - target variable. Must not contain NaN Values. An Error will be raised otherwise. \n
|
|
878
|
+
|
|
879
|
+
- *trend*: State whether your ADF model has a trend or not.
|
|
880
|
+
|
|
881
|
+
- *poly_trend*: State whether your target variable has a distinct polynomial trend. \n
|
|
882
|
+
If a value bigger than 1 is entered, the test will detrend the target variable to get a robust result.
|
|
883
|
+
|
|
884
|
+
- *intercept*: State whether ADF model has an intercept or not.
|
|
885
|
+
|
|
886
|
+
- *n_lags*: Determine the amount of lags in the Augmented Dickey-Fuller regression.
|
|
887
|
+
|
|
888
|
+
- *level*: Value of significance to conduct the test at (in %%).
|
|
889
|
+
|
|
890
|
+
- *log_target*: Specify whether the test shall apply a natural logarithm to your target variable. Defaults to True.
|
|
891
|
+
|
|
892
|
+
- *n_reps*: the amount of Monte-Carlo replications used for Dickey-Fuller moments estimation. *Defaults to 50_000, as suggested by Im, Pesaran, Shin (2003)*.
|
|
893
|
+
|
|
894
|
+
- *seed*: input the random seed for NumPy. This seed is used for the ADF Monte-Carlo simulations. *Defaults to 42.*
|
|
895
|
+
|
|
896
|
+
- *chunksize*: the ADF Monte-Carlo simulations utilize Dask for parallel computation. Each worker computes (chunksize) t-statistics. For the default simulation_count = 50_000, changing this parameter is ill-advised. *Defaults to 500*.
|
|
897
|
+
|
|
898
|
+
- *dask_scheduler*: the ADF Monte-Carlo simulations utilize Dask for parallel computation. This parameter sets a scheduler from **["threads", "processes", "synchronous"]**. Generally, setting a scheduler other than "processes" is ill-advised, if said scheduler is supported by the system. *Defaults to "processes"*.
|
|
899
|
+
-----------------------------
|
|
900
|
+
RETURNS:
|
|
901
|
+
--
|
|
902
|
+
+ **via instance.verdict() -> None**: Prints the verdict of the test based on the parameters set by the user.
|
|
903
|
+
+ **PLEASE NOTE** that the test is computationally expensive due to Monte-Carlo simulations (approx. 20 - 35 seconds per each unique value of T, if panels are unbalanced)
|
|
904
|
+
+ **Due to computational complexity, it is highly advised that one does not run any methods, except for instance.verdict()
|
|
905
|
+
unless they specifically wish to observe the ADF Mean & Variance point-estimates or the test Z-Score**
|
|
906
|
+
|
|
907
|
+
'''
|
|
908
|
+
def __init__(self, df: pd.DataFrame, trend: bool = False, poly_trend: int = 1, intercept: bool = False, n_lags: int = 2, level: int = 5, log_target: bool = True, n_reps: int = 50_000, seed: int = 42, chunksize: int = 500, dask_scheduler: Literal['threads', 'processes', 'synchronous'] = 'processes') -> None:
|
|
909
|
+
self.__df = df.copy(deep=True)
|
|
910
|
+
self.__poly = poly_trend
|
|
911
|
+
self.__alpha = level/100
|
|
912
|
+
self.__df = self.__df.rename(columns={self.__df.columns[0]:'SpUnit', self.__df.columns[1]:'time', self.__df.columns[2]:'target'})
|
|
913
|
+
if log_target:
|
|
914
|
+
self.__df['target'] = np.log(self.__df['target'])
|
|
915
|
+
|
|
916
|
+
self.__trend = trend
|
|
917
|
+
self.__C = intercept
|
|
918
|
+
self.__n_lags = n_lags
|
|
919
|
+
self.__seed = seed
|
|
920
|
+
self.__chunksize = chunksize
|
|
921
|
+
self.__scheduler = dask_scheduler
|
|
922
|
+
self.__n_reps = n_reps
|
|
923
|
+
|
|
924
|
+
self.__compute_T_and_N()
|
|
925
|
+
self.__verify()
|
|
926
|
+
|
|
927
|
+
if self.__trend:
|
|
928
|
+
if self.__poly > 1:
|
|
929
|
+
self.__df = self.detrend()
|
|
930
|
+
self.__trend = False
|
|
931
|
+
|
|
932
|
+
if self.__C and self.__trend:
|
|
933
|
+
self.__mode = 'ct'
|
|
934
|
+
elif self.__C:
|
|
935
|
+
self.__mode = 'c'
|
|
936
|
+
elif self.__trend:
|
|
937
|
+
raise TypeError('A Linear Trend cannot exist without a Constant.')
|
|
938
|
+
else:
|
|
939
|
+
self.__mode = 'n'
|
|
940
|
+
|
|
941
|
+
def __verify(self) -> None:
|
|
942
|
+
if self.__df.target.isnull().sum() > 0:
|
|
943
|
+
raise TypeError('Values in Target must NOT be NaN!')
|
|
944
|
+
if self.__poly < 1:
|
|
945
|
+
raise ValueError('The Polynomial Power Cannot be lesser than 1!')
|
|
946
|
+
|
|
947
|
+
for periods in self.__T:
|
|
948
|
+
if periods <= 6:
|
|
949
|
+
raise ValueError('The IPS tests expects longer Time Series (T > 6)')
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
def __compute_T_and_N(self) -> None:
|
|
953
|
+
self.__N = len(self.__df.SpUnit.unique())
|
|
954
|
+
self.__T = self.__df.groupby('SpUnit').size().values - self.__n_lags - 1
|
|
955
|
+
|
|
956
|
+
def detrend(self) -> pd.DataFrame:
|
|
957
|
+
lst = []
|
|
958
|
+
for unit in self.__df.SpUnit.unique():
|
|
959
|
+
subdf = self.__df[self.__df.SpUnit == unit].copy()
|
|
960
|
+
for i in range(1, self.__poly+1):
|
|
961
|
+
subdf.insert(3, f't^{i}', np.linspace(1, len(subdf), len(subdf))**i)
|
|
962
|
+
diff = subdf['target'].copy() - sm.OLS(subdf['target'], sm.add_constant(subdf.iloc[:, 3:])).fit().predict(sm.add_constant(subdf.iloc[:, 3:]))
|
|
963
|
+
subdf.loc[:, 'target'] = diff
|
|
964
|
+
lst.append(subdf.iloc[:, :3])
|
|
965
|
+
return pd.concat(lst, axis=0)
|
|
966
|
+
|
|
967
|
+
def build_regressions(self, lags: int) -> list[pd.DataFrame]:
|
|
968
|
+
lst = []
|
|
969
|
+
for unit in self.__df.SpUnit.unique():
|
|
970
|
+
subdf = self.__df[self.__df.SpUnit == unit].copy()
|
|
971
|
+
|
|
972
|
+
subdf['target_1'] = subdf['target'].shift(1)
|
|
973
|
+
subdf['target_diff'] = subdf['target'] - subdf['target_1']
|
|
974
|
+
|
|
975
|
+
for i in range(1, lags + 1):
|
|
976
|
+
subdf[f'target_diff_{i}'] = subdf['target_diff'].shift(i)
|
|
977
|
+
|
|
978
|
+
if self.__trend:
|
|
979
|
+
subdf['t'] = np.arange(1, len(subdf) + 1)
|
|
980
|
+
|
|
981
|
+
if self.__trend:
|
|
982
|
+
base = ['target_diff', 't', 'target_1']
|
|
983
|
+
else:
|
|
984
|
+
base = ['target_diff', 'target_1']
|
|
985
|
+
additional = [f'target_diff_{i}' for i in range(1, lags + 1)]
|
|
986
|
+
|
|
987
|
+
subdf = subdf.loc[:, base + additional].iloc[lags + 1:, :]
|
|
988
|
+
lst.append(subdf)
|
|
989
|
+
return lst
|
|
990
|
+
|
|
991
|
+
def compute_per_panel_moments(self) -> dict:
|
|
992
|
+
means, variances = [], []
|
|
993
|
+
cache = {}
|
|
994
|
+
|
|
995
|
+
for periods in self.__T:
|
|
996
|
+
|
|
997
|
+
if periods not in cache:
|
|
998
|
+
result = compute_adf_moments(T=periods, mode = self.__mode, simulation_count=self.__n_reps, lag_depth=self.__n_lags, seed = self.__seed, chunksize = self.__chunksize, dask_scheduler=self.__scheduler)
|
|
999
|
+
means.append(result['E'])
|
|
1000
|
+
variances.append(result['Var'])
|
|
1001
|
+
cache[periods] = result
|
|
1002
|
+
else:
|
|
1003
|
+
means.append(cache[periods]['E'])
|
|
1004
|
+
variances.append(cache[periods]['Var'])
|
|
1005
|
+
|
|
1006
|
+
return {'E_Mean': float(np.mean(means)), 'E_Var': float(np.mean(variances))}
|
|
1007
|
+
|
|
1008
|
+
def get_test_statistic(self) -> float:
|
|
1009
|
+
moments = self.compute_per_panel_moments()
|
|
1010
|
+
|
|
1011
|
+
regressions = self.build_regressions(self.__n_lags)
|
|
1012
|
+
if self.__C:
|
|
1013
|
+
t_bar = np.mean([sm.OLS(reg.loc[:, 'target_diff'], sm.add_constant(reg.drop(columns='target_diff'))).fit().tvalues['target_1'] for reg in regressions])
|
|
1014
|
+
else:
|
|
1015
|
+
t_bar = np.mean([sm.OLS(reg.loc[:, 'target_diff'], reg.drop(columns='target_diff')).fit().tvalues['target_1'] for reg in regressions])
|
|
1016
|
+
|
|
1017
|
+
Z = np.sqrt(self.__N) * (t_bar - moments['E_Mean']) / np.sqrt(moments['E_Var'])
|
|
1018
|
+
|
|
1019
|
+
return Z
|
|
1020
|
+
|
|
1021
|
+
def verdict(self) -> None:
|
|
1022
|
+
|
|
1023
|
+
Z_value = self.get_test_statistic()
|
|
1024
|
+
p_value = sc.norm().cdf(Z_value)
|
|
1025
|
+
|
|
1026
|
+
if p_value >= self.__alpha:
|
|
1027
|
+
print(f"According to the IPS test, your variable is non-stationary I(1) with p-value >= alpha: {p_value} >= {self.__alpha} \n Lag amount: {self.__n_lags}")
|
|
1028
|
+
else:
|
|
1029
|
+
print(f"According to the IPS test, your variable is stationary I(0) with p-value < alpha: {p_value} < {self.__alpha} \n Lag amount: {self.__n_lags}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: econmethods
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.1.0.0
|
|
4
4
|
Summary: A python package implementing various econometrical tests and estimators
|
|
5
5
|
Home-page: https://github.com/NaturionBG/econmethods
|
|
6
6
|
Author: NaturionBG
|
|
@@ -14,19 +14,12 @@ Requires-Dist: statsmodels>=0.14.5
|
|
|
14
14
|
Requires-Dist: numpy>=2.3.5
|
|
15
15
|
Requires-Dist: pandas>=2.3.3
|
|
16
16
|
Requires-Dist: scipy>=1.16.3
|
|
17
|
+
Requires-Dist: dask>=2025.9.1
|
|
17
18
|
Dynamic: author
|
|
18
19
|
Dynamic: author-email
|
|
19
20
|
Dynamic: classifier
|
|
20
|
-
Dynamic: description
|
|
21
21
|
Dynamic: home-page
|
|
22
22
|
Dynamic: license
|
|
23
23
|
Dynamic: requires-dist
|
|
24
24
|
Dynamic: requires-python
|
|
25
25
|
Dynamic: summary
|
|
26
|
-
|
|
27
|
-
* econmethods
|
|
28
|
-
|
|
29
|
-
A library made specifically for an econometrics project.
|
|
30
|
-
Contains implementations of various estimators and tests.
|
|
31
|
-
|
|
32
|
-
The library is not made by a professional, hence, the implemented methods may require a very scecific data struture.
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
from setuptools import find_packages, setup
|
|
2
2
|
|
|
3
|
-
with open('README.md', 'r') as f:
|
|
4
|
-
long_desc = f.read()
|
|
5
|
-
|
|
6
3
|
setup(
|
|
7
4
|
name = 'econmethods',
|
|
8
|
-
version = 'v3.0.
|
|
5
|
+
version = 'v3.1.0.0',
|
|
9
6
|
description='A python package implementing various econometrical tests and estimators',
|
|
10
7
|
packages = find_packages(),
|
|
11
|
-
long_description=
|
|
8
|
+
long_description='',
|
|
12
9
|
url = 'https://github.com/NaturionBG/econmethods',
|
|
13
10
|
package_data= {
|
|
14
11
|
"econmethods": ["CADF_Crit_Values.xlsx"]
|
|
@@ -26,6 +23,7 @@ setup(
|
|
|
26
23
|
'statsmodels >= 0.14.5',
|
|
27
24
|
'numpy >= 2.3.5',
|
|
28
25
|
'pandas >= 2.3.3',
|
|
29
|
-
'scipy >= 1.16.3'
|
|
26
|
+
'scipy >= 1.16.3',
|
|
27
|
+
'dask >= 2025.9.1',
|
|
30
28
|
],
|
|
31
29
|
)
|
econmethods-3.0.6.2/README.md
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|