aigroup-econ-mcp 0.1.1__py3-none-any.whl → 0.1.5__py3-none-any.whl
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.
Potentially problematic release.
This version of aigroup-econ-mcp might be problematic. Click here for more details.
- aigroup_econ_mcp/__init__.py +18 -18
- aigroup_econ_mcp/cli.py +86 -81
- aigroup_econ_mcp/server.py +486 -73
- aigroup_econ_mcp/tools/__init__.py +6 -6
- aigroup_econ_mcp/tools/regression.py +213 -213
- aigroup_econ_mcp/tools/statistics.py +133 -133
- aigroup_econ_mcp/tools/time_series.py +259 -259
- aigroup_econ_mcp-0.1.5.dist-info/METADATA +448 -0
- aigroup_econ_mcp-0.1.5.dist-info/RECORD +12 -0
- {aigroup_econ_mcp-0.1.1.dist-info → aigroup_econ_mcp-0.1.5.dist-info}/licenses/LICENSE +20 -20
- aigroup_econ_mcp-0.1.1.dist-info/METADATA +0 -226
- aigroup_econ_mcp-0.1.1.dist-info/RECORD +0 -12
- {aigroup_econ_mcp-0.1.1.dist-info → aigroup_econ_mcp-0.1.5.dist-info}/WHEEL +0 -0
- {aigroup_econ_mcp-0.1.1.dist-info → aigroup_econ_mcp-0.1.5.dist-info}/entry_points.txt +0 -0
|
@@ -1,214 +1,214 @@
|
|
|
1
|
-
"""
|
|
2
|
-
回归分析工具
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pandas as pd
|
|
7
|
-
import statsmodels.api as sm
|
|
8
|
-
from typing import List, Dict, Any, Optional
|
|
9
|
-
from pydantic import BaseModel
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class OLSResult(BaseModel):
|
|
13
|
-
"""OLS回归结果"""
|
|
14
|
-
coefficients: Dict[str, Dict[str, float]]
|
|
15
|
-
rsquared: float
|
|
16
|
-
rsquared_adj: float
|
|
17
|
-
f_statistic: float
|
|
18
|
-
f_pvalue: float
|
|
19
|
-
aic: float
|
|
20
|
-
bic: float
|
|
21
|
-
n_obs: int
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class DiagnosticTests(BaseModel):
|
|
25
|
-
"""模型诊断结果"""
|
|
26
|
-
jb_statistic: float
|
|
27
|
-
jb_pvalue: float
|
|
28
|
-
bp_statistic: float
|
|
29
|
-
bp_pvalue: float
|
|
30
|
-
dw_statistic: float
|
|
31
|
-
vif: Dict[str, float]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def perform_ols_regression(
|
|
35
|
-
y: List[float],
|
|
36
|
-
X: List[List[float]],
|
|
37
|
-
feature_names: Optional[List[str]] = None,
|
|
38
|
-
add_constant: bool = True
|
|
39
|
-
) -> OLSResult:
|
|
40
|
-
"""执行OLS回归分析"""
|
|
41
|
-
# 准备数据
|
|
42
|
-
X_matrix = np.array(X)
|
|
43
|
-
y_vector = np.array(y)
|
|
44
|
-
|
|
45
|
-
if add_constant:
|
|
46
|
-
X_matrix = sm.add_constant(X_matrix)
|
|
47
|
-
|
|
48
|
-
# 拟合模型
|
|
49
|
-
model = sm.OLS(y_vector, X_matrix).fit()
|
|
50
|
-
|
|
51
|
-
# 构建结果
|
|
52
|
-
result = OLSResult(
|
|
53
|
-
coefficients={},
|
|
54
|
-
rsquared=model.rsquared,
|
|
55
|
-
rsquared_adj=model.rsquared_adj,
|
|
56
|
-
f_statistic=model.fvalue,
|
|
57
|
-
f_pvalue=model.f_pvalue,
|
|
58
|
-
aic=model.aic,
|
|
59
|
-
bic=model.bic,
|
|
60
|
-
n_obs=model.nobs
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
# 添加系数详情
|
|
64
|
-
conf_int = model.conf_int()
|
|
65
|
-
for i, coef in enumerate(model.params):
|
|
66
|
-
var_name = "const" if i == 0 and add_constant else feature_names[i-1] if feature_names else f"x{i}"
|
|
67
|
-
result.coefficients[var_name] = {
|
|
68
|
-
"coef": coef,
|
|
69
|
-
"std_err": model.bse[i],
|
|
70
|
-
"t_value": model.tvalues[i],
|
|
71
|
-
"p_value": model.pvalues[i],
|
|
72
|
-
"ci_lower": conf_int[i][0],
|
|
73
|
-
"ci_upper": conf_int[i][1]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return result
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def calculate_vif(X: List[List[float]], feature_names: Optional[List[str]] = None) -> Dict[str, float]:
|
|
80
|
-
"""计算方差膨胀因子(VIF)"""
|
|
81
|
-
X_matrix = np.array(X)
|
|
82
|
-
|
|
83
|
-
# 添加常数项用于VIF计算
|
|
84
|
-
X_with_const = sm.add_constant(X_matrix)
|
|
85
|
-
|
|
86
|
-
if feature_names is None:
|
|
87
|
-
feature_names = [f"x{i}" for i in range(X_matrix.shape[1])]
|
|
88
|
-
|
|
89
|
-
# 计算每个变量的VIF
|
|
90
|
-
vif_values = {}
|
|
91
|
-
|
|
92
|
-
for i in range(1, X_with_const.shape[1]): # 跳过常数项
|
|
93
|
-
var_name = feature_names[i-1] if i-1 < len(feature_names) else f"x{i-1}"
|
|
94
|
-
|
|
95
|
-
# 将当前变量作为因变量,其他作为自变量
|
|
96
|
-
y_temp = X_with_const[:, i]
|
|
97
|
-
X_temp = np.delete(X_with_const, i, axis=1)
|
|
98
|
-
|
|
99
|
-
# 拟合辅助回归
|
|
100
|
-
aux_model = sm.OLS(y_temp, X_temp).fit()
|
|
101
|
-
r_squared = aux_model.rsquared
|
|
102
|
-
|
|
103
|
-
# 计算VIF
|
|
104
|
-
if r_squared < 1:
|
|
105
|
-
vif = 1 / (1 - r_squared)
|
|
106
|
-
else:
|
|
107
|
-
vif = float('inf')
|
|
108
|
-
|
|
109
|
-
vif_values[var_name] = vif
|
|
110
|
-
|
|
111
|
-
return vif_values
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def run_diagnostic_tests(
|
|
115
|
-
y: List[float],
|
|
116
|
-
X: List[List[float]],
|
|
117
|
-
residuals: Optional[List[float]] = None
|
|
118
|
-
) -> DiagnosticTests:
|
|
119
|
-
"""运行模型诊断检验"""
|
|
120
|
-
X_matrix = np.array(X)
|
|
121
|
-
y_vector = np.array(y)
|
|
122
|
-
|
|
123
|
-
# 拟合模型获取残差
|
|
124
|
-
if residuals is None:
|
|
125
|
-
X_with_const = sm.add_constant(X_matrix)
|
|
126
|
-
model = sm.OLS(y_vector, X_with_const).fit()
|
|
127
|
-
residuals = model.resid
|
|
128
|
-
|
|
129
|
-
# Jarque-Bera正态性检验
|
|
130
|
-
jb_stat, jb_p_value, _, _ = sm.stats.stattools.jarque_bera(residuals)
|
|
131
|
-
|
|
132
|
-
# Breusch-Pagan异方差检验
|
|
133
|
-
X_with_const = sm.add_constant(X_matrix)
|
|
134
|
-
bp_stat, bp_p_value, _, _ = sm.stats.diagnostic.het_breuschpagan(residuals, X_with_const)
|
|
135
|
-
|
|
136
|
-
# Durbin-Watson序列相关检验
|
|
137
|
-
dw_stat = sm.stats.stattools.durbin_watson(residuals)
|
|
138
|
-
|
|
139
|
-
# 计算VIF
|
|
140
|
-
vif_values = calculate_vif(X_matrix)
|
|
141
|
-
|
|
142
|
-
return DiagnosticTests(
|
|
143
|
-
jb_statistic=jb_stat,
|
|
144
|
-
jb_pvalue=jb_p_value,
|
|
145
|
-
bp_statistic=bp_stat,
|
|
146
|
-
bp_pvalue=bp_p_value,
|
|
147
|
-
dw_statistic=dw_stat,
|
|
148
|
-
vif=vif_values
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def stepwise_regression(
|
|
153
|
-
y: List[float],
|
|
154
|
-
X: List[List[float]],
|
|
155
|
-
feature_names: List[str],
|
|
156
|
-
direction: str = "both",
|
|
157
|
-
alpha_in: float = 0.05,
|
|
158
|
-
alpha_out: float = 0.10
|
|
159
|
-
) -> Dict[str, Any]:
|
|
160
|
-
"""逐步回归(简化版本)"""
|
|
161
|
-
X_matrix = np.array(X)
|
|
162
|
-
y_vector = np.array(y)
|
|
163
|
-
|
|
164
|
-
# 为了简化,这里返回所有变量的模型
|
|
165
|
-
# 实际的逐步回归需要更复杂的实现
|
|
166
|
-
X_with_const = sm.add_constant(X_matrix)
|
|
167
|
-
final_model = sm.OLS(y_vector, X_with_const).fit()
|
|
168
|
-
|
|
169
|
-
# 找出显著的变量(p值 < alpha_in)
|
|
170
|
-
significant_features = []
|
|
171
|
-
significant_indices = []
|
|
172
|
-
|
|
173
|
-
for i, p_val in enumerate(final_model.pvalues[1:], 1): # 跳过常数项
|
|
174
|
-
if p_val < alpha_in:
|
|
175
|
-
significant_features.append(feature_names[i-1])
|
|
176
|
-
significant_indices.append(i)
|
|
177
|
-
|
|
178
|
-
# 如果有显著变量,返回只包含显著变量的模型
|
|
179
|
-
if significant_indices:
|
|
180
|
-
X_significant = sm.add_constant(X_matrix[:, [i-1 for i in significant_indices]])
|
|
181
|
-
significant_model = sm.OLS(y_vector, X_significant).fit()
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
"selected_features": significant_features,
|
|
185
|
-
"model_summary": {
|
|
186
|
-
"rsquared": significant_model.rsquared,
|
|
187
|
-
"rsquared_adj": significant_model.rsquared_adj,
|
|
188
|
-
"aic": significant_model.aic,
|
|
189
|
-
"bic": significant_model.bic,
|
|
190
|
-
"f_statistic": significant_model.fvalue,
|
|
191
|
-
"f_pvalue": significant_model.f_pvalue
|
|
192
|
-
},
|
|
193
|
-
"coefficients": dict(zip(
|
|
194
|
-
["const"] + significant_features,
|
|
195
|
-
zip(significant_model.params, significant_model.pvalues)
|
|
196
|
-
))
|
|
197
|
-
}
|
|
198
|
-
else:
|
|
199
|
-
# 如果没有显著变量,返回全模型
|
|
200
|
-
return {
|
|
201
|
-
"selected_features": feature_names,
|
|
202
|
-
"model_summary": {
|
|
203
|
-
"rsquared": final_model.rsquared,
|
|
204
|
-
"rsquared_adj": final_model.rsquared_adj,
|
|
205
|
-
"aic": final_model.aic,
|
|
206
|
-
"bic": final_model.bic,
|
|
207
|
-
"f_statistic": final_model.fvalue,
|
|
208
|
-
"f_pvalue": final_model.f_pvalue
|
|
209
|
-
},
|
|
210
|
-
"coefficients": dict(zip(
|
|
211
|
-
["const"] + feature_names,
|
|
212
|
-
zip(final_model.params, final_model.pvalues)
|
|
213
|
-
))
|
|
1
|
+
"""
|
|
2
|
+
回归分析工具
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import statsmodels.api as sm
|
|
8
|
+
from typing import List, Dict, Any, Optional
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class OLSResult(BaseModel):
|
|
13
|
+
"""OLS回归结果"""
|
|
14
|
+
coefficients: Dict[str, Dict[str, float]]
|
|
15
|
+
rsquared: float
|
|
16
|
+
rsquared_adj: float
|
|
17
|
+
f_statistic: float
|
|
18
|
+
f_pvalue: float
|
|
19
|
+
aic: float
|
|
20
|
+
bic: float
|
|
21
|
+
n_obs: int
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DiagnosticTests(BaseModel):
|
|
25
|
+
"""模型诊断结果"""
|
|
26
|
+
jb_statistic: float
|
|
27
|
+
jb_pvalue: float
|
|
28
|
+
bp_statistic: float
|
|
29
|
+
bp_pvalue: float
|
|
30
|
+
dw_statistic: float
|
|
31
|
+
vif: Dict[str, float]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def perform_ols_regression(
|
|
35
|
+
y: List[float],
|
|
36
|
+
X: List[List[float]],
|
|
37
|
+
feature_names: Optional[List[str]] = None,
|
|
38
|
+
add_constant: bool = True
|
|
39
|
+
) -> OLSResult:
|
|
40
|
+
"""执行OLS回归分析"""
|
|
41
|
+
# 准备数据
|
|
42
|
+
X_matrix = np.array(X)
|
|
43
|
+
y_vector = np.array(y)
|
|
44
|
+
|
|
45
|
+
if add_constant:
|
|
46
|
+
X_matrix = sm.add_constant(X_matrix)
|
|
47
|
+
|
|
48
|
+
# 拟合模型
|
|
49
|
+
model = sm.OLS(y_vector, X_matrix).fit()
|
|
50
|
+
|
|
51
|
+
# 构建结果
|
|
52
|
+
result = OLSResult(
|
|
53
|
+
coefficients={},
|
|
54
|
+
rsquared=model.rsquared,
|
|
55
|
+
rsquared_adj=model.rsquared_adj,
|
|
56
|
+
f_statistic=model.fvalue,
|
|
57
|
+
f_pvalue=model.f_pvalue,
|
|
58
|
+
aic=model.aic,
|
|
59
|
+
bic=model.bic,
|
|
60
|
+
n_obs=model.nobs
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# 添加系数详情
|
|
64
|
+
conf_int = model.conf_int()
|
|
65
|
+
for i, coef in enumerate(model.params):
|
|
66
|
+
var_name = "const" if i == 0 and add_constant else feature_names[i-1] if feature_names else f"x{i}"
|
|
67
|
+
result.coefficients[var_name] = {
|
|
68
|
+
"coef": coef,
|
|
69
|
+
"std_err": model.bse[i],
|
|
70
|
+
"t_value": model.tvalues[i],
|
|
71
|
+
"p_value": model.pvalues[i],
|
|
72
|
+
"ci_lower": conf_int[i][0],
|
|
73
|
+
"ci_upper": conf_int[i][1]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def calculate_vif(X: List[List[float]], feature_names: Optional[List[str]] = None) -> Dict[str, float]:
|
|
80
|
+
"""计算方差膨胀因子(VIF)"""
|
|
81
|
+
X_matrix = np.array(X)
|
|
82
|
+
|
|
83
|
+
# 添加常数项用于VIF计算
|
|
84
|
+
X_with_const = sm.add_constant(X_matrix)
|
|
85
|
+
|
|
86
|
+
if feature_names is None:
|
|
87
|
+
feature_names = [f"x{i}" for i in range(X_matrix.shape[1])]
|
|
88
|
+
|
|
89
|
+
# 计算每个变量的VIF
|
|
90
|
+
vif_values = {}
|
|
91
|
+
|
|
92
|
+
for i in range(1, X_with_const.shape[1]): # 跳过常数项
|
|
93
|
+
var_name = feature_names[i-1] if i-1 < len(feature_names) else f"x{i-1}"
|
|
94
|
+
|
|
95
|
+
# 将当前变量作为因变量,其他作为自变量
|
|
96
|
+
y_temp = X_with_const[:, i]
|
|
97
|
+
X_temp = np.delete(X_with_const, i, axis=1)
|
|
98
|
+
|
|
99
|
+
# 拟合辅助回归
|
|
100
|
+
aux_model = sm.OLS(y_temp, X_temp).fit()
|
|
101
|
+
r_squared = aux_model.rsquared
|
|
102
|
+
|
|
103
|
+
# 计算VIF
|
|
104
|
+
if r_squared < 1:
|
|
105
|
+
vif = 1 / (1 - r_squared)
|
|
106
|
+
else:
|
|
107
|
+
vif = float('inf')
|
|
108
|
+
|
|
109
|
+
vif_values[var_name] = vif
|
|
110
|
+
|
|
111
|
+
return vif_values
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def run_diagnostic_tests(
|
|
115
|
+
y: List[float],
|
|
116
|
+
X: List[List[float]],
|
|
117
|
+
residuals: Optional[List[float]] = None
|
|
118
|
+
) -> DiagnosticTests:
|
|
119
|
+
"""运行模型诊断检验"""
|
|
120
|
+
X_matrix = np.array(X)
|
|
121
|
+
y_vector = np.array(y)
|
|
122
|
+
|
|
123
|
+
# 拟合模型获取残差
|
|
124
|
+
if residuals is None:
|
|
125
|
+
X_with_const = sm.add_constant(X_matrix)
|
|
126
|
+
model = sm.OLS(y_vector, X_with_const).fit()
|
|
127
|
+
residuals = model.resid
|
|
128
|
+
|
|
129
|
+
# Jarque-Bera正态性检验
|
|
130
|
+
jb_stat, jb_p_value, _, _ = sm.stats.stattools.jarque_bera(residuals)
|
|
131
|
+
|
|
132
|
+
# Breusch-Pagan异方差检验
|
|
133
|
+
X_with_const = sm.add_constant(X_matrix)
|
|
134
|
+
bp_stat, bp_p_value, _, _ = sm.stats.diagnostic.het_breuschpagan(residuals, X_with_const)
|
|
135
|
+
|
|
136
|
+
# Durbin-Watson序列相关检验
|
|
137
|
+
dw_stat = sm.stats.stattools.durbin_watson(residuals)
|
|
138
|
+
|
|
139
|
+
# 计算VIF
|
|
140
|
+
vif_values = calculate_vif(X_matrix)
|
|
141
|
+
|
|
142
|
+
return DiagnosticTests(
|
|
143
|
+
jb_statistic=jb_stat,
|
|
144
|
+
jb_pvalue=jb_p_value,
|
|
145
|
+
bp_statistic=bp_stat,
|
|
146
|
+
bp_pvalue=bp_p_value,
|
|
147
|
+
dw_statistic=dw_stat,
|
|
148
|
+
vif=vif_values
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def stepwise_regression(
|
|
153
|
+
y: List[float],
|
|
154
|
+
X: List[List[float]],
|
|
155
|
+
feature_names: List[str],
|
|
156
|
+
direction: str = "both",
|
|
157
|
+
alpha_in: float = 0.05,
|
|
158
|
+
alpha_out: float = 0.10
|
|
159
|
+
) -> Dict[str, Any]:
|
|
160
|
+
"""逐步回归(简化版本)"""
|
|
161
|
+
X_matrix = np.array(X)
|
|
162
|
+
y_vector = np.array(y)
|
|
163
|
+
|
|
164
|
+
# 为了简化,这里返回所有变量的模型
|
|
165
|
+
# 实际的逐步回归需要更复杂的实现
|
|
166
|
+
X_with_const = sm.add_constant(X_matrix)
|
|
167
|
+
final_model = sm.OLS(y_vector, X_with_const).fit()
|
|
168
|
+
|
|
169
|
+
# 找出显著的变量(p值 < alpha_in)
|
|
170
|
+
significant_features = []
|
|
171
|
+
significant_indices = []
|
|
172
|
+
|
|
173
|
+
for i, p_val in enumerate(final_model.pvalues[1:], 1): # 跳过常数项
|
|
174
|
+
if p_val < alpha_in:
|
|
175
|
+
significant_features.append(feature_names[i-1])
|
|
176
|
+
significant_indices.append(i)
|
|
177
|
+
|
|
178
|
+
# 如果有显著变量,返回只包含显著变量的模型
|
|
179
|
+
if significant_indices:
|
|
180
|
+
X_significant = sm.add_constant(X_matrix[:, [i-1 for i in significant_indices]])
|
|
181
|
+
significant_model = sm.OLS(y_vector, X_significant).fit()
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
"selected_features": significant_features,
|
|
185
|
+
"model_summary": {
|
|
186
|
+
"rsquared": significant_model.rsquared,
|
|
187
|
+
"rsquared_adj": significant_model.rsquared_adj,
|
|
188
|
+
"aic": significant_model.aic,
|
|
189
|
+
"bic": significant_model.bic,
|
|
190
|
+
"f_statistic": significant_model.fvalue,
|
|
191
|
+
"f_pvalue": significant_model.f_pvalue
|
|
192
|
+
},
|
|
193
|
+
"coefficients": dict(zip(
|
|
194
|
+
["const"] + significant_features,
|
|
195
|
+
zip(significant_model.params, significant_model.pvalues)
|
|
196
|
+
))
|
|
197
|
+
}
|
|
198
|
+
else:
|
|
199
|
+
# 如果没有显著变量,返回全模型
|
|
200
|
+
return {
|
|
201
|
+
"selected_features": feature_names,
|
|
202
|
+
"model_summary": {
|
|
203
|
+
"rsquared": final_model.rsquared,
|
|
204
|
+
"rsquared_adj": final_model.rsquared_adj,
|
|
205
|
+
"aic": final_model.aic,
|
|
206
|
+
"bic": final_model.bic,
|
|
207
|
+
"f_statistic": final_model.fvalue,
|
|
208
|
+
"f_pvalue": final_model.f_pvalue
|
|
209
|
+
},
|
|
210
|
+
"coefficients": dict(zip(
|
|
211
|
+
["const"] + feature_names,
|
|
212
|
+
zip(final_model.params, final_model.pvalues)
|
|
213
|
+
))
|
|
214
214
|
}
|