1) 客服 Agent 四份交付文档 + 构建脚手架:品牌由包装占位 XX科技 / 旧名 南方财富 统一为南方基金(热线 400-889-8899 / 官网 nffund.com),系统名改为「智能服务系统」; 同步追加 §0.4 修订记录行,工程记录行保留原占位字面以支撑硬编码扫描验收。 2) 开发文档:清理 28 份已作废/残留文档(14 份移出归档 + 14 份仓库副本), 新增《文档规整方案与开发前待决事项-2026-09-17》。 3) 客服agent 四份交付文档首次纳入本分支。
71 lines
2.6 KiB
Python
71 lines
2.6 KiB
Python
"""把真实场内日行情同步进 `fin_market_price`(下单的硬前置)。
|
||
|
||
## 什么时候要跑
|
||
|
||
`fin_market_price` 是下单的硬前置:`TradeService` 要求产品在这张表里有
|
||
`close_price > 0`、`total_fund_shares > 0`,且 `source_updated_at` 落在 `MAX_QUOTE_AGE` 内。
|
||
**行情过期后没有任何自动刷新机制**,表现是下单全线 `503 FUND_QUOTE_UNAVAILABLE`,
|
||
而错误信息只说"行情已过期",看不出根因。
|
||
|
||
所以:**每次演示/验收之前跑一次本脚本**。它同时解决两件事:
|
||
· 把只有 2 只产品的行情补齐到全部场内产品(`seed_sim_account_demo` 只写 2 只);
|
||
· 把已有行情的时间戳刷新到当前,让新鲜度校验通过。
|
||
|
||
## 数据源
|
||
|
||
腾讯行情(`qt.gtimg.cn`)—— 本环境唯一可用的行情源:东财的 push2 / push2his
|
||
两个行情域名实测一律连接被拒(`Server disconnected`),而它的净值/概况域名正常。
|
||
总份额按"已有值 → 腾讯总市值推算 → 季度规模兜底"的优先级确定,详见
|
||
`app/service/market_price_sync_service.py`。
|
||
|
||
## 用法
|
||
|
||
python tools/sync_market_prices.py # 全部场内产品
|
||
python tools/sync_market_prices.py --codes 510300,510500
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import asyncio
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||
if str(PROJECT_ROOT) not in sys.path:
|
||
sys.path.insert(0, str(PROJECT_ROOT))
|
||
|
||
from app.service.market_price_sync_service import ( # noqa: E402
|
||
MarketPriceSyncService,
|
||
summarize,
|
||
)
|
||
|
||
if hasattr(sys.stdout, "reconfigure"):
|
||
sys.stdout.reconfigure(errors="replace") # type: ignore[union-attr]
|
||
|
||
|
||
async def main() -> int:
|
||
parser = argparse.ArgumentParser(description="同步场内日行情到 fin_market_price")
|
||
parser.add_argument("--codes", default="", help="只同步这些产品代码(逗号分隔)")
|
||
args = parser.parse_args()
|
||
|
||
codes = tuple(code.strip() for code in args.codes.split(",") if code.strip())
|
||
service = MarketPriceSyncService()
|
||
result = await service.sync(product_codes=codes or None)
|
||
|
||
print(summarize(result))
|
||
skipped = result.get("skipped") or []
|
||
if skipped:
|
||
print("\n未同步的产品(以及原因):")
|
||
for item in skipped:
|
||
print(f" · {item['product_code']} {item['reason']}")
|
||
if not result.get("written"):
|
||
print("\n[警告] 一行都没写 —— 下单仍然会失败。")
|
||
return 1
|
||
print("\n完成。下单应已可用(过期校验看的是 source_updated_at)。")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(asyncio.run(main()))
|