|
|
|
@ -599,43 +599,213 @@ def _split_codes(stocks: str) -> list[str]: |
|
|
|
return codes |
|
|
|
return codes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _simple_endpoint(path: str, fetch, label: str, default_years: int, has_years: bool = True): |
|
|
|
@app.get("/fin/mda") |
|
|
|
"""生成统一的 GET 端点: 只有 stocks (+years) 参数的接口.""" |
|
|
|
def fin_mda( |
|
|
|
def endpoint( |
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
years: int = Query(5, ge=1, le=20, description="拉取最近多少年的管理层讨论与分析"), |
|
|
|
years: Optional[int] = Query(default_years if has_years else None, ge=1, le=20, description=f"拉取最近多少年的{label}"), |
|
|
|
): |
|
|
|
): |
|
|
|
"""拉取管理层讨论与分析(年报/中报)。""" |
|
|
|
codes = _split_codes(stocks) |
|
|
|
codes = _split_codes(stocks) |
|
|
|
df = fetch(codes) if years is None else fetch(codes, years=years) |
|
|
|
df = get_mda(codes, years=years) |
|
|
|
if df.empty: |
|
|
|
if df.empty: |
|
|
|
extra = {"years": years} if years is not None else {} |
|
|
|
return _empty_response("无管理层讨论与分析数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
return _empty_response(f"无{label}数据, 请检查股票代码或筛选条件", codes, **extra) |
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
payload["codes_requested"] = codes |
|
|
|
payload["codes_requested"] = codes |
|
|
|
if years is not None: |
|
|
|
payload["years"] = years |
|
|
|
payload["years"] = years |
|
|
|
return payload |
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.get(path)(endpoint) |
|
|
|
@app.get("/fin/equity") |
|
|
|
return endpoint |
|
|
|
def fin_equity( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
): |
|
|
|
# ---- 管理层讨论与分析 / 股本结构 (无 years) ---- |
|
|
|
"""拉取股本结构 (全量历史)。""" |
|
|
|
_simple_endpoint("/fin/mda", get_mda, "管理层讨论与分析", default_years=5) |
|
|
|
codes = _split_codes(stocks) |
|
|
|
_simple_endpoint("/fin/equity", get_equity, "股本结构", default_years=3, has_years=False) |
|
|
|
df = get_equity(codes) |
|
|
|
_simple_endpoint("/fin/company-info", get_company_info, "公司介绍", default_years=3, has_years=False) |
|
|
|
if df.empty: |
|
|
|
_simple_endpoint("/fin/industry", get_industry, "所属行业", default_years=3, has_years=False) |
|
|
|
return _empty_response("无股本结构数据, 请检查股票代码或筛选条件", codes) |
|
|
|
_simple_endpoint("/fin/index-classif", get_index_classif, "所属指数分类", default_years=3, has_years=False) |
|
|
|
|
|
|
|
_simple_endpoint("/fin/belong-index", get_belong_index, "纳入指数统计", default_years=3, has_years=False) |
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
_simple_endpoint("/fin/index-membership", get_index_membership, "指数成分权重", default_years=3, has_years=False) |
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
# ---- 重大事项六类 ---- |
|
|
|
|
|
|
|
_simple_endpoint("/fin/acquisitions", get_acquisitions, "并购事件", default_years=3) |
|
|
|
|
|
|
|
_simple_endpoint("/fin/equity-incentive", get_equity_incentive, "股权激励", default_years=3) |
|
|
|
@app.get("/fin/company-info") |
|
|
|
_simple_endpoint("/fin/litigation", get_litigation, "诉讼仲裁", default_years=3) |
|
|
|
def fin_company_info( |
|
|
|
_simple_endpoint("/fin/related-transaction", get_related_transaction, "关联交易", default_years=3) |
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
_simple_endpoint("/fin/violation", get_violation, "违规处罚", default_years=3) |
|
|
|
): |
|
|
|
_simple_endpoint("/fin/guarantee", get_guarantee, "对外担保", default_years=3) |
|
|
|
"""拉取公司介绍 (基本资料)。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_company_info(codes) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无公司介绍数据, 请检查股票代码或筛选条件", codes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/industry") |
|
|
|
|
|
|
|
def fin_industry( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取所属行业 (当前生效分类)。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_industry(codes) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无所属行业数据, 请检查股票代码或筛选条件", codes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/index-classif") |
|
|
|
|
|
|
|
def fin_index_classif( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取所属指数分类。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_index_classif(codes) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无所属指数分类数据, 请检查股票代码或筛选条件", codes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/belong-index") |
|
|
|
|
|
|
|
def fin_belong_index( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取纳入指数统计。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_belong_index(codes) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无纳入指数统计数据, 请检查股票代码或筛选条件", codes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/index-membership") |
|
|
|
|
|
|
|
def fin_index_membership( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取指数成分权重。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_index_membership(codes) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无指数成分权重数据, 请检查股票代码或筛选条件", codes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/acquisitions") |
|
|
|
|
|
|
|
def fin_acquisitions( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的并购事件"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取并购事件。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_acquisitions(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无并购事件数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/equity-incentive") |
|
|
|
|
|
|
|
def fin_equity_incentive( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的股权激励"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取股权激励方案。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_equity_incentive(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无股权激励数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/litigation") |
|
|
|
|
|
|
|
def fin_litigation( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的诉讼仲裁"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取诉讼仲裁信息。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_litigation(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无诉讼仲裁数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/related-transaction") |
|
|
|
|
|
|
|
def fin_related_transaction( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的关联交易"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取关联交易。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_related_transaction(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无关联交易数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/violation") |
|
|
|
|
|
|
|
def fin_violation( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的违规处罚"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取违规处罚记录。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_violation(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无违规处罚数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/fin/guarantee") |
|
|
|
|
|
|
|
def fin_guarantee( |
|
|
|
|
|
|
|
stocks: str = Query(..., description="股票代码,逗号分隔,例如 '603233.SH'。仅支持代码,不需要 ORG_CODE。", examples=["603233.SH"]), |
|
|
|
|
|
|
|
years: int = Query(3, ge=1, le=20, description="拉取最近多少年的对外担保"), |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
"""拉取对外担保记录。""" |
|
|
|
|
|
|
|
codes = _split_codes(stocks) |
|
|
|
|
|
|
|
df = get_guarantee(codes, years=years) |
|
|
|
|
|
|
|
if df.empty: |
|
|
|
|
|
|
|
return _empty_response("无对外担保数据, 请检查股票代码或筛选条件", codes, years=years) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
payload = _df_to_json_payload(df) |
|
|
|
|
|
|
|
payload["codes_requested"] = codes |
|
|
|
|
|
|
|
payload["years"] = years |
|
|
|
|
|
|
|
return payload |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
if __name__ == "__main__": |
|
|
|
|