更新后端板块数据路由和服务(预提交)
This commit is contained in:
@@ -245,3 +245,19 @@ async def stock_fund_flow(
|
||||
"negativeDays": negative,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@router.get("/mx-tool", summary="MX 通用金融数据查询")
|
||||
async def mx_tool(
|
||||
query: str = Query(..., description="自然语言问句,如:「格力电器2024年净利润」「沪深300最新收盘价」「市盈率最低的50只股票」"),
|
||||
):
|
||||
"""通过 MX 妙想 API 查询任意金融数据(A股/港股/美股/基金/债券/指数/板块/宏观/新闻/公告/选股等)
|
||||
|
||||
单次查询最多支持 20 只证券。返回原始结构化表格(sheetName + columns + items)。
|
||||
"""
|
||||
if not query or not query.strip():
|
||||
raise HTTPException(status_code=400, detail="查询内容不能为空")
|
||||
data = await eastmoney.fetch_mx_tool(query.strip())
|
||||
if not data:
|
||||
raise HTTPException(status_code=404, detail="MX 查询无结果或所有 API Key 已耗尽")
|
||||
return {"data": data}
|
||||
|
||||
@@ -206,6 +206,75 @@ async def fetch_mx_api(name: str, days: int) -> Optional[List[dict]]:
|
||||
return None
|
||||
|
||||
|
||||
async def fetch_mx_tool(tool_query: str) -> Optional[dict]:
|
||||
"""通用 MX 妙想 API 查询(自然语言 → 结构化数据,缓存 6 小时)
|
||||
|
||||
支持东方财富数据库的全品类查询,包括但不限于:
|
||||
- A 股/港股/美股行情、财务、估值、股本、事件
|
||||
- 基金净值、收益、持仓、排名
|
||||
- 债券基本信息、久期凸性、信用评级
|
||||
- 指数与板块行情、技术指标
|
||||
- 宏观经济/行业经济/大宗商品数据
|
||||
- 新闻研报、公告搜索
|
||||
- 多条件选股/选基/选债
|
||||
|
||||
Args:
|
||||
tool_query: 自然语言问句,如 "格力电器2024年营业收入和净利润"
|
||||
"沪深300最新收盘价" "市盈率最低的50只股票"
|
||||
|
||||
Returns:
|
||||
MX API 原始 JSON(status=0 时成功,data 中含 sheetName/columns/items)
|
||||
失败返回 None
|
||||
"""
|
||||
cache_key = f"mx_tool:{tool_query}"
|
||||
cached = get_cache(cache_key)
|
||||
if cached is not None:
|
||||
return json.loads(cached)
|
||||
|
||||
if not _ensure_keys():
|
||||
return None
|
||||
|
||||
url = "https://mkapi2.dfcfs.com/finskillshub/api/claw/query"
|
||||
payload = {"toolQuery": tool_query}
|
||||
|
||||
for attempt in range(len(_api_keys)):
|
||||
key = _get_key()
|
||||
async with httpx.AsyncClient() as client:
|
||||
try:
|
||||
resp = await client.post(
|
||||
url,
|
||||
json=payload,
|
||||
headers={"Content-Type": "application/json", "apikey": key},
|
||||
timeout=15,
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
_rotate_key()
|
||||
continue
|
||||
result = resp.json()
|
||||
except Exception as e:
|
||||
print(f"[eastmoney] MX tool error: {e}")
|
||||
_rotate_key()
|
||||
continue
|
||||
|
||||
status = result.get("status", -1)
|
||||
if status == 113:
|
||||
print(f"[eastmoney] key 已达每日上限,切换到下一个")
|
||||
_rotate_key()
|
||||
continue
|
||||
if status == 114:
|
||||
_rotate_key()
|
||||
continue
|
||||
if status != 0:
|
||||
_rotate_key()
|
||||
continue
|
||||
|
||||
set_cache(cache_key, json.dumps(result, ensure_ascii=False), ttl_hours=6)
|
||||
return result
|
||||
|
||||
print(f"[eastmoney] 所有 MX API key 均已耗尽")
|
||||
return None
|
||||
|
||||
|
||||
def get_eastmoney_market(code: str) -> str:
|
||||
"""获取东方财富格式的市场标识"""
|
||||
if code.startswith("688"):
|
||||
|
||||
Reference in New Issue
Block a user