aigroup-econ-mcp 0.1.6__py3-none-any.whl → 0.2.0__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.
@@ -4,7 +4,7 @@ AIGroup 计量经济学 MCP 服务器
4
4
  使用最新的MCP特性提供专业计量经济学分析工具
5
5
  """
6
6
 
7
- from typing import List, Dict, Any, Optional, Annotated
7
+ from typing import List, Dict, Any, Optional, Annotated, Tuple
8
8
  from collections.abc import AsyncIterator
9
9
  from contextlib import asynccontextmanager
10
10
  from dataclasses import dataclass
@@ -160,7 +160,7 @@ async def descriptive_statistics(
160
160
  "失业率": [4.5, 4.2, 4.0, 4.3]
161
161
  }
162
162
 
163
- 要求:
163
+ 要求:
164
164
  - 至少包含一个变量
165
165
  - 每个变量的数据点数量应相同
166
166
  - 数值必须为浮点数或整数
@@ -262,12 +262,12 @@ async def ols_regression(
262
262
  Field(
263
263
  description="""因变量数据(被解释变量/响应变量)
264
264
 
265
- 示例:[12000, 13500, 11800, 14200, 15100]
265
+ 示例:[12000, 13500, 11800, 14200, 15100]
266
266
 
267
- 要求:
267
+ 要求:
268
268
  - 必须为数值列表
269
269
  - 长度必须与自变量观测数量一致
