feat: 优化游资详情股票列表

This commit is contained in:
wanghep
2026-04-18 13:06:11 +08:00
parent 5a5dd3c9fd
commit d661b801df
6 changed files with 440 additions and 159 deletions

View File

@ -354,8 +354,7 @@ def fetch_trader_detail(trader_id: int) -> dict[str, Any]:
)
seats = [_normalize_row(row) for row in cursor.fetchall()]
cursor.execute(
"""
stock_query = """
SELECT
d.stock_code,
MAX(COALESCE(o.stock_name, d.stock_name)) AS stock_name,
@ -365,22 +364,120 @@ def fetch_trader_detail(trader_id: int) -> dict[str, Any]:
MAX(d.trade_date) AS last_trade_date,
SUM(CASE WHEN CAST(COALESCE(NULLIF(d.buy_amount_wan, ''), '0') AS DECIMAL(18,2)) > 0 THEN 1 ELSE 0 END) AS buy_action_count,
SUM(CASE WHEN CAST(COALESCE(NULLIF(d.sell_amount_wan, ''), '0') AS DECIMAL(18,2)) > 0 THEN 1 ELSE 0 END) AS sell_action_count,
SUM(CAST(COALESCE(NULLIF(d.net_amount_wan, ''), '0') AS DECIMAL(18,2))) AS total_net_amount_wan,
MAX(CASE WHEN w.warning_type = 'sell_alert' THEN 1 ELSE 0 END) AS has_sell_alert,
MAX(CASE WHEN w.warning_type = 'slow_exit_watch' THEN 1 ELSE 0 END) AS has_slow_exit
MAX(CASE WHEN w.warning_type = 'slow_exit_watch' THEN 1 ELSE 0 END) AS has_slow_exit,
MAX(s.industry) AS industry,
MAX(s.market) AS market,
MAX(s.total_market_value) AS total_market_value,
MAX(s.circulating_market_value) AS circulating_market_value
FROM lhb_detail_seats d
LEFT JOIN lhb_overview o
ON o.stock_code = d.stock_code AND o.trade_date = d.trade_date
LEFT JOIN warning_events w
ON w.stock_code = d.stock_code AND w.trader_name = d.matched_trader_name
LEFT JOIN stocks s
ON s.stock_code = d.stock_code
WHERE d.matched_trader_name = %s
GROUP BY d.stock_code
ORDER BY last_trade_date DESC, action_count DESC
LIMIT 100
""",
(trader_name,),
)
"""
cursor.execute(stock_query, (trader_name,))
stocks = [_normalize_row(row) for row in cursor.fetchall()]
stock_codes = [row["stock_code"] for row in stocks if row.get("stock_code")]
increasing_by_stock: dict[str, bool] = {}
if stock_codes:
placeholders = ", ".join(["%s"] * len(stock_codes))
cursor.execute(
f"""
SELECT
stock_code,
trade_date,
SUM(CAST(COALESCE(NULLIF(net_amount_wan, ''), '0') AS DECIMAL(18,2))) AS daily_net_amount_wan
FROM lhb_detail_seats
WHERE matched_trader_name = %s
AND stock_code IN ({placeholders})
AND trade_date IS NOT NULL
GROUP BY stock_code, trade_date
ORDER BY stock_code, trade_date
""",
(trader_name, *stock_codes),
)
net_history_by_stock: dict[str, list[float]] = {}
for row in cursor.fetchall():
stock_code = row["stock_code"]
net_history_by_stock.setdefault(stock_code, []).append(float(row["daily_net_amount_wan"] or 0))
for stock_code, net_history in net_history_by_stock.items():
increasing_by_stock[stock_code] = len(net_history) >= 2 and all(
current > previous for previous, current in zip(net_history, net_history[1:])
)
for stock in stocks:
stock["is_net_amount_increasing"] = increasing_by_stock.get(stock["stock_code"], False)
missing_codes = [
row["stock_code"]
for row in stocks[:30]
if not row.get("industry") or not row.get("market") or row.get("total_market_value") is None
]
if missing_codes:
eastmoney = EastMoneyClient()
seen_codes: set[str] = set()
for stock_code in missing_codes:
if stock_code in seen_codes:
continue
seen_codes.add(stock_code)
profile: dict[str, Any] = {}
snapshot: dict[str, Any] = {}
try:
profile = eastmoney.fetch_company_profile(stock_code)
except Exception:
profile = {}
try:
snapshot = eastmoney.fetch_quote_snapshot(stock_code)
except Exception:
snapshot = {}
cursor.execute(
"""
INSERT INTO stocks (
stock_code,
stock_name,
market,
industry,
concept_tags,
total_market_value,
circulating_market_value
)
VALUES (%s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
stock_name = COALESCE(NULLIF(VALUES(stock_name), ''), stock_name),
market = COALESCE(NULLIF(VALUES(market), ''), market),
industry = COALESCE(NULLIF(VALUES(industry), ''), industry),
concept_tags = COALESCE(VALUES(concept_tags), concept_tags),
total_market_value = COALESCE(VALUES(total_market_value), total_market_value),
circulating_market_value = COALESCE(VALUES(circulating_market_value), circulating_market_value)
""",
(
stock_code,
profile.get("stock_name") or (snapshot.get("stock_name") if snapshot else None) or stock_code,
profile.get("market"),
profile.get("industry") or snapshot.get("industry"),
json.dumps(profile.get("concept_tags") or [], ensure_ascii=False) if profile.get("concept_tags") else None,
snapshot.get("total_market_value"),
snapshot.get("circulating_market_value"),
),
)
cursor.execute(stock_query, (trader_name,))
stocks = [_normalize_row(row) for row in cursor.fetchall()]
for stock in stocks:
stock["is_net_amount_increasing"] = increasing_by_stock.get(stock["stock_code"], False)
cursor.execute(
"""
SELECT trade_date, stock_code, stock_name, warning_type, warning_level, trigger_reason