270
- - 不能包含缺失值(NaN
270
+ - 不能包含缺失值(NaN)
271
271
  - 建议样本量 >= 30"""
272
272
  )
273
273
  ],
@@ -283,7 +283,7 @@ async def ols_regression(
283
283
  [750, 4.9] # 第3个观测的自变量值
284
284
  ]
285
285
 
286
- 要求:
286
+ 要求:
287
287
  - 外层列表:每个元素代表一个观测
288
288
  - 内层列表:该观测的所有自变量值
289
289
  - 所有观测的自变量数量必须相同
@@ -297,7 +297,7 @@ async def ols_regression(
297
297
  default=None,
298
298
  description="""自变量名称列表(可选)
299
299
 
300
- 示例:["广告支出", "价格指数"]
300
+ 示例:["广告支出", "价格指数"]
301
301
 
302
302
  说明:
303
303
  - 如果不提供,将自动命名为 x1, x2, x3...
@@ -429,9 +429,9 @@ async def hypothesis_testing(
429
429
  Field(
430
430
  description="""第一组数据或单一样本数据
431
431
 
432
- 示例:[3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3]
432
+ 示例:[3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3]
433
433
 
434
- 要求:
434
+ 要求:
435
435
  - 必须为数值列表
436
436
  - 不能包含缺失值
437
437
  - 建议样本量 >= 30(大样本)
@@ -444,7 +444,7 @@ async def hypothesis_testing(
444
444
  default=None,
445
445
  description="""第二组数据(可选,用于双样本检验)
446
446
 
447
- 示例:[2.5, 2.9, 2.3, 2.6, 2.8]
447
+ 示例:[2.5, 2.9, 2.3, 2.6, 2.8]
448
448
 
449
449
  说明:
450
450
  - 仅在双样本t检验时需要提供
@@ -588,14 +588,14 @@ async def time_series_analysis(
588
588
  [12000, 13500, 11800, 14200, 15100, 14800, 16200, 15900]
589
589
  # 表示连续8期的观测值,如月度销售额
590
590
 
591
- 要求:
591
+ 要求:
592
592
  - 必须按时间顺序排列(从早到晚)
593
593
  - 建议至少30个观测点以获得可靠结果
594
594
  - 数据应等间隔采样(如日度、月度、季度)
595
595
  - 不能包含缺失值
596
596
  - 数据量越大,ACF/PACF分析越准确
597
597
 
598
- 应用示例:
598
+ 应用示例:
599
599
  - 股票价格序列
600
600
  - GDP季度数据
601
601
  - 月度销售额
@@ -737,7 +737,7 @@ async def correlation_analysis(
737
737
  "竞争对手数量": [3, 3, 4, 3]
738
738
  }
739
739
 
740
- 要求:
740
+ 要求:
741
741
  - 至少包含2个变量
742
742
  - 所有变量的数据点数量必须相同
743
743
  - 建议样本量 >= 30
@@ -759,7 +759,7 @@ async def correlation_analysis(
759
759
  - "pearson": 皮尔逊相关系数(默认)
760
760
  * 衡量线性相关关系
761
761
  * 取值范围:-1到1
762
- * 要求:数据近似正态分布
762
+ * 要求:数据近似正态分布
763
763
  * 对异常值敏感
764
764
 
765
765
  - "spearman": 斯皮尔曼秩相关系数
@@ -808,7 +808,7 @@ async def correlation_analysis(
808
808
  - 回归分析中,自变量间相关系数>0.8可能导致多重共线性
809
809
  - 小样本(<30)的相关系数可能不稳定
810
810
 
811
- 📖 实际应用示例:
811
+ 📖 实际应用示例:
812
812
  - 营销分析:广告支出与销售额的相关性
813
813
  - 金融分析:不同股票收益率之间的相关性
814
814
  - 经济研究:GDP增长与失业率的关系
@@ -853,4 +853,2491 @@ async def correlation_analysis(
853
853
 
854
854
  def create_mcp_server() -> FastMCP:
855
855
  """创建并返回MCP服务器实例"""
856
- return mcp
856
+ return mcp
857
+
858
+
859
+ # 面板数据分析工具
860
+ # 高级时间序列分析工具
861
+ from .tools.time_series import (
862
+ VARModelResult,
863
+ VECMModelResult,
864
+ GARCHModelResult,
865
+ StateSpaceModelResult,
866
+ var_model,
867
+ vecm_model,
868
+ garch_model,
869
+ state_space_model,
870
+ forecast_var,
871
+ impulse_response_analysis,
872
+ variance_decomposition
873
+ )
874
+
875
+
876
+ class VARModelArguments(BaseModel):
877
+ """VAR模型参数"""
878
+ data: Dict[str, List[float]] = Field(description="多变量时间序列数据")
879
+ max_lags: int = Field(default=5, description="最大滞后阶数")
880
+ ic: str = Field(default="aic", description="信息准则")
881
+
882
+
883
+ class VECMModelArguments(BaseModel):
884
+ """VECM模型参数"""
885
+ data: Dict[str, List[float]] = Field(description="多变量时间序列数据")
886
+ coint_rank: int = Field(default=1, description="协整秩")
887
+ deterministic: str = Field(default="co", description="确定性项")
888
+ max_lags: int = Field(default=5, description="最大滞后阶数")
889
+
890
+
891
+ class GARCHModelArguments(BaseModel):
892
+ """GARCH模型参数"""
893
+ data: List[float] = Field(description="时间序列数据")
894
+ order: Tuple[int, int] = Field(default=(1, 1), description="GARCH阶数")
895
+ dist: str = Field(default="normal", description="误差分布")
896
+
897
+
898
+ class StateSpaceModelArguments(BaseModel):
899
+ """状态空间模型参数"""
900
+ data: List[float] = Field(description="时间序列数据")
901
+ state_dim: int = Field(default=1, description="状态维度")
902
+ observation_dim: int = Field(default=1, description="观测维度")
903
+ trend: bool = Field(default=True, description="是否包含趋势项")
904
+ seasonal: bool = Field(default=False, description="是否包含季节项")
905
+ period: int = Field(default=12, description="季节周期")
906
+
907
+
908
+ class VARForecastArguments(BaseModel):
909
+ """VAR预测参数"""
910
+ data: Dict[str, List[float]] = Field(description="多变量时间序列数据")
911
+ steps: int = Field(default=10, description="预测步数")
912
+ max_lags: int = Field(default=5, description="最大滞后阶数")
913
+
914
+
915
+ class ImpulseResponseArguments(BaseModel):
916
+ """脉冲响应分析参数"""
917
+ data: Dict[str, List[float]] = Field(description="多变量时间序列数据")
918
+ periods: int = Field(default=10, description="响应期数")
919
+ max_lags: int = Field(default=5, description="最大滞后阶数")
920
+
921
+
922
+ class VarianceDecompositionArguments(BaseModel):
923
+ """方差分解参数"""
924
+ data: Dict[str, List[float]] = Field(description="多变量时间序列数据")
925
+ periods: int = Field(default=10, description="分解期数")
926
+ max_lags: int = Field(default=5, description="最大滞后阶数")
927
+ from .tools.panel_data import (
928
+ FixedEffectsResult,
929
+ RandomEffectsResult,
930
+ HausmanTestResult,
931
+ PanelUnitRootResult,
932
+ fixed_effects_model,
933
+ random_effects_model,
934
+ hausman_test,
935
+ panel_unit_root_test,
936
+ compare_panel_models
937
+ )
938
+
939
+
940
+ class FixedEffectsArguments(BaseModel):
941
+ """固定效应模型参数"""
942
+ y_data: List[float] = Field(description="因变量数据")
943
+ x_data: List[List[float]] = Field(description="自变量数据")
944
+ entity_ids: List[str] = Field(description="个体标识符")
945
+ time_periods: List[str] = Field(description="时间标识符")
946
+ feature_names: Optional[List[str]] = Field(default=None, description="自变量名称")
947
+ entity_effects: bool = Field(default=True, description="是否包含个体效应")
948
+ time_effects: bool = Field(default=False, description="是否包含时间效应")
949
+
950
+
951
+ class RandomEffectsArguments(BaseModel):
952
+ """随机效应模型参数"""
953
+ y_data: List[float] = Field(description="因变量数据")
954
+ x_data: List[List[float]] = Field(description="自变量数据")
955
+ entity_ids: List[str] = Field(description="个体标识符")
956
+ time_periods: List[str] = Field(description="时间标识符")
957
+ feature_names: Optional[List[str]] = Field(default=None, description="自变量名称")
958
+ entity_effects: bool = Field(default=True, description="是否包含个体效应")
959
+ time_effects: bool = Field(default=False, description="是否包含时间效应")
960
+
961
+
962
+ class HausmanTestArguments(BaseModel):
963
+ """Hausman检验参数"""
964
+ y_data: List[float] = Field(description="因变量数据")
965
+ x_data: List[List[float]] = Field(description="自变量数据")
966
+ entity_ids: List[str] = Field(description="个体标识符")
967
+ time_periods: List[str] = Field(description="时间标识符")
968
+ feature_names: Optional[List[str]] = Field(default=None, description="自变量名称")
969
+
970
+
971
+ class PanelUnitRootArguments(BaseModel):
972
+ """面板单位根检验参数"""
973
+ data: List[float] = Field(description="面板数据序列")
974
+ entity_ids: List[str] = Field(description="个体标识符")
975
+ time_periods: List[str] = Field(description="时间标识符")
976
+ test_type: str = Field(default="levinlin", description="检验类型")
977
+
978
+
979
+ @mcp.tool()
980
+ async def panel_fixed_effects(
981
+ ctx: Context[ServerSession, AppContext],
982
+ y_data: Annotated[
983
+ List[float],
984
+ Field(
985
+ description="""因变量数据(被解释变量)
986
+
987
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220, 240, 260]
988
+
989
+ 要求:
990
+ - 必须为数值列表
991
+ - 长度必须与自变量观测数量一致
992
+ - 不能包含缺失值(NaN)
993
+ - 建议样本量 >= 30"""
994
+ )
995
+ ],
996
+ x_data: Annotated[
997
+ List[List[float]],
998
+ Field(
999
+ description="""自变量数据(解释变量),二维列表格式
1000
+
1001
+ 示例格式(5个观测,2个自变量):
1002
+ [
1003
+ [5, 100], # 第1个观测的自变量值
1004
+ [6, 98], # 第2个观测的自变量值
1005
+ [7.5, 95], # 第3个观测的自变量值
1006
+ [6.5, 97], # 第4个观测的自变量值
1007
+ [9, 92] # 第5个观测的自变量值
1008
+ ]
1009
+
1010
+ 要求:
1011
+ - 外层列表:每个元素代表一个观测
1012
+ - 内层列表:该观测的所有自变量值
1013
+ - 所有观测的自变量数量必须相同
1014
+ - 观测数量必须与y_data长度一致"""
1015
+ )
1016
+ ],
1017
+ entity_ids: Annotated[
1018
+ List[str],
1019
+ Field(
1020
+ description="""个体标识符列表
1021
+
1022
+ 示例:["公司A", "公司A", "公司A", "公司B", "公司B", "公司B"]
1023
+
1024
+ 要求:
1025
+ - 长度必须与观测数量一致
1026
+ - 建议使用有意义的标识符
1027
+ - 每个个体应有多个时间观测"""
1028
+ )
1029
+ ],
1030
+ time_periods: Annotated[
1031
+ List[str],
1032
+ Field(
1033
+ description="""时间标识符列表
1034
+
1035
+ 示例:["2020Q1", "2020Q2", "2020Q3", "2020Q1", "2020Q2", "2020Q3"]
1036
+
1037
+ 要求:
1038
+ - 长度必须与观测数量一致
1039
+ - 建议使用标准时间格式
1040
+ - 每个时间点可以有多个个体观测"""
1041
+ )
1042
+ ],
1043
+ feature_names: Annotated[
1044
+ Optional[List[str]],
1045
+ Field(
1046
+ default=None,
1047
+ description="""自变量名称列表(可选)
1048
+
1049
+ 示例:["广告支出", "价格"]
1050
+
1051
+ 说明:
1052
+ - 如果不提供,将自动命名为 x1, x2, x3...
1053
+ - 名称数量必须与自变量数量一致
1054
+ - 建议使用有意义的名称以便解释结果"""
1055
+ )
1056
+ ] = None,
1057
+ entity_effects: Annotated[
1058
+ bool,
1059
+ Field(
1060
+ default=True,
1061
+ description="""是否包含个体效应
1062
+
1063
+ 说明:
1064
+ - True:包含个体固定效应(默认)
1065
+ - False:不包含个体固定效应
1066
+ - 通常建议包含个体效应以控制个体间差异"""
1067
+ )
1068
+ ] = True,
1069
+ time_effects: Annotated[
1070
+ bool,
1071
+ Field(
1072
+ default=False,
1073
+ description="""是否包含时间效应
1074
+
1075
+ 说明:
1076
+ - True:包含时间固定效应
1077
+ - False:不包含时间固定效应(默认)
1078
+ - 如果存在时间趋势,建议包含时间效应"""
1079
+ )
1080
+ ] = False
1081
+ ) -> CallToolResult:
1082
+ """固定效应模型分析
1083
+
1084
+ 📊 功能说明:
1085
+ 固定效应模型假设个体间存在不可观测的固定差异,通过组内变换消除这些固定效应。
1086
+ 适用于个体特征不随时间变化的情况。
1087
+
1088
+ 📈 模型形式:
1089
+ y_it = α_i + βX_it + ε_it
1090
+
1091
+ 💡 使用场景:
1092
+ - 研究个体内部随时间变化的影响
1093
+ - 控制个体固定特征的影响
1094
+ - 面板数据中个体间存在系统性差异
1095
+
1096
+ ⚠️ 注意事项:
1097
+ - 无法估计不随时间变化的变量的系数
1098
+ - 需要较大的时间维度以获得可靠估计
1099
+ - 对个体异质性敏感
1100
+
1101
+ Args:
1102
+ y_data: 因变量数据
1103
+ x_data: 自变量数据
1104
+ entity_ids: 个体标识符
1105
+ time_periods: 时间标识符
1106
+ feature_names: 自变量名称
1107
+ entity_effects: 是否包含个体效应
1108
+ time_effects: 是否包含时间效应
1109
+ ctx: MCP上下文对象
1110
+ """
1111
+ await ctx.info(f"开始固定效应模型分析,样本大小: {len(y_data)},个体数量: {len(set(entity_ids))}")
1112
+
1113
+ try:
1114
+ # 数据验证
1115
+ if not y_data:
1116
+ raise ValueError("因变量数据不能为空")
1117
+ if not x_data:
1118
+ raise ValueError("自变量数据不能为空")
1119
+ if len(y_data) != len(x_data):
1120
+ raise ValueError(f"因变量和自变量的观测数量不一致: y_data={len(y_data)}, x_data={len(x_data)}")
1121
+ if len(y_data) != len(entity_ids):
1122
+ raise ValueError(f"因变量和个体标识符数量不一致: y_data={len(y_data)}, entity_ids={len(entity_ids)}")
1123
+ if len(y_data) != len(time_periods):
1124
+ raise ValueError(f"因变量和时间标识符数量不一致: y_data={len(y_data)}, time_periods={len(time_periods)}")
1125
+
1126
+ # 执行固定效应模型分析
1127
+ result = fixed_effects_model(
1128
+ y_data, x_data, entity_ids, time_periods, feature_names,
1129
+ entity_effects, time_effects
1130
+ )
1131
+
1132
+ await ctx.info("固定效应模型分析完成")
1133
+
1134
+ return CallToolResult(
1135
+ content=[
1136
+ TextContent(
1137
+ type="text",
1138
+ text=f"固定效应模型分析结果:\n"
1139
+ f"R² = {result.rsquared:.4f}\n"
1140
+ f"调整R² = {result.rsquared_adj:.4f}\n"
1141
+ f"F统计量 = {result.f_statistic:.4f} (p = {result.f_pvalue:.4f})\n"
1142
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}\n"
1143
+ f"组内R² = {result.within_rsquared:.4f}\n"
1144
+ f"观测数量 = {result.n_obs}\n"
1145
+ f"个体效应: {'是' if result.entity_effects else '否'}, "
1146
+ f"时间效应: {'是' if result.time_effects else '否'}"
1147
+ )
1148
+ ],
1149
+ structuredContent=result.model_dump()
1150
+ )
1151
+
1152
+ except Exception as e:
1153
+ await ctx.error(f"固定效应模型分析出错: {str(e)}")
1154
+ return CallToolResult(
1155
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1156
+ isError=True
1157
+ )
1158
+
1159
+
1160
+ @mcp.tool()
1161
+ async def panel_random_effects(
1162
+ ctx: Context[ServerSession, AppContext],
1163
+ y_data: Annotated[
1164
+ List[float],
1165
+ Field(
1166
+ description="""因变量数据(被解释变量)
1167
+
1168
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220, 240, 260]
1169
+
1170
+ 要求:
1171
+ - 必须为数值列表
1172
+ - 长度必须与自变量观测数量一致
1173
+ - 不能包含缺失值(NaN)
1174
+ - 建议样本量 >= 30"""
1175
+ )
1176
+ ],
1177
+ x_data: Annotated[
1178
+ List[List[float]],
1179
+ Field(
1180
+ description="""自变量数据(解释变量),二维列表格式
1181
+
1182
+ 示例格式(5个观测,2个自变量):
1183
+ [
1184
+ [5, 100], # 第1个观测的自变量值
1185
+ [6, 98], # 第2个观测的自变量值
1186
+ [7.5, 95], # 第3个观测的自变量值
1187
+ [6.5, 97], # 第4个观测的自变量值
1188
+ [9, 92] # 第5个观测的自变量值
1189
+ ]
1190
+
1191
+ 要求:
1192
+ - 外层列表:每个元素代表一个观测
1193
+ - 内层列表:该观测的所有自变量值
1194
+ - 所有观测的自变量数量必须相同
1195
+ - 观测数量必须与y_data长度一致"""
1196
+ )
1197
+ ],
1198
+ entity_ids: Annotated[
1199
+ List[str],
1200
+ Field(
1201
+ description="""个体标识符列表
1202
+
1203
+ 示例:["公司A", "公司A", "公司A", "公司B", "公司B", "公司B"]
1204
+
1205
+ 要求:
1206
+ - 长度必须与观测数量一致
1207
+ - 建议使用有意义的标识符
1208
+ - 每个个体应有多个时间观测"""
1209
+ )
1210
+ ],
1211
+ time_periods: Annotated[
1212
+ List[str],
1213
+ Field(
1214
+ description="""时间标识符列表
1215
+
1216
+ 示例:["2020Q1", "2020Q2", "2020Q3", "2020Q1", "2020Q2", "2020Q3"]
1217
+
1218
+ 要求:
1219
+ - 长度必须与观测数量一致
1220
+ - 建议使用标准时间格式
1221
+ - 每个时间点可以有多个个体观测"""
1222
+ )
1223
+ ],
1224
+ feature_names: Annotated[
1225
+ Optional[List[str]],
1226
+ Field(
1227
+ default=None,
1228
+ description="""自变量名称列表(可选)
1229
+
1230
+ 示例:["广告支出", "价格"]
1231
+
1232
+ 说明:
1233
+ - 如果不提供,将自动命名为 x1, x2, x3...
1234
+ - 名称数量必须与自变量数量一致
1235
+ - 建议使用有意义的名称以便解释结果"""
1236
+ )
1237
+ ] = None,
1238
+ entity_effects: Annotated[
1239
+ bool,
1240
+ Field(
1241
+ default=True,
1242
+ description="""是否包含个体效应
1243
+
1244
+ 说明:
1245
+ - True:包含个体随机效应(默认)
1246
+ - False:不包含个体随机效应
1247
+ - 通常建议包含个体效应以控制个体间差异"""
1248
+ )
1249
+ ] = True,
1250
+ time_effects: Annotated[
1251
+ bool,
1252
+ Field(
1253
+ default=False,
1254
+ description="""是否包含时间效应
1255
+
1256
+ 说明:
1257
+ - True:包含时间随机效应
1258
+ - False:不包含时间随机效应(默认)
1259
+ - 如果存在时间趋势,建议包含时间效应"""
1260
+ )
1261
+ ] = False
1262
+ ) -> CallToolResult:
1263
+ """随机效应模型分析
1264
+
1265
+ 📊 功能说明:
1266
+ 随机效应模型假设个体间差异是随机的,通过GLS估计同时利用组内和组间变异。
1267
+ 适用于个体特征与解释变量不相关的情况。
1268
+
1269
+ 📈 模型形式:
1270
+ y_it = α + βX_it + μ_i + ε_it
1271
+
1272
+ 💡 使用场景:
1273
+ - 个体特征与解释变量不相关
1274
+ - 希望估计不随时间变化的变量的系数
1275
+ - 样本来自更大的总体
1276
+
1277
+ ⚠️ 注意事项:
1278
+ - 需要满足个体效应与解释变量不相关的假设
1279
+ - 如果假设不成立,估计可能不一致
1280
+ - 比固定效应模型更有效率
1281
+
1282
+ Args:
1283
+ y_data: 因变量数据
1284
+ x_data: 自变量数据
1285
+ entity_ids: 个体标识符
1286
+ time_periods: 时间标识符
1287
+ feature_names: 自变量名称
1288
+ entity_effects: 是否包含个体效应
1289
+ time_effects: 是否包含时间效应
1290
+ ctx: MCP上下文对象
1291
+ """
1292
+ await ctx.info(f"开始随机效应模型分析,样本大小: {len(y_data)},个体数量: {len(set(entity_ids))}")
1293
+
1294
+ try:
1295
+ # 数据验证
1296
+ if not y_data:
1297
+ raise ValueError("因变量数据不能为空")
1298
+ if not x_data:
1299
+ raise ValueError("自变量数据不能为空")
1300
+ if len(y_data) != len(x_data):
1301
+ raise ValueError(f"因变量和自变量的观测数量不一致: y_data={len(y_data)}, x_data={len(x_data)}")
1302
+ if len(y_data) != len(entity_ids):
1303
+ raise ValueError(f"因变量和个体标识符数量不一致: y_data={len(y_data)}, entity_ids={len(entity_ids)}")
1304
+ if len(y_data) != len(time_periods):
1305
+ raise ValueError(f"因变量和时间标识符数量不一致: y_data={len(y_data)}, time_periods={len(time_periods)}")
1306
+
1307
+ # 执行随机效应模型分析
1308
+ result = random_effects_model(
1309
+ y_data, x_data, entity_ids, time_periods, feature_names,
1310
+ entity_effects, time_effects
1311
+ )
1312
+
1313
+ await ctx.info("随机效应模型分析完成")
1314
+
1315
+ return CallToolResult(
1316
+ content=[
1317
+ TextContent(
1318
+ type="text",
1319
+ text=f"随机效应模型分析结果:\n"
1320
+ f"R² = {result.rsquared:.4f}\n"
1321
+ f"调整R² = {result.rsquared_adj:.4f}\n"
1322
+ f"F统计量 = {result.f_statistic:.4f} (p = {result.f_pvalue:.4f})\n"
1323
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}\n"
1324
+ f"组间R² = {result.between_rsquared:.4f}\n"
1325
+ f"观测数量 = {result.n_obs}\n"
1326
+ f"个体效应: {'是' if result.entity_effects else '否'}, "
1327
+ f"时间效应: {'是' if result.time_effects else '否'}"
1328
+ )
1329
+ ],
1330
+ structuredContent=result.model_dump()
1331
+ )
1332
+
1333
+ except Exception as e:
1334
+ await ctx.error(f"随机效应模型分析出错: {str(e)}")
1335
+ return CallToolResult(
1336
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1337
+ isError=True
1338
+ )
1339
+
1340
+
1341
+ @mcp.tool()
1342
+ async def panel_hausman_test(
1343
+ ctx: Context[ServerSession, AppContext],
1344
+ y_data: Annotated[
1345
+ List[float],
1346
+ Field(
1347
+ description="""因变量数据(被解释变量)
1348
+
1349
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220, 240, 260]
1350
+
1351
+ 要求:
1352
+ - 必须为数值列表
1353
+ - 长度必须与自变量观测数量一致
1354
+ - 不能包含缺失值(NaN)
1355
+ - 建议样本量 >= 30"""
1356
+ )
1357
+ ],
1358
+ x_data: Annotated[
1359
+ List[List[float]],
1360
+ Field(
1361
+ description="""自变量数据(解释变量),二维列表格式
1362
+
1363
+ 示例格式(5个观测,2个自变量):
1364
+ [
1365
+ [5, 100], # 第1个观测的自变量值
1366
+ [6, 98], # 第2个观测的自变量值
1367
+ [7.5, 95], # 第3个观测的自变量值
1368
+ [6.5, 97], # 第4个观测的自变量值
1369
+ [9, 92] # 第5个观测的自变量值
1370
+ ]
1371
+
1372
+ 要求:
1373
+ - 外层列表:每个元素代表一个观测
1374
+ - 内层列表:该观测的所有自变量值
1375
+ - 所有观测的自变量数量必须相同
1376
+ - 观测数量必须与y_data长度一致"""
1377
+ )
1378
+ ],
1379
+ entity_ids: Annotated[
1380
+ List[str],
1381
+ Field(
1382
+ description="""个体标识符列表
1383
+
1384
+ 示例:["公司A", "公司A", "公司A", "公司B", "公司B", "公司B"]
1385
+
1386
+ 要求:
1387
+ - 长度必须与观测数量一致
1388
+ - 建议使用有意义的标识符
1389
+ - 每个个体应有多个时间观测"""
1390
+ )
1391
+ ],
1392
+ time_periods: Annotated[
1393
+ List[str],
1394
+ Field(
1395
+ description="""时间标识符列表
1396
+
1397
+ 示例:["2020Q1", "2020Q2", "2020Q3", "2020Q1", "2020Q2", "2020Q3"]
1398
+
1399
+ 要求:
1400
+ - 长度必须与观测数量一致
1401
+ - 建议使用标准时间格式
1402
+ - 每个时间点可以有多个个体观测"""
1403
+ )
1404
+ ],
1405
+ feature_names: Annotated[
1406
+ Optional[List[str]],
1407
+ Field(
1408
+ default=None,
1409
+ description="""自变量名称列表(可选)
1410
+
1411
+ 示例:["广告支出", "价格"]
1412
+
1413
+ 说明:
1414
+ - 如果不提供,将自动命名为 x1, x2, x3...
1415
+ - 名称数量必须与自变量数量一致
1416
+ - 建议使用有意义的名称以便解释结果"""
1417
+ )
1418
+ ] = None
1419
+ ) -> CallToolResult:
1420
+ """Hausman检验
1421
+
1422
+ 📊 功能说明:
1423
+ Hausman检验用于比较固定效应模型和随机效应模型,判断个体效应是否与解释变量相关。
1424
+ 原假设:随机效应模型是一致的(个体效应与解释变量不相关)
1425
+ 备择假设:固定效应模型是一致的
1426
+
1427
+ 💡 使用场景:
1428
+ - 在固定效应和随机效应模型之间选择
1429
+ - 检验个体效应是否与解释变量相关
1430
+ - 验证随机效应模型的假设
1431
+
1432
+ ⚠️ 注意事项:
1433
+ - p值 < 0.05:拒绝原假设,选择固定效应模型
1434
+ - p值 >= 0.05:不能拒绝原假设,选择随机效应模型
1435
+ - 检验统计量服从卡方分布
1436
+
1437
+ Args:
1438
+ y_data: 因变量数据
1439
+ x_data: 自变量数据
1440
+ entity_ids: 个体标识符
1441
+ time_periods: 时间标识符
1442
+ feature_names: 自变量名称
1443
+ ctx: MCP上下文对象
1444
+ """
1445
+ await ctx.info(f"开始Hausman检验,样本大小: {len(y_data)},个体数量: {len(set(entity_ids))}")
1446
+
1447
+ try:
1448
+ # 数据验证
1449
+ if not y_data:
1450
+ raise ValueError("因变量数据不能为空")
1451
+ if not x_data:
1452
+ raise ValueError("自变量数据不能为空")
1453
+ if len(y_data) != len(x_data):
1454
+ raise ValueError(f"因变量和自变量的观测数量不一致: y_data={len(y_data)}, x_data={len(x_data)}")
1455
+ if len(y_data) != len(entity_ids):
1456
+ raise ValueError(f"因变量和个体标识符数量不一致: y_data={len(y_data)}, entity_ids={len(entity_ids)}")
1457
+ if len(y_data) != len(time_periods):
1458
+ raise ValueError(f"因变量和时间标识符数量不一致: y_data={len(y_data)}, time_periods={len(time_periods)}")
1459
+
1460
+ # 执行Hausman检验
1461
+ result = hausman_test(y_data, x_data, entity_ids, time_periods, feature_names)
1462
+
1463
+ await ctx.info("Hausman检验完成")
1464
+
1465
+ return CallToolResult(
1466
+ content=[
1467
+ TextContent(
1468
+ type="text",
1469
+ text=f"Hausman检验结果:\n"
1470
+ f"检验统计量 = {result.statistic:.4f}\n"
1471
+ f"p值 = {result.p_value:.4f}\n"
1472
+ f"{'显著' if result.significant else '不显著'} (5%水平)\n"
1473
+ f"建议:{result.recommendation}"
1474
+ )
1475
+ ],
1476
+ structuredContent=result.model_dump()
1477
+ )
1478
+
1479
+ except Exception as e:
1480
+ await ctx.error(f"Hausman检验出错: {str(e)}")
1481
+ return CallToolResult(
1482
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1483
+ isError=True
1484
+ )
1485
+
1486
+
1487
+ @mcp.tool()
1488
+ async def panel_unit_root_test(
1489
+ ctx: Context[ServerSession, AppContext],
1490
+ data: Annotated[
1491
+ List[float],
1492
+ Field(
1493
+ description="""面板数据序列
1494
+
1495
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220, 240, 260]
1496
+
1497
+ 要求:
1498
+ - 必须为数值列表
1499
+ - 长度必须与个体和时间标识符数量一致
1500
+ - 不能包含缺失值(NaN)
1501
+ - 建议每个个体至少有5个时间观测"""
1502
+ )
1503
+ ],
1504
+ entity_ids: Annotated[
1505
+ List[str],
1506
+ Field(
1507
+ description="""个体标识符列表
1508
+
1509
+ 示例:["公司A", "公司A", "公司A", "公司B", "公司B", "公司B"]
1510
+
1511
+ 要求:
1512
+ - 长度必须与数据序列长度一致
1513
+ - 建议使用有意义的标识符
1514
+ - 每个个体应有多个时间观测"""
1515
+ )
1516
+ ],
1517
+ time_periods: Annotated[
1518
+ List[str],
1519
+ Field(
1520
+ description="""时间标识符列表
1521
+
1522
+ 示例:["2020Q1", "2020Q2", "2020Q3", "2020Q1", "2020Q2", "2020Q3"]
1523
+
1524
+ 要求:
1525
+ - 长度必须与数据序列长度一致
1526
+ - 建议使用标准时间格式
1527
+ - 每个时间点可以有多个个体观测"""
1528
+ )
1529
+ ],
1530
+ test_type: Annotated[
1531
+ str,
1532
+ Field(
1533
+ default="levinlin",
1534
+ description="""面板单位根检验类型
1535
+
1536
+ 可选值:
1537
+ - "levinlin": Levin-Lin-Chu检验(默认)
1538
+ * 假设所有个体有相同的自回归系数
1539
+ * 适用于平衡面板数据
1540
+
1541
+ - "ips": Im-Pesaran-Shin检验
1542
+ * 允许个体间有不同的自回归系数
1543
+ * 适用于非平衡面板数据
1544
+
1545
+ - "fisher": Fisher组合检验
1546
+ * 基于个体ADF检验的组合
1547
+ * 适用于各种面板数据类型
1548
+
1549
+ 选择建议:
1550
+ - 平衡面板 + 同质系数 → levinlin
1551
+ - 非平衡面板 + 异质系数 → ips
1552
+ - 小样本或复杂情况 → fisher"""
1553
+ )
1554
+ ] = "levinlin"
1555
+ ) -> CallToolResult:
1556
+ """面板单位根检验
1557
+
1558
+ 📊 功能说明:
1559
+ 检验面板数据是否存在单位根,判断序列是否平稳。
1560
+ 常用的检验方法包括Levin-Lin-Chu检验、Im-Pesaran-Shin检验等。
1561
+
1562
+ 💡 使用场景:
1563
+ - 面板数据建模前的平稳性检验
1564
+ - 判断是否需要差分处理
1565
+ - 验证面板数据的协整关系
1566
+
1567
+ ⚠️ 注意事项:
1568
+ - p值 < 0.05:拒绝原假设,序列平稳
1569
+ - p值 >= 0.05:不能拒绝原假设,序列非平稳
1570
+ - 不同检验方法适用于不同的数据特征
1571
+
1572
+ Args:
1573
+ data: 面板数据序列
1574
+ entity_ids: 个体标识符
1575
+ time_periods: 时间标识符
1576
+ test_type: 检验类型
1577
+ ctx: MCP上下文对象
1578
+ """
1579
+ await ctx.info(f"开始面板单位根检验: {test_type},样本大小: {len(data)},个体数量: {len(set(entity_ids))}")
1580
+
1581
+ try:
1582
+ # 数据验证
1583
+ if not data:
1584
+ raise ValueError("面板数据不能为空")
1585
+ if len(data) != len(entity_ids):
1586
+ raise ValueError(f"数据和个体标识符数量不一致: data={len(data)}, entity_ids={len(entity_ids)}")
1587
+ if len(data) != len(time_periods):
1588
+ raise ValueError(f"数据和时间标识符数量不一致: data={len(data)}, time_periods={len(time_periods)}")
1589
+
1590
+ # 执行面板单位根检验
1591
+ result = panel_unit_root_test(data, entity_ids, time_periods, test_type)
1592
+
1593
+ await ctx.info("面板单位根检验完成")
1594
+
1595
+ return CallToolResult(
1596
+ content=[
1597
+ TextContent(
1598
+ type="text",
1599
+ text=f"面板单位根检验结果 ({result.test_type}):\n"
1600
+ f"检验统计量 = {result.statistic:.4f}\n"
1601
+ f"p值 = {result.p_value:.4f}\n"
1602
+ f"{'平稳' if result.stationary else '非平稳'}序列\n"
1603
+ f"建议:{'可直接建模' if result.stationary else '需要差分处理'}"
1604
+ )
1605
+ ],
1606
+ structuredContent=result.model_dump()
1607
+ )
1608
+
1609
+ except Exception as e:
1610
+ await ctx.error(f"面板单位根检验出错: {str(e)}")
1611
+ return CallToolResult(
1612
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1613
+ isError=True
1614
+ )
1615
+
1616
+ @mcp.tool()
1617
+ async def var_model_analysis(
1618
+ ctx: Context[ServerSession, AppContext],
1619
+ data: Annotated[
1620
+ Dict[str, List[float]],
1621
+ Field(
1622
+ description="""多变量时间序列数据
1623
+
1624
+ 示例格式:
1625
+ {
1626
+ "GDP增长率": [3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3, 3.0],
1627
+ "通货膨胀率": [2.1, 2.3, 1.9, 2.4, 2.2, 2.5, 2.0, 2.3],
1628
+ "失业率": [4.5, 4.2, 4.0, 4.3, 4.1, 4.4, 3.9, 4.2]
1629
+ }
1630
+
1631
+ 要求:
1632
+ - 至少包含2个变量
1633
+ - 所有变量的数据点数量必须相同
1634
+ - 建议样本量 >= 30
1635
+ - 数据应平稳或经过差分处理"""
1636
+ )
1637
+ ],
1638
+ max_lags: Annotated[
1639
+ int,
1640
+ Field(
1641
+ default=5,
1642
+ description="""最大滞后阶数
1643
+
1644
+ 说明:
1645
+ - 用于自动选择最优滞后阶数
1646
+ - 建议值:3-8
1647
+ - 样本量越大,可选择的滞后阶数越多"""
1648
+ )
1649
+ ] = 5,
1650
+ ic: Annotated[
1651
+ str,
1652
+ Field(
1653
+ default="aic",
1654
+ description="""信息准则
1655
+
1656
+ 可选值:
1657
+ - "aic": Akaike信息准则(默认)
1658
+ - "bic": Bayesian信息准则
1659
+ - "hqic": Hannan-Quinn信息准则
1660
+
1661
+ 选择建议:
1662
+ - 小样本 → AIC
1663
+ - 大样本 → BIC
1664
+ - 中等样本 → HQIC"""
1665
+ )
1666
+ ] = "aic"
1667
+ ) -> CallToolResult:
1668
+ """VAR模型分析
1669
+
1670
+ 📊 功能说明:
1671
+ 向量自回归模型用于分析多个时间序列变量之间的动态关系。
1672
+ 每个变量的当前值都依赖于所有变量的滞后值。
1673
+
1674
+ 📈 模型形式:
1675
+ Y_t = A_1 Y_{t-1} + A_2 Y_{t-2} + ... + A_p Y_{t-p} + ε_t
1676
+
1677
+ 💡 使用场景:
1678
+ - 宏观经济变量间的相互影响分析
1679
+ - 金融市场联动性研究
1680
+ - 脉冲响应函数和方差分解
1681
+ - 格兰杰因果关系检验
1682
+
1683
+ ⚠️ 注意事项:
1684
+ - 所有变量都应该是平稳的
1685
+ - 滞后阶数选择很重要
1686
+ - 变量数量不宜过多(避免维度灾难)
1687
+ - 样本量应足够大
1688
+
1689
+ Args:
1690
+ data: 多变量时间序列数据
1691
+ max_lags: 最大滞后阶数
1692
+ ic: 信息准则
1693
+ ctx: MCP上下文对象
1694
+ """
1695
+ await ctx.info(f"开始VAR模型分析,变量数量: {len(data)},最大滞后阶数: {max_lags}")
1696
+
1697
+ try:
1698
+ # 数据验证
1699
+ if not data:
1700
+ raise ValueError("数据不能为空")
1701
+ if len(data) < 2:
1702
+ raise ValueError("VAR模型至少需要2个变量")
1703
+
1704
+ # 执行VAR模型分析
1705
+ result = var_model(data, max_lags=max_lags, ic=ic)
1706
+
1707
+ await ctx.info("VAR模型分析完成")
1708
+
1709
+ return CallToolResult(
1710
+ content=[
1711
+ TextContent(
1712
+ type="text",
1713
+ text=f"VAR模型分析结果:\n"
1714
+ f"最优滞后阶数: {result.order}\n"
1715
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}, HQIC = {result.hqic:.2f}\n"
1716
+ f"变量数量: {len(data)}\n"
1717
+ f"格兰杰因果关系检验完成"
1718
+ )
1719
+ ],
1720
+ structuredContent=result.model_dump()
1721
+ )
1722
+
1723
+ except Exception as e:
1724
+ await ctx.error(f"VAR模型分析出错: {str(e)}")
1725
+ return CallToolResult(
1726
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1727
+ isError=True
1728
+ )
1729
+
1730
+
1731
+ @mcp.tool()
1732
+ async def vecm_model_analysis(
1733
+ ctx: Context[ServerSession, AppContext],
1734
+ data: Annotated[
1735
+ Dict[str, List[float]],
1736
+ Field(
1737
+ description="""多变量时间序列数据
1738
+
1739
+ 示例格式:
1740
+ {
1741
+ "GDP": [100, 102, 105, 103, 108, 110, 109, 112],
1742
+ "消费": [80, 82, 85, 83, 88, 90, 89, 92],
1743
+ "投资": [20, 21, 22, 21, 23, 24, 23, 25]
1744
+ }
1745
+
1746
+ 要求:
1747
+ - 至少包含2个变量
1748
+ - 所有变量的数据点数量必须相同
1749
+ - 建议样本量 >= 50
1750
+ - 变量应为一阶单整I(1)"""
1751
+ )
1752
+ ],
1753
+ coint_rank: Annotated[
1754
+ int,
1755
+ Field(
1756
+ default=1,
1757
+ description="""协整秩
1758
+
1759
+ 说明:
1760
+ - 协整向量的数量
1761
+ - 通常为变量数量-1
1762
+ - 需要根据协整检验确定"""
1763
+ )
1764
+ ] = 1,
1765
+ deterministic: Annotated[
1766
+ str,
1767
+ Field(
1768
+ default="co",
1769
+ description="""确定性项
1770
+
1771
+ 可选值:
1772
+ - "co": 常数项(默认)
1773
+ - "ci": 常数项和趋势项
1774
+ - "lo": 线性趋势
1775
+ - "li": 线性趋势和二次趋势"""
1776
+ )
1777
+ ] = "co",
1778
+ max_lags: Annotated[
1779
+ int,
1780
+ Field(
1781
+ default=5,
1782
+ description="""最大滞后阶数
1783
+
1784
+ 说明:
1785
+ - 用于误差修正模型
1786
+ - 建议值:2-6
1787
+ - 根据样本量调整"""
1788
+ )
1789
+ ] = 5
1790
+ ) -> CallToolResult:
1791
+ """VECM模型分析
1792
+
1793
+ 📊 功能说明:
1794
+ 用于分析非平稳时间序列之间的长期均衡关系和短期动态调整。
1795
+ 适用于存在协整关系的多变量系统。
1796
+
1797
+ 📈 模型形式:
1798
+ ΔY_t = αβ' Y_{t-1} + Γ_1 ΔY_{t-1} + ... + Γ_{p-1} ΔY_{t-p+1} + ε_t
1799
+
1800
+ 💡 使用场景:
1801
+ - 存在长期均衡关系的经济变量分析
1802
+ - 误差修正机制研究
1803
+ - 协整关系检验
1804
+ - 短期动态调整分析
1805
+
1806
+ ⚠️ 注意事项:
1807
+ - 所有变量应该是一阶单整的I(1)
1808
+ - 协整秩的选择很重要
1809
+ - 需要较大的样本量
1810
+ - 对模型设定敏感
1811
+
1812
+ Args:
1813
+ data: 多变量时间序列数据
1814
+ coint_rank: 协整秩
1815
+ deterministic: 确定性项
1816
+ max_lags: 最大滞后阶数
1817
+ ctx: MCP上下文对象
1818
+ """
1819
+ await ctx.info(f"开始VECM模型分析,变量数量: {len(data)},协整秩: {coint_rank}")
1820
+
1821
+ try:
1822
+ # 数据验证
1823
+ if not data:
1824
+ raise ValueError("数据不能为空")
1825
+ if len(data) < 2:
1826
+ raise ValueError("VECM模型至少需要2个变量")
1827
+
1828
+ # 执行VECM模型分析
1829
+ result = vecm_model(data, coint_rank=coint_rank, deterministic=deterministic, max_lags=max_lags)
1830
+
1831
+ await ctx.info("VECM模型分析完成")
1832
+
1833
+ return CallToolResult(
1834
+ content=[
1835
+ TextContent(
1836
+ type="text",
1837
+ text=f"VECM模型分析结果:\n"
1838
+ f"协整秩: {result.coint_rank}\n"
1839
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}, HQIC = {result.hqic:.2f}\n"
1840
+ f"协整关系数量: {len(result.cointegration_relations)}\n"
1841
+ f"调整速度计算完成"
1842
+ )
1843
+ ],
1844
+ structuredContent=result.model_dump()
1845
+ )
1846
+
1847
+ except Exception as e:
1848
+ await ctx.error(f"VECM模型分析出错: {str(e)}")
1849
+ return CallToolResult(
1850
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1851
+ isError=True
1852
+ )
1853
+
1854
+
1855
+ @mcp.tool()
1856
+ async def garch_model_analysis(
1857
+ ctx: Context[ServerSession, AppContext],
1858
+ data: Annotated[
1859
+ List[float],
1860
+ Field(
1861
+ description="""时间序列数据(通常是收益率)
1862
+
1863
+ 示例:[0.02, -0.015, 0.018, -0.008, 0.012, -0.005, 0.025, -0.01]
1864
+
1865
+ 要求:
1866
+ - 建议使用收益率数据
1867
+ - 不能包含缺失值
1868
+ - 建议样本量 >= 50
1869
+ - 数据应具有波动率聚类特征"""
1870
+ )
1871
+ ],
1872
+ order: Annotated[
1873
+ Tuple[int, int],
1874
+ Field(
1875
+ default=(1, 1),
1876
+ description="""GARCH阶数
1877
+
1878
+ 说明:
1879
+ - 第一个数:ARCH项阶数
1880
+ - 第二个数:GARCH项阶数
1881
+ - 常用阶数:(1,1)"""
1882
+ )
1883
+ ] = (1, 1),
1884
+ dist: Annotated[
1885
+ str,
1886
+ Field(
1887
+ default="normal",
1888
+ description="""误差分布
1889
+
1890
+ 可选值:
1891
+ - "normal": 正态分布(默认)
1892
+ - "t": t分布
1893
+ - "skewt": 偏t分布
1894
+
1895
+ 选择建议:
1896
+ - 一般情况 → normal
1897
+ - 厚尾数据 → t
1898
+ - 非对称数据 → skewt"""
1899
+ )
1900
+ ] = "normal"
1901
+ ) -> CallToolResult:
1902
+ """GARCH模型分析
1903
+
1904
+ 📊 功能说明:
1905
+ 用于建模金融时间序列的波动率聚类现象,捕捉条件方差的时变特征。
1906
+
1907
+ 📈 模型形式:
1908
+ r_t = μ + ε_t, ε_t = σ_t z_t
1909
+ σ_t² = ω + α ε_{t-1}² + β σ_{t-1}²
1910
+
1911
+ 💡 使用场景:
1912
+ - 金融资产波动率建模
1913
+ - 风险管理和VaR计算
1914
+ - 期权定价
1915
+ - 波动率预测
1916
+
1917
+ ⚠️ 注意事项:
1918
+ - 数据应具有波动率聚类特征
1919
+ - 需要较大的样本量
1920
+ - 对分布假设敏感
1921
+ - 高阶GARCH可能不稳定
1922
+
1923
+ Args:
1924
+ data: 时间序列数据
1925
+ order: GARCH阶数
1926
+ dist: 误差分布
1927
+ ctx: MCP上下文对象
1928
+ """
1929
+ await ctx.info(f"开始GARCH模型分析,样本大小: {len(data)},阶数: {order}")
1930
+
1931
+ try:
1932
+ # 数据验证
1933
+ if not data:
1934
+ raise ValueError("数据不能为空")
1935
+ if len(data) < 50:
1936
+ raise ValueError("GARCH模型至少需要50个观测点")
1937
+
1938
+ # 执行GARCH模型分析
1939
+ result = garch_model(data, order=order, dist=dist)
1940
+
1941
+ await ctx.info("GARCH模型分析完成")
1942
+
1943
+ return CallToolResult(
1944
+ content=[
1945
+ TextContent(
1946
+ type="text",
1947
+ text=f"GARCH模型分析结果:\n"
1948
+ f"阶数: {result.order}\n"
1949
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}\n"
1950
+ f"持久性: {result.persistence:.4f}\n"
1951
+ f"无条件方差: {result.unconditional_variance:.6f}"
1952
+ )
1953
+ ],
1954
+ structuredContent=result.model_dump()
1955
+ )
1956
+
1957
+ except Exception as e:
1958
+ await ctx.error(f"GARCH模型分析出错: {str(e)}")
1959
+ return CallToolResult(
1960
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
1961
+ isError=True
1962
+ )
1963
+
1964
+
1965
+ @mcp.tool()
1966
+ async def state_space_model_analysis(
1967
+ ctx: Context[ServerSession, AppContext],
1968
+ data: Annotated[
1969
+ List[float],
1970
+ Field(
1971
+ description="""时间序列数据
1972
+
1973
+ 示例:[100, 102, 105, 103, 108, 110, 109, 112, 115, 118]
1974
+
1975
+ 要求:
1976
+ - 不能包含缺失值
1977
+ - 建议样本量 >= 20
1978
+ - 数据应具有趋势或季节特征"""
1979
+ )
1980
+ ],
1981
+ state_dim: Annotated[
1982
+ int,
1983
+ Field(
1984
+ default=1,
1985
+ description="""状态维度
1986
+
1987
+ 说明:
1988
+ - 不可观测状态变量的维度
1989
+ - 通常为1-3
1990
+ - 根据模型复杂度选择"""
1991
+ )
1992
+ ] = 1,
1993
+ observation_dim: Annotated[
1994
+ int,
1995
+ Field(
1996
+ default=1,
1997
+ description="""观测维度
1998
+
1999
+ 说明:
2000
+ - 观测变量的维度
2001
+ - 通常为1
2002
+ - 多变量时为变量数量"""
2003
+ )
2004
+ ] = 1,
2005
+ trend: Annotated[
2006
+ bool,
2007
+ Field(
2008
+ default=True,
2009
+ description="""是否包含趋势项
2010
+
2011
+ 说明:
2012
+ - True:包含趋势项(默认)
2013
+ - False:不包含趋势项
2014
+ - 适用于有趋势的数据"""
2015
+ )
2016
+ ] = True,
2017
+ seasonal: Annotated[
2018
+ bool,
2019
+ Field(
2020
+ default=False,
2021
+ description="""是否包含季节项
2022
+
2023
+ 说明:
2024
+ - True:包含季节项
2025
+ - False:不包含季节项(默认)
2026
+ - 适用于有季节性的数据"""
2027
+ )
2028
+ ] = False,
2029
+ period: Annotated[
2030
+ int,
2031
+ Field(
2032
+ default=12,
2033
+ description="""季节周期
2034
+
2035
+ 说明:
2036
+ - 季节周期的长度
2037
+ - 月度数据:12
2038
+ - 季度数据:4
2039
+ - 日度数据:7"""
2040
+ )
2041
+ ] = 12
2042
+ ) -> CallToolResult:
2043
+ """状态空间模型分析
2044
+
2045
+ 📊 功能说明:
2046
+ 使用状态空间表示和卡尔曼滤波进行时间序列建模,可以处理不可观测的状态变量。
2047
+
2048
+ 📈 模型形式:
2049
+ 状态方程: α_t = T α_{t-1} + R η_t
2050
+ 观测方程: y_t = Z α_t + ε_t
2051
+
2052
+ 💡 使用场景:
2053
+ - 不可观测状态变量的估计
2054
+ - 结构时间序列建模
2055
+ - 实时滤波和平滑
2056
+ - 缺失数据处理
2057
+
2058
+ ⚠️ 注意事项:
2059
+ - 模型设定复杂
2060
+ - 需要先验知识
2061
+ - 计算量较大
2062
+ - 对初始值敏感
2063
+
2064
+ Args:
2065
+ data: 时间序列数据
2066
+ state_dim: 状态维度
2067
+ observation_dim: 观测维度
2068
+ trend: 是否包含趋势项
2069
+ seasonal: 是否包含季节项
2070
+ period: 季节周期
2071
+ ctx: MCP上下文对象
2072
+ """
2073
+ await ctx.info(f"开始状态空间模型分析,样本大小: {len(data)},状态维度: {state_dim}")
2074
+
2075
+ try:
2076
+ # 数据验证
2077
+ if not data:
2078
+ raise ValueError("数据不能为空")
2079
+ if len(data) < 20:
2080
+ raise ValueError("状态空间模型至少需要20个观测点")
2081
+
2082
+ # 执行状态空间模型分析
2083
+ result = state_space_model(
2084
+ data,
2085
+ state_dim=state_dim,
2086
+ observation_dim=observation_dim,
2087
+ trend=trend,
2088
+ seasonal=seasonal,
2089
+ period=period
2090
+ )
2091
+
2092
+ await ctx.info("状态空间模型分析完成")
2093
+
2094
+ return CallToolResult(
2095
+ content=[
2096
+ TextContent(
2097
+ type="text",
2098
+ text=f"状态空间模型分析结果:\n"
2099
+ f"状态变量: {result.state_names}\n"
2100
+ f"对数似然: {result.log_likelihood:.2f}\n"
2101
+ f"AIC = {result.aic:.2f}, BIC = {result.bic:.2f}\n"
2102
+ f"滤波和平滑完成"
2103
+ )
2104
+ ],
2105
+ structuredContent=result.model_dump()
2106
+ )
2107
+
2108
+ except Exception as e:
2109
+ await ctx.error(f"状态空间模型分析出错: {str(e)}")
2110
+ return CallToolResult(
2111
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2112
+ isError=True
2113
+ )
2114
+
2115
+
2116
+ @mcp.tool()
2117
+ async def var_forecast(
2118
+ ctx: Context[ServerSession, AppContext],
2119
+ data: Annotated[
2120
+ Dict[str, List[float]],
2121
+ Field(
2122
+ description="""多变量时间序列数据
2123
+
2124
+ 示例格式:
2125
+ {
2126
+ "GDP增长率": [3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3, 3.0],
2127
+ "通货膨胀率": [2.1, 2.3, 1.9, 2.4, 2.2, 2.5, 2.0, 2.3]
2128
+ }
2129
+
2130
+ 要求:
2131
+ - 至少包含2个变量
2132
+ - 所有变量的数据点数量必须相同
2133
+ - 建议样本量 >= 30
2134
+ - 数据应平稳或经过差分处理"""
2135
+ )
2136
+ ],
2137
+ steps: Annotated[
2138
+ int,
2139
+ Field(
2140
+ default=10,
2141
+ description="""预测步数
2142
+
2143
+ 说明:
2144
+ - 向前预测的期数
2145
+ - 建议值:5-20
2146
+ - 预测期数越长,不确定性越大"""
2147
+ )
2148
+ ] = 10,
2149
+ max_lags: Annotated[
2150
+ int,
2151
+ Field(
2152
+ default=5,
2153
+ description="""最大滞后阶数
2154
+
2155
+ 说明:
2156
+ - 用于VAR模型拟合
2157
+ - 建议值:3-8
2158
+ - 根据样本量调整"""
2159
+ )
2160
+ ] = 5
2161
+ ) -> CallToolResult:
2162
+ """VAR模型预测
2163
+
2164
+ 📊 功能说明:
2165
+ 基于VAR模型进行多变量时间序列预测。
2166
+
2167
+ 💡 使用场景:
2168
+ - 宏观经济变量联合预测
2169
+ - 金融市场联动预测
2170
+ - 政策模拟和情景分析
2171
+
2172
+ ⚠️ 注意事项:
2173
+ - 预测精度随步数增加而下降
2174
+ - 需要平稳数据
2175
+ - 预测结果包含不确定性
2176
+
2177
+ Args:
2178
+
2179
+ data: 多变量时间序列数据
2180
+ steps: 预测步数
2181
+ max_lags: 最大滞后阶数
2182
+ ctx: MCP上下文对象
2183
+ """
2184
+ await ctx.info(f"开始VAR模型预测,变量数量: {len(data)},预测步数: {steps}")
2185
+
2186
+ try:
2187
+ # 数据验证
2188
+ if not data:
2189
+ raise ValueError("数据不能为空")
2190
+ if len(data) < 2:
2191
+ raise ValueError("VAR预测至少需要2个变量")
2192
+
2193
+ # 执行VAR预测
2194
+ result = forecast_var(data, steps=steps, max_lags=max_lags)
2195
+
2196
+ await ctx.info("VAR模型预测完成")
2197
+
2198
+ return CallToolResult(
2199
+ content=[
2200
+ TextContent(
2201
+ type="text",
2202
+ text=f"VAR模型预测结果:\n"
2203
+ f"预测步数: {steps}\n"
2204
+ f"模型滞后阶数: {result['model_order']}\n"
2205
+ f"AIC = {result['model_aic']:.2f}, BIC = {result['model_bic']:.2f}\n"
2206
+ f"各变量预测值已生成"
2207
+ )
2208
+ ],
2209
+ structuredContent=result
2210
+ )
2211
+
2212
+ except Exception as e:
2213
+ await ctx.error(f"VAR模型预测出错: {str(e)}")
2214
+ return CallToolResult(
2215
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2216
+ isError=True
2217
+ )
2218
+
2219
+
2220
+ @mcp.tool()
2221
+ async def impulse_response_analysis(
2222
+ ctx: Context[ServerSession, AppContext],
2223
+ data: Annotated[
2224
+ Dict[str, List[float]],
2225
+ Field(
2226
+ description="""多变量时间序列数据
2227
+
2228
+ 示例格式:
2229
+ {
2230
+ "GDP增长率": [3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3, 3.0],
2231
+ "通货膨胀率": [2.1, 2.3, 1.9, 2.4, 2.2, 2.5, 2.0, 2.3],
2232
+ "利率": [2.5, 2.6, 2.4, 2.7, 2.5, 2.8, 2.3, 2.6]
2233
+ }
2234
+
2235
+ 要求:
2236
+ - 至少包含2个变量
2237
+ - 所有变量的数据点数量必须相同
2238
+ - 建议样本量 >= 30
2239
+ - 数据应平稳或经过差分处理"""
2240
+ )
2241
+ ],
2242
+ periods: Annotated[
2243
+ int,
2244
+ Field(
2245
+ default=10,
2246
+ description="""响应期数
2247
+
2248
+ 说明:
2249
+ - 脉冲响应的追踪期数
2250
+ - 建议值:5-20
2251
+ - 期数越长,计算量越大"""
2252
+ )
2253
+ ] = 10,
2254
+ max_lags: Annotated[
2255
+ int,
2256
+ Field(
2257
+ default=5,
2258
+ description="""最大滞后阶数
2259
+
2260
+ 说明:
2261
+ - 用于VAR模型拟合
2262
+ - 建议值:3-8
2263
+ - 根据样本量调整"""
2264
+ )
2265
+ ] = 5
2266
+ ) -> CallToolResult:
2267
+ """脉冲响应分析
2268
+
2269
+ 📊 功能说明:
2270
+ 分析一个变量的冲击对其他变量的动态影响。
2271
+
2272
+ 💡 使用场景:
2273
+ - 政策冲击效应分析
2274
+ - 变量间动态关系研究
2275
+ - 经济传导机制分析
2276
+
2277
+ ⚠️ 注意事项:
2278
+ - 需要正交化处理
2279
+ - 结果对变量顺序敏感
2280
+ - 需要平稳数据
2281
+
2282
+ Args:
2283
+ data: 多变量时间序列数据
2284
+ periods: 响应期数
2285
+ max_lags: 最大滞后阶数
2286
+ ctx: MCP上下文对象
2287
+ """
2288
+ await ctx.info(f"开始脉冲响应分析,变量数量: {len(data)},响应期数: {periods}")
2289
+
2290
+ try:
2291
+ # 数据验证
2292
+ if not data:
2293
+ raise ValueError("数据不能为空")
2294
+ if len(data) < 2:
2295
+ raise ValueError("脉冲响应分析至少需要2个变量")
2296
+
2297
+ # 执行脉冲响应分析
2298
+ result = impulse_response_analysis(data, periods=periods, max_lags=max_lags)
2299
+
2300
+ await ctx.info("脉冲响应分析完成")
2301
+
2302
+ return CallToolResult(
2303
+ content=[
2304
+ TextContent(
2305
+ type="text",
2306
+ text=f"脉冲响应分析结果:\n"
2307
+ f"响应期数: {periods}\n"
2308
+ f"变量数量: {len(data)}\n"
2309
+ f"所有冲击-响应组合的脉冲响应函数已计算"
2310
+ )
2311
+ ],
2312
+ structuredContent=result
2313
+ )
2314
+
2315
+ except Exception as e:
2316
+ await ctx.error(f"脉冲响应分析出错: {str(e)}")
2317
+ return CallToolResult(
2318
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2319
+ isError=True
2320
+ )
2321
+
2322
+
2323
+ @mcp.tool()
2324
+ async def variance_decomposition_analysis(
2325
+ ctx: Context[ServerSession, AppContext],
2326
+ data: Annotated[
2327
+ Dict[str, List[float]],
2328
+ Field(
2329
+ description="""多变量时间序列数据
2330
+
2331
+ 示例格式:
2332
+ {
2333
+ "GDP增长率": [3.2, 2.8, 3.5, 2.9, 3.1, 2.7, 3.3, 3.0],
2334
+ "通货膨胀率": [2.1, 2.3, 1.9, 2.4, 2.2, 2.5, 2.0, 2.3],
2335
+ "利率": [2.5, 2.6, 2.4, 2.7, 2.5, 2.8, 2.3, 2.6]
2336
+ }
2337
+
2338
+ 要求:
2339
+ - 至少包含2个变量
2340
+ - 所有变量的数据点数量必须相同
2341
+ - 建议样本量 >= 30
2342
+ - 数据应平稳或经过差分处理"""
2343
+ )
2344
+ ],
2345
+ periods: Annotated[
2346
+ int,
2347
+ Field(
2348
+ default=10,
2349
+ description="""分解期数
2350
+
2351
+ 说明:
2352
+ - 方差分解的期数
2353
+ - 建议值:5-20
2354
+ - 期数越长,结果越稳定"""
2355
+ )
2356
+ ] = 10,
2357
+ max_lags: Annotated[
2358
+ int,
2359
+ Field(
2360
+ default=5,
2361
+ description="""最大滞后阶数
2362
+
2363
+ 说明:
2364
+ - 用于VAR模型拟合
2365
+ - 建议值:3-8
2366
+ - 根据样本量调整"""
2367
+ )
2368
+ ] = 5
2369
+ ) -> CallToolResult:
2370
+ """方差分解分析
2371
+
2372
+ 📊 功能说明:
2373
+ 将每个变量的预测误差方差分解为各冲击源的贡献。
2374
+
2375
+ 💡 使用场景:
2376
+ - 变量重要性分析
2377
+ - 冲击来源识别
2378
+ - 系统稳定性分析
2379
+
2380
+ ⚠️ 注意事项:
2381
+ - 需要正交化处理
2382
+ - 结果对变量顺序敏感
2383
+ - 需要平稳数据
2384
+
2385
+ Args:
2386
+ data: 多变量时间序列数据
2387
+ periods: 分解期数
2388
+ max_lags: 最大滞后阶数
2389
+ ctx: MCP上下文对象
2390
+ """
2391
+ await ctx.info(f"开始方差分解分析,变量数量: {len(data)},分解期数: {periods}")
2392
+
2393
+ try:
2394
+ # 数据验证
2395
+ if not data:
2396
+ raise ValueError("数据不能为空")
2397
+ if len(data) < 2:
2398
+ raise ValueError("方差分解分析至少需要2个变量")
2399
+
2400
+ # 执行方差分解分析
2401
+ result = variance_decomposition(data, periods=periods, max_lags=max_lags)
2402
+
2403
+ await ctx.info("方差分解分析完成")
2404
+
2405
+ return CallToolResult(
2406
+ content=[
2407
+ TextContent(
2408
+ type="text",
2409
+ text=f"方差分解分析结果:\n"
2410
+ f"分解期数: {periods}\n"
2411
+ f"变量数量: {len(data)}\n"
2412
+ f"各变量方差分解已完成"
2413
+ )
2414
+ ],
2415
+ structuredContent=result
2416
+ )
2417
+
2418
+ except Exception as e:
2419
+ await ctx.error(f"方差分解分析出错: {str(e)}")
2420
+ return CallToolResult(
2421
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2422
+ isError=True
2423
+ )
2424
+
2425
+ # 机器学习工具导入
2426
+ from .tools.machine_learning import (
2427
+ RandomForestResult,
2428
+ GradientBoostingResult,
2429
+ RegularizedRegressionResult,
2430
+ CrossValidationResult,
2431
+ FeatureImportanceResult,
2432
+ random_forest_regression,
2433
+ gradient_boosting_regression,
2434
+ lasso_regression,
2435
+ ridge_regression,
2436
+ cross_validation,
2437
+ feature_importance_analysis,
2438
+ compare_ml_models
2439
+ )
2440
+
2441
+
2442
+ class RandomForestArguments(BaseModel):
2443
+ """随机森林回归参数"""
2444
+ y_data: List[float] = Field(description="因变量数据")
2445
+ x_data: List[List[float]] = Field(description="自变量数据")
2446
+ feature_names: Optional[List[str]] = Field(default=None, description="特征名称")
2447
+ n_estimators: int = Field(default=100, description="树的数量")
2448
+ max_depth: Optional[int] = Field(default=None, description="最大深度")
2449
+
2450
+
2451
+ class GradientBoostingArguments(BaseModel):
2452
+ """梯度提升树回归参数"""
2453
+ y_data: List[float] = Field(description="因变量数据")
2454
+ x_data: List[List[float]] = Field(description="自变量数据")
2455
+ feature_names: Optional[List[str]] = Field(default=None, description="特征名称")
2456
+ n_estimators: int = Field(default=100, description="树的数量")
2457
+ learning_rate: float = Field(default=0.1, description="学习率")
2458
+ max_depth: int = Field(default=3, description="最大深度")
2459
+
2460
+
2461
+ class LassoRegressionArguments(BaseModel):
2462
+ """Lasso回归参数"""
2463
+ y_data: List[float] = Field(description="因变量数据")
2464
+ x_data: List[List[float]] = Field(description="自变量数据")
2465
+ feature_names: Optional[List[str]] = Field(default=None, description="特征名称")
2466
+ alpha: float = Field(default=1.0, description="正则化强度")
2467
+
2468
+
2469
+ class RidgeRegressionArguments(BaseModel):
2470
+ """Ridge回归参数"""
2471
+ y_data: List[float] = Field(description="因变量数据")
2472
+ x_data: List[List[float]] = Field(description="自变量数据")
2473
+ feature_names: Optional[List[str]] = Field(default=None, description="特征名称")
2474
+ alpha: float = Field(default=1.0, description="正则化强度")
2475
+
2476
+
2477
+ class CrossValidationArguments(BaseModel):
2478
+ """交叉验证参数"""
2479
+ y_data: List[float] = Field(description="因变量数据")
2480
+ x_data: List[List[float]] = Field(description="自变量数据")
2481
+ model_type: str = Field(default="random_forest", description="模型类型")
2482
+ cv_folds: int = Field(default=5, description="交叉验证折数")
2483
+ scoring: str = Field(default="r2", description="评分指标")
2484
+
2485
+
2486
+ class FeatureImportanceArguments(BaseModel):
2487
+ """特征重要性分析参数"""
2488
+ y_data: List[float] = Field(description="因变量数据")
2489
+ x_data: List[List[float]] = Field(description="自变量数据")
2490
+ feature_names: Optional[List[str]] = Field(default=None, description="特征名称")
2491
+ method: str = Field(default="random_forest", description="分析方法")
2492
+ top_k: int = Field(default=5, description="最重要的特征数量")
2493
+
2494
+
2495
+ @mcp.tool()
2496
+ async def random_forest_regression_analysis(
2497
+ ctx: Context[ServerSession, AppContext],
2498
+ y_data: Annotated[
2499
+ List[float],
2500
+ Field(
2501
+ description="""因变量数据(被解释变量)
2502
+
2503
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
2504
+
2505
+ 要求:
2506
+ - 必须为数值列表
2507
+ - 长度必须与自变量观测数量一致
2508
+ - 不能包含缺失值(NaN)
2509
+ - 建议样本量 >= 30"""
2510
+ )
2511
+ ],
2512
+ x_data: Annotated[
2513
+ List[List[float]],
2514
+ Field(
2515
+ description="""自变量数据(解释变量),二维列表格式
2516
+
2517
+ 示例格式(4个观测,2个自变量):
2518
+ [
2519
+ [5, 100], # 第1个观测的自变量值
2520
+ [6, 98], # 第2个观测的自变量值
2521
+ [7.5, 95], # 第3个观测的自变量值
2522
+ [6.5, 97] # 第4个观测的自变量值
2523
+ ]
2524
+
2525
+ 要求:
2526
+ - 外层列表:每个元素代表一个观测
2527
+ - 内层列表:该观测的所有自变量值
2528
+ - 所有观测的自变量数量必须相同
2529
+ - 观测数量必须与y_data长度一致"""
2530
+ )
2531
+ ],
2532
+ feature_names: Annotated[
2533
+ Optional[List[str]],
2534
+ Field(
2535
+ default=None,
2536
+ description="""特征名称列表(可选)
2537
+
2538
+ 示例:["广告支出", "价格"]
2539
+
2540
+ 说明:
2541
+ - 如果不提供,将自动命名为 x1, x2, x3...
2542
+ - 名称数量必须与自变量数量一致
2543
+ - 建议使用有意义的名称以便解释结果"""
2544
+ )
2545
+ ] = None,
2546
+ n_estimators: Annotated[
2547
+ int,
2548
+ Field(
2549
+ default=100,
2550
+ description="""树的数量
2551
+
2552
+ 说明:
2553
+ - 随机森林中决策树的数量
2554
+ - 默认值:100
2555
+ - 建议范围:50-500
2556
+ - 树越多,模型越稳定但计算成本越高"""
2557
+ )
2558
+ ] = 100,
2559
+ max_depth: Annotated[
2560
+ Optional[int],
2561
+ Field(
2562
+ default=None,
2563
+ description="""最大深度
2564
+
2565
+ 说明:
2566
+ - 决策树的最大深度
2567
+ - None:不限制深度
2568
+ - 建议值:3-20
2569
+ - 深度越大,模型越复杂,可能过拟合"""
2570
+ )
2571
+ ] = None
2572
+ ) -> CallToolResult:
2573
+ """随机森林回归分析
2574
+
2575
+ 📊 功能说明:
2576
+ 使用随机森林算法进行回归分析,适用于非线性关系和复杂交互效应。
2577
+
2578
+ 📈 算法特点:
2579
+ - 集成学习:多个决策树的组合
2580
+ - 抗过拟合:通过袋外样本和特征随机选择
2581
+ - 非线性建模:能够捕捉复杂的非线性关系
2582
+ - 特征重要性:提供特征重要性排序
2583
+
2584
+ 💡 使用场景:
2585
+ - 复杂非线性关系建模
2586
+ - 特征重要性分析
2587
+ - 高维数据回归
2588
+ - 稳健预测建模
2589
+
2590
+ ⚠️ 注意事项:
2591
+ - 计算复杂度较高
2592
+ - 需要调整超参数(n_estimators, max_depth)
2593
+ - 对异常值相对稳健
2594
+
2595
+ Args:
2596
+ y_data: 因变量数据
2597
+ x_data: 自变量数据
2598
+ feature_names: 特征名称
2599
+ n_estimators: 树的数量
2600
+ max_depth: 最大深度
2601
+ ctx: MCP上下文对象
2602
+ """
2603
+ await ctx.info(f"开始随机森林回归分析,样本大小: {len(y_data)},特征数量: {len(x_data[0]) if x_data else 0}")
2604
+
2605
+ try:
2606
+ # 执行随机森林回归
2607
+ result = random_forest_regression(
2608
+ y_data, x_data, feature_names, n_estimators, max_depth
2609
+ )
2610
+
2611
+ await ctx.info("随机森林回归分析完成")
2612
+
2613
+ return CallToolResult(
2614
+ content=[
2615
+ TextContent(
2616
+ type="text",
2617
+ text=f"随机森林回归分析结果:\n"
2618
+ f"R² = {result.r2_score:.4f}\n"
2619
+ f"均方误差 = {result.mse:.4f}\n"
2620
+ f"平均绝对误差 = {result.mae:.4f}\n"
2621
+ f"树的数量 = {result.n_estimators}\n"
2622
+ f"最大深度 = {result.max_depth if result.max_depth != -1 else '无限制'}\n"
2623
+ f"袋外得分 = {result.oob_score:.4f if result.oob_score else 'N/A'}\n\n"
2624
+ f"特征重要性:\n" + "\n".join([
2625
+ f" {feature}: {importance:.4f}"
2626
+ for feature, importance in result.feature_importance.items()
2627
+ ])
2628
+ )
2629
+ ],
2630
+ structuredContent=result.model_dump()
2631
+ )
2632
+
2633
+ except Exception as e:
2634
+ await ctx.error(f"随机森林回归分析出错: {str(e)}")
2635
+ return CallToolResult(
2636
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2637
+ isError=True
2638
+ )
2639
+
2640
+
2641
+ @mcp.tool()
2642
+ async def gradient_boosting_regression_analysis(
2643
+ ctx: Context[ServerSession, AppContext],
2644
+ y_data: Annotated[
2645
+ List[float],
2646
+ Field(
2647
+ description="""因变量数据(被解释变量)
2648
+
2649
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
2650
+
2651
+ 要求:
2652
+ - 必须为数值列表
2653
+ - 长度必须与自变量观测数量一致
2654
+ - 不能包含缺失值(NaN)
2655
+ - 建议样本量 >= 30"""
2656
+ )
2657
+ ],
2658
+ x_data: Annotated[
2659
+ List[List[float]],
2660
+ Field(
2661
+ description="""自变量数据(解释变量),二维列表格式
2662
+
2663
+ 示例格式(4个观测,2个自变量):
2664
+ [
2665
+ [5, 100], # 第1个观测的自变量值
2666
+ [6, 98], # 第2个观测的自变量值
2667
+ [7.5, 95], # 第3个观测的自变量值
2668
+ [6.5, 97] # 第4个观测的自变量值
2669
+ ]
2670
+
2671
+ 要求:
2672
+ - 外层列表:每个元素代表一个观测
2673
+ - 内层列表:该观测的所有自变量值
2674
+ - 所有观测的自变量数量必须相同
2675
+ - 观测数量必须与y_data长度一致"""
2676
+ )
2677
+ ],
2678
+ feature_names: Annotated[
2679
+ Optional[List[str]],
2680
+ Field(
2681
+ default=None,
2682
+ description="""特征名称列表(可选)
2683
+
2684
+ 示例:["广告支出", "价格"]
2685
+
2686
+ 说明:
2687
+ - 如果不提供,将自动命名为 x1, x2, x3...
2688
+ - 名称数量必须与自变量数量一致
2689
+ - 建议使用有意义的名称以便解释结果"""
2690
+ )
2691
+ ] = None,
2692
+ n_estimators: Annotated[
2693
+ int,
2694
+ Field(
2695
+ default=100,
2696
+ description="""树的数量
2697
+
2698
+ 说明:
2699
+ - 梯度提升树中决策树的数量
2700
+ - 默认值:100
2701
+ - 建议范围:50-500
2702
+ - 树越多,模型越精确但计算成本越高"""
2703
+ )
2704
+ ] = 100,
2705
+ learning_rate: Annotated[
2706
+ float,
2707
+ Field(
2708
+ default=0.1,
2709
+ description="""学习率
2710
+
2711
+ 说明:
2712
+ - 每棵树对最终预测的贡献程度
2713
+ - 默认值:0.1
2714
+ - 建议范围:0.01-0.3
2715
+ - 学习率越小,需要更多的树"""
2716
+ )
2717
+ ] = 0.1,
2718
+ max_depth: Annotated[
2719
+ int,
2720
+ Field(
2721
+ default=3,
2722
+ description="""最大深度
2723
+
2724
+ 说明:
2725
+ - 决策树的最大深度
2726
+ - 默认值:3
2727
+ - 建议范围:2-8
2728
+ - 深度越大,模型越复杂,可能过拟合"""
2729
+ )
2730
+ ] = 3
2731
+ ) -> CallToolResult:
2732
+ """梯度提升树回归分析
2733
+
2734
+ 📊 功能说明:
2735
+ 使用梯度提升算法进行回归分析,通过逐步优化残差来提升模型性能。
2736
+
2737
+ 📈 算法特点:
2738
+ - 逐步优化:通过梯度下降逐步改进模型
2739
+ - 高精度:通常比随机森林有更好的预测精度
2740
+ - 正则化:通过学习率和树深度控制过拟合
2741
+ - 特征重要性:提供特征重要性排序
2742
+
2743
+ 💡 使用场景:
2744
+ - 高精度预测需求
2745
+ - 结构化数据建模
2746
+ - 竞赛和实际应用
2747
+ - 需要精细调优的场景
2748
+
2749
+ ⚠️ 注意事项:
2750
+ - 对超参数敏感
2751
+ - 训练时间较长
2752
+ - 容易过拟合(需要仔细调参)
2753
+
2754
+ Args:
2755
+ y_data: 因变量数据
2756
+ x_data: 自变量数据
2757
+ feature_names: 特征名称
2758
+ n_estimators: 树的数量
2759
+ learning_rate: 学习率
2760
+ max_depth: 最大深度
2761
+ ctx: MCP上下文对象
2762
+ """
2763
+ await ctx.info(f"开始梯度提升树回归分析,样本大小: {len(y_data)},特征数量: {len(x_data[0]) if x_data else 0}")
2764
+
2765
+ try:
2766
+ # 执行梯度提升树回归
2767
+ result = gradient_boosting_regression(
2768
+ y_data, x_data, feature_names, n_estimators, learning_rate, max_depth
2769
+ )
2770
+
2771
+ await ctx.info("梯度提升树回归分析完成")
2772
+
2773
+ return CallToolResult(
2774
+ content=[
2775
+ TextContent(
2776
+ type="text",
2777
+ text=f"梯度提升树回归分析结果:\n"
2778
+ f"R² = {result.r2_score:.4f}\n"
2779
+ f"均方误差 = {result.mse:.4f}\n"
2780
+ f"平均绝对误差 = {result.mae:.4f}\n"
2781
+ f"树的数量 = {result.n_estimators}\n"
2782
+ f"学习率 = {result.learning_rate}\n"
2783
+ f"最大深度 = {result.max_depth}\n\n"
2784
+ f"特征重要性:\n" + "\n".join([
2785
+ f" {feature}: {importance:.4f}"
2786
+ for feature, importance in result.feature_importance.items()
2787
+ ])
2788
+ )
2789
+ ],
2790
+ structuredContent=result.model_dump()
2791
+ )
2792
+
2793
+ except Exception as e:
2794
+ await ctx.error(f"梯度提升树回归分析出错: {str(e)}")
2795
+ return CallToolResult(
2796
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2797
+ isError=True
2798
+ )
2799
+
2800
+
2801
+ @mcp.tool()
2802
+ async def lasso_regression_analysis(
2803
+ ctx: Context[ServerSession, AppContext],
2804
+ y_data: Annotated[
2805
+ List[float],
2806
+ Field(
2807
+ description="""因变量数据(被解释变量)
2808
+
2809
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
2810
+
2811
+ 要求:
2812
+ - 必须为数值列表
2813
+ - 长度必须与自变量观测数量一致
2814
+ - 不能包含缺失值(NaN)
2815
+ - 建议样本量 >= 30"""
2816
+ )
2817
+ ],
2818
+ x_data: Annotated[
2819
+ List[List[float]],
2820
+ Field(
2821
+ description="""自变量数据(解释变量),二维列表格式
2822
+
2823
+ 示例格式(4个观测,2个自变量):
2824
+ [
2825
+ [5, 100], # 第1个观测的自变量值
2826
+ [6, 98], # 第2个观测的自变量值
2827
+ [7.5, 95], # 第3个观测的自变量值
2828
+ [6.5, 97] # 第4个观测的自变量值
2829
+ ]
2830
+
2831
+ 要求:
2832
+ - 外层列表:每个元素代表一个观测
2833
+ - 内层列表:该观测的所有自变量值
2834
+ - 所有观测的自变量数量必须相同
2835
+ - 观测数量必须与y_data长度一致"""
2836
+ )
2837
+ ],
2838
+ feature_names: Annotated[
2839
+ Optional[List[str]],
2840
+ Field(
2841
+ default=None,
2842
+ description="""特征名称列表(可选)
2843
+
2844
+ 示例:["广告支出", "价格"]
2845
+
2846
+ 说明:
2847
+ - 如果不提供,将自动命名为 x1, x2, x3...
2848
+ - 名称数量必须与自变量数量一致
2849
+ - 建议使用有意义的名称以便解释结果"""
2850
+ )
2851
+ ] = None,
2852
+ alpha: Annotated[
2853
+ float,
2854
+ Field(
2855
+ default=1.0,
2856
+ description="""正则化强度
2857
+
2858
+ 说明:
2859
+ - L1正则化的强度参数
2860
+ - 默认值:1.0
2861
+ - 建议范围:0.001-10
2862
+ - alpha越大,正则化越强,更多系数变为0"""
2863
+ )
2864
+ ] = 1.0
2865
+ ) -> CallToolResult:
2866
+ """Lasso回归分析
2867
+
2868
+ 📊 功能说明:
2869
+ 使用L1正则化的线性回归,能够进行特征选择和稀疏建模。
2870
+
2871
+ 📈 算法特点:
2872
+ - 特征选择:自动将不重要的特征系数压缩为0
2873
+ - 稀疏解:产生稀疏的系数向量
2874
+ - 可解释性:保留重要特征,去除冗余特征
2875
+ - 处理多重共线性:对高度相关的特征进行选择
2876
+
2877
+ 💡 使用场景:
2878
+ - 高维数据特征选择
2879
+ - 多重共线性问题
2880
+ - 稀疏建模需求
2881
+ - 可解释性要求高的场景
2882
+
2883
+ ⚠️ 注意事项:
2884
+ - 对alpha参数敏感
2885
+ - 可能过度压缩重要特征
2886
+ - 需要数据标准化
2887
+
2888
+ Args:
2889
+ y_data: 因变量数据
2890
+ x_data: 自变量数据
2891
+ feature_names: 特征名称
2892
+ alpha: 正则化强度
2893
+ ctx: MCP上下文对象
2894
+ """
2895
+ await ctx.info(f"开始Lasso回归分析,样本大小: {len(y_data)},特征数量: {len(x_data[0]) if x_data else 0}")
2896
+
2897
+ try:
2898
+ # 执行Lasso回归
2899
+ result = lasso_regression(y_data, x_data, feature_names, alpha)
2900
+
2901
+ await ctx.info("Lasso回归分析完成")
2902
+
2903
+ return CallToolResult(
2904
+ content=[
2905
+ TextContent(
2906
+ type="text",
2907
+ text=f"Lasso回归分析结果:\n"
2908
+ f"R² = {result.r2_score:.4f}\n"
2909
+ f"均方误差 = {result.mse:.4f}\n"
2910
+ f"平均绝对误差 = {result.mae:.4f}\n"
2911
+ f"正则化强度 = {result.alpha}\n\n"
2912
+ f"回归系数:\n" + "\n".join([
2913
+ f" {feature}: {coef:.4f}"
2914
+ for feature, coef in result.coefficients.items()
2915
+ ])
2916
+ )
2917
+ ],
2918
+ structuredContent=result.model_dump()
2919
+ )
2920
+
2921
+ except Exception as e:
2922
+ await ctx.error(f"Lasso回归分析出错: {str(e)}")
2923
+ return CallToolResult(
2924
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
2925
+ isError=True
2926
+ )
2927
+
2928
+
2929
+ @mcp.tool()
2930
+ async def ridge_regression_analysis(
2931
+ ctx: Context[ServerSession, AppContext],
2932
+ y_data: Annotated[
2933
+ List[float],
2934
+ Field(
2935
+ description="""因变量数据(被解释变量)
2936
+
2937
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
2938
+
2939
+ 要求:
2940
+ - 必须为数值列表
2941
+ - 长度必须与自变量观测数量一致
2942
+ - 不能包含缺失值(NaN)
2943
+ - 建议样本量 >= 30"""
2944
+ )
2945
+ ],
2946
+ x_data: Annotated[
2947
+ List[List[float]],
2948
+ Field(
2949
+ description="""自变量数据(解释变量),二维列表格式
2950
+
2951
+ 示例格式(4个观测,2个自变量):
2952
+ [
2953
+ [5, 100], # 第1个观测的自变量值
2954
+ [6, 98], # 第2个观测的自变量值
2955
+ [7.5, 95], # 第3个观测的自变量值
2956
+ [6.5, 97] # 第4个观测的自变量值
2957
+ ]
2958
+
2959
+ 要求:
2960
+ - 外层列表:每个元素代表一个观测
2961
+ - 内层列表:该观测的所有自变量值
2962
+ - 所有观测的自变量数量必须相同
2963
+ - 观测数量必须与y_data长度一致"""
2964
+ )
2965
+ ],
2966
+ feature_names: Annotated[
2967
+ Optional[List[str]],
2968
+ Field(
2969
+ default=None,
2970
+ description="""特征名称列表(可选)
2971
+
2972
+ 示例:["广告支出", "价格"]
2973
+
2974
+ 说明:
2975
+ - 如果不提供,将自动命名为 x1, x2, x3...
2976
+ - 名称数量必须与自变量数量一致
2977
+ - 建议使用有意义的名称以便解释结果"""
2978
+ )
2979
+ ] = None,
2980
+ alpha: Annotated[
2981
+ float,
2982
+ Field(
2983
+ default=1.0,
2984
+ description="""正则化强度
2985
+
2986
+ 说明:
2987
+ - L2正则化的强度参数
2988
+ - 默认值:1.0
2989
+ - 建议范围:0.001-10
2990
+ - alpha越大,正则化越强,系数收缩越明显"""
2991
+ )
2992
+ ] = 1.0
2993
+ ) -> CallToolResult:
2994
+ """Ridge回归分析
2995
+
2996
+ 📊 功能说明:
2997
+ 使用L2正则化的线性回归,能够处理多重共线性问题。
2998
+
2999
+ 📈 算法特点:
3000
+ - 稳定性:对多重共线性稳健
3001
+ - 收缩系数:将所有系数向0收缩
3002
+ - 无特征选择:保留所有特征
3003
+ - 数值稳定性:改善矩阵条件数
3004
+
3005
+ 💡 使用场景:
3006
+ - 多重共线性问题
3007
+ - 需要稳定估计的场景
3008
+ - 所有特征都可能有贡献的情况
3009
+ - 小样本高维数据
3010
+
3011
+ ⚠️ 注意事项:
3012
+ - 不进行特征选择
3013
+ - 对alpha参数敏感
3014
+ - 需要数据标准化
3015
+
3016
+ Args:
3017
+ y_data: 因变量数据
3018
+ x_data: 自变量数据
3019
+ feature_names: 特征名称
3020
+ alpha: 正则化强度
3021
+ ctx: MCP上下文对象
3022
+ """
3023
+ await ctx.info(f"开始Ridge回归分析,样本大小: {len(y_data)},特征数量: {len(x_data[0]) if x_data else 0}")
3024
+
3025
+ try:
3026
+ # 执行Ridge回归
3027
+ result = ridge_regression(y_data, x_data, feature_names, alpha)
3028
+
3029
+ await ctx.info("Ridge回归分析完成")
3030
+
3031
+ return CallToolResult(
3032
+ content=[
3033
+ TextContent(
3034
+ type="text",
3035
+ text=f"Ridge回归分析结果:\n"
3036
+ f"R² = {result.r2_score:.4f}\n"
3037
+ f"均方误差 = {result.mse:.4f}\n"
3038
+ f"平均绝对误差 = {result.mae:.4f}\n"
3039
+ f"正则化强度 = {result.alpha}\n\n"
3040
+ f"回归系数:\n" + "\n".join([
3041
+ f" {feature}: {coef:.4f}"
3042
+ for feature, coef in result.coefficients.items()
3043
+ ])
3044
+ )
3045
+ ],
3046
+ structuredContent=result.model_dump()
3047
+ )
3048
+
3049
+ except Exception as e:
3050
+ await ctx.error(f"Ridge回归分析出错: {str(e)}")
3051
+ return CallToolResult(
3052
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
3053
+ isError=True
3054
+ )
3055
+
3056
+
3057
+ @mcp.tool()
3058
+ async def cross_validation_analysis(
3059
+ ctx: Context[ServerSession, AppContext],
3060
+ y_data: Annotated[
3061
+ List[float],
3062
+ Field(
3063
+ description="""因变量数据(被解释变量)
3064
+
3065
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
3066
+
3067
+ 要求:
3068
+ - 必须为数值列表
3069
+ - 长度必须与自变量观测数量一致
3070
+ - 不能包含缺失值(NaN)
3071
+ - 建议样本量 >= 30"""
3072
+ )
3073
+ ],
3074
+ x_data: Annotated[
3075
+ List[List[float]],
3076
+ Field(
3077
+ description="""自变量数据(解释变量),二维列表格式
3078
+
3079
+ 示例格式(4个观测,2个自变量):
3080
+ [
3081
+ [5, 100], # 第1个观测的自变量值
3082
+ [6, 98], # 第2个观测的自变量值
3083
+ [7.5, 95], # 第3个观测的自变量值
3084
+ [6.5, 97] # 第4个观测的自变量值
3085
+ ]
3086
+
3087
+ 要求:
3088
+ - 外层列表:每个元素代表一个观测
3089
+ - 内层列表:该观测的所有自变量值
3090
+ - 所有观测的自变量数量必须相同
3091
+ - 观测数量必须与y_data长度一致"""
3092
+ )
3093
+ ],
3094
+ model_type: Annotated[
3095
+ str,
3096
+ Field(
3097
+ default="random_forest",
3098
+ description="""模型类型
3099
+
3100
+ 可选值:
3101
+ - "random_forest": 随机森林
3102
+ - "gradient_boosting": 梯度提升树
3103
+ - "lasso": Lasso回归
3104
+ - "ridge": Ridge回归
3105
+
3106
+ 选择建议:
3107
+ - 非线性关系 → random_forest, gradient_boosting
3108
+ - 特征选择 → lasso
3109
+ - 稳定性 → ridge"""
3110
+ )
3111
+ ] = "random_forest",
3112
+ cv_folds: Annotated[
3113
+ int,
3114
+ Field(
3115
+ default=5,
3116
+ description="""交叉验证折数
3117
+
3118
+ 说明:
3119
+ - 将数据分为多少份进行交叉验证
3120
+ - 默认值:5
3121
+ - 建议范围:3-10
3122
+ - 折数越多,评估越稳定但计算成本越高"""
3123
+ )
3124
+ ] = 5,
3125
+ scoring: Annotated[
3126
+ str,
3127
+ Field(
3128
+ default="r2",
3129
+ description="""评分指标
3130
+
3131
+ 可选值:
3132
+ - "r2": R²得分
3133
+ - "neg_mean_squared_error": 负均方误差
3134
+ - "neg_mean_absolute_error": 负平均绝对误差
3135
+
3136
+ 说明:
3137
+ - 使用负值指标时,得分越高表示模型越好"""
3138
+ )
3139
+ ] = "r2"
3140
+ ) -> CallToolResult:
3141
+ """交叉验证分析
3142
+
3143
+ 📊 功能说明:
3144
+ 通过交叉验证评估模型的泛化能力和稳定性。
3145
+
3146
+ 📈 验证方法:
3147
+ - K折交叉验证:将数据分为K份,轮流使用K-1份训练,1份测试
3148
+ - 稳定性评估:通过多次验证评估模型稳定性
3149
+ - 泛化能力:评估模型在未见数据上的表现
3150
+
3151
+ 💡 使用场景:
3152
+ - 模型选择和比较
3153
+ - 超参数调优
3154
+ - 评估模型稳定性
3155
+ - 防止过拟合
3156
+
3157
+ ⚠️ 注意事项:
3158
+ - 计算成本较高
3159
+ - 需要足够的数据量
3160
+ - 折数选择影响结果稳定性
3161
+
3162
+ Args:
3163
+ y_data: 因变量数据
3164
+ x_data: 自变量数据
3165
+ model_type: 模型类型
3166
+ cv_folds: 交叉验证折数
3167
+ scoring: 评分指标
3168
+ ctx: MCP上下文对象
3169
+ """
3170
+ await ctx.info(f"开始交叉验证分析,模型类型: {model_type},折数: {cv_folds}")
3171
+
3172
+ try:
3173
+ # 执行交叉验证
3174
+ result = cross_validation(
3175
+ y_data, x_data, model_type, cv_folds, scoring
3176
+ )
3177
+
3178
+ await ctx.info("交叉验证分析完成")
3179
+
3180
+ return CallToolResult(
3181
+ content=[
3182
+ TextContent(
3183
+ type="text",
3184
+ text=f"交叉验证分析结果:\n"
3185
+ f"模型类型 = {result.model_type}\n"
3186
+ f"交叉验证折数 = {result.n_splits}\n"
3187
+ f"平均得分 = {result.mean_score:.4f}\n"
3188
+ f"标准差 = {result.std_score:.4f}\n"
3189
+ f"各折得分 = {[f'{score:.4f}' for score in result.cv_scores]}"
3190
+ )
3191
+ ],
3192
+ structuredContent=result.model_dump()
3193
+ )
3194
+
3195
+ except Exception as e:
3196
+ await ctx.error(f"交叉验证分析出错: {str(e)}")
3197
+ return CallToolResult(
3198
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
3199
+ isError=True
3200
+ )
3201
+
3202
+
3203
+ @mcp.tool()
3204
+ async def feature_importance_analysis_tool(
3205
+ ctx: Context[ServerSession, AppContext],
3206
+ y_data: Annotated[
3207
+ List[float],
3208
+ Field(
3209
+ description="""因变量数据(被解释变量)
3210
+
3211
+ 示例:[100, 120, 150, 130, 180, 200, 190, 220]
3212
+
3213
+ 要求:
3214
+ - 必须为数值列表
3215
+ - 长度必须与自变量观测数量一致
3216
+ - 不能包含缺失值(NaN)
3217
+ - 建议样本量 >= 30"""
3218
+ )
3219
+ ],
3220
+ x_data: Annotated[
3221
+ List[List[float]],
3222
+ Field(
3223
+ description="""自变量数据(解释变量),二维列表格式
3224
+
3225
+ 示例格式(4个观测,2个自变量):
3226
+ [
3227
+ [5, 100], # 第1个观测的自变量值
3228
+ [6, 98], # 第2个观测的自变量值
3229
+ [7.5, 95], # 第3个观测的自变量值
3230
+ [6.5, 97] # 第4个观测的自变量值
3231
+ ]
3232
+
3233
+ 要求:
3234
+ - 外层列表:每个元素代表一个观测
3235
+ - 内层列表:该观测的所有自变量值
3236
+ - 所有观测的自变量数量必须相同
3237
+ - 观测数量必须与y_data长度一致"""
3238
+ )
3239
+ ],
3240
+ feature_names: Annotated[
3241
+ Optional[List[str]],
3242
+ Field(
3243
+ default=None,
3244
+ description="""特征名称列表(可选)
3245
+
3246
+ 示例:["广告支出", "价格"]
3247
+
3248
+ 说明:
3249
+ - 如果不提供,将自动命名为 x1, x2, x3...
3250
+ - 名称数量必须与自变量数量一致
3251
+ - 建议使用有意义的名称以便解释结果"""
3252
+ )
3253
+ ] = None,
3254
+ method: Annotated[
3255
+ str,
3256
+ Field(
3257
+ default="random_forest",
3258
+ description="""分析方法
3259
+
3260
+ 可选值:
3261
+ - "random_forest": 基于随机森林
3262
+ - "gradient_boosting": 基于梯度提升树
3263
+
3264
+ 选择建议:
3265
+ - 一般情况 → random_forest
3266
+ - 高精度需求 → gradient_boosting"""
3267
+ )
3268
+ ] = "random_forest",
3269
+ top_k: Annotated[
3270
+ int,
3271
+ Field(
3272
+ default=5,
3273
+ description="""最重要的特征数量
3274
+
3275
+ 说明:
3276
+ - 返回重要性排名前k的特征
3277
+ - 默认值:5
3278
+ - 建议范围:3-10
3279
+ - 根据实际需求调整"""
3280
+ )
3281
+ ] = 5
3282
+ ) -> CallToolResult:
3283
+ """特征重要性分析
3284
+
3285
+ 📊 功能说明:
3286
+ 分析各个特征对预测目标的重要性,帮助理解数据中的关键因素。
3287
+
3288
+ 📈 分析方法:
3289
+ - 基于模型:使用机器学习模型计算特征重要性
3290
+ - 排序分析:按重要性对特征进行排序
3291
+ - 关键特征识别:识别最重要的top-k个特征
3292
+
3293
+ 💡 使用场景:
3294
+ - 特征选择和降维
3295
+ - 模型可解释性分析
3296
+ - 业务洞察提取
3297
+ - 数据理解增强
3298
+
3299
+ ⚠️ 注意事项:
3300
+ - 不同方法可能给出不同的重要性排序
3301
+ - 重要性分数是相对的,不是绝对的
3302
+ - 需要结合业务知识解释结果
3303
+
3304
+ Args:
3305
+ y_data: 因变量数据
3306
+ x_data: 自变量数据
3307
+ feature_names: 特征名称
3308
+ method: 分析方法
3309
+ top_k: 最重要的特征数量
3310
+ ctx: MCP上下文对象
3311
+ """
3312
+ await ctx.info(f"开始特征重要性分析,分析方法: {method},top_k: {top_k}")
3313
+
3314
+ try:
3315
+ # 执行特征重要性分析
3316
+ result = feature_importance_analysis(
3317
+ y_data, x_data, feature_names, method, top_k
3318
+ )
3319
+
3320
+ await ctx.info("特征重要性分析完成")
3321
+
3322
+ return CallToolResult(
3323
+ content=[
3324
+ TextContent(
3325
+ type="text",
3326
+ text=f"特征重要性分析结果:\n"
3327
+ f"分析方法 = {method}\n"
3328
+ f"最重要的{top_k}个特征 = {result.top_features}\n\n"
3329
+ f"特征重要性排序:\n" + "\n".join([
3330
+ f" {i+1}. {feature}: {importance:.4f}"
3331
+ for i, (feature, importance) in enumerate(result.sorted_features)
3332
+ ])
3333
+ )
3334
+ ],
3335
+ structuredContent=result.model_dump()
3336
+ )
3337
+
3338
+ except Exception as e:
3339
+ await ctx.error(f"特征重要性分析出错: {str(e)}")
3340
+ return CallToolResult(
3341
+ content=[TextContent(type="text", text=f"错误: {str(e)}")],
3342
+ isError=True
3343
+ )