stock-ai-agent/backend/diagnose_sector_detection.py
2026-03-11 00:01:18 +08:00

151 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
诊断板块资金异动检测
检查为什么没有找到异动板块
"""
import asyncio
import sys
import os
from datetime import datetime, timedelta
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from app.utils.logger import logger
from app.config import get_settings
from app.astock_agent.tushare_client import get_tushare_client
async def diagnose_sector_detection():
"""诊断板块检测"""
print("\n" + "=" * 80)
print("🔍 板块资金异动诊断")
print("=" * 80)
settings = get_settings()
ts_client = get_tushare_client(settings.tushare_token)
# 获取热门概念板块
print("\n【第一步】获取热门概念板块...")
hot_concept_sectors = [
'人工智能', '新能源汽车', '芯片', '半导体', '5G',
'智能电网', '物联网', '云计算', '大数据', '区块链'
]
sectors_df = ts_client.get_concept_sectors()
# 找到热门板块
hot_sectors_codes = []
for hot_name in hot_concept_sectors:
matches = sectors_df[sectors_df['name'].str.contains(hot_name, na=False)]
if not matches.empty:
for _, row in matches.iterrows():
hot_sectors_codes.append({
'ts_code': row['ts_code'],
'name': row['name']
})
print(f"✓ 找到 {len(hot_sectors_codes)} 个热门板块")
# 检查这些板块的资金异动
print("\n【第二步】检查板块资金异动(量比、额比、涨幅)...")
print("=" * 80)
today = datetime.now().strftime('%Y%m%d')
yesterday = (datetime.now() - timedelta(days=10)).strftime('%Y%m%d')
# 宽松模式的阈值
vol_threshold = 1.5
amount_threshold = 1.3
min_change = 0.5
qualified_sectors = []
for sector_info in hot_sectors_codes[:15]: # 只检查前15个
ts_code = sector_info['ts_code']
name = sector_info['name']
try:
daily_df = ts_client.pro.ths_daily(
ts_code=ts_code,
start_date=yesterday,
end_date=today
)
if daily_df.empty or len(daily_df) < 2:
print(f" ⚠️ {name}: 数据不足")
continue
daily_df = daily_df.sort_values('trade_date')
latest = daily_df.iloc[-1]
prev = daily_df.iloc[-2]
latest_vol = float(latest.get('vol', 0))
latest_avg_price = float(latest.get('avg_price', 0))
latest_amount = latest_vol * latest_avg_price * 100 # 估算成交额
prev_vol = float(prev.get('vol', 0))
prev_avg_price = float(prev.get('avg_price', 0))
prev_amount = prev_vol * prev_avg_price * 100
change_pct = float(latest.get('pct_change', 0))
# 计算量比和额比
vol_ratio = latest_vol / prev_vol if prev_vol > 0 else 0
amount_ratio = latest_amount / prev_amount if prev_amount > 0 else 0
# 判断是否符合条件
is_volume_surge = vol_ratio >= vol_threshold
is_amount_surge = amount_ratio >= amount_threshold
has_min_change = change_pct >= min_change
is_qualified = (is_volume_surge or is_amount_surge) and has_min_change
# 显示结果
status = "" if is_qualified else ""
vol_status = "🔥" if is_volume_surge else "📊"
amount_status = "🔥" if is_amount_surge else "📊"
change_status = "" if has_min_change else ""
print(f" {status} {name}")
print(f" 涨跌幅: {change_pct:+.2f}% {change_status}")
print(f" 量比: {vol_ratio:.2f}x {vol_status} (需要≥{vol_threshold})")
print(f" 额比: {amount_ratio:.2f}x {amount_status} (需要≥{amount_threshold})")
if is_qualified:
qualified_sectors.append({
'name': name,
'change_pct': change_pct,
'vol_ratio': vol_ratio,
'amount_ratio': amount_ratio
})
except Exception as e:
print(f"{name}: 查询失败 ({e})")
continue
print("\n" + "=" * 80)
print(f"【结果】找到 {len(qualified_sectors)} 个符合资金异动条件的板块")
if len(qualified_sectors) == 0:
print("\n⚠️ 没有板块符合条件,可能原因:")
print(" 1. 市场整体资金流入不足(量比、额比都未达标)")
print(" 2. 板块涨幅不够需要≥0.5%")
print(" 3. 阈值设置过高当前量比≥1.5额比≥1.3")
print("\n建议放宽阈值:")
print(" - 量比阈值: 1.5 → 1.2")
print(" - 额比阈值: 1.3 → 1.1")
print(" - 最小涨幅: 0.5% → 0.3%")
else:
print("\n✅ 符合条件的板块:")
for idx, sector in enumerate(qualified_sectors, 1):
print(f" {idx}. {sector['name']}: {sector['change_pct']:+.2f}%, "
f"量比{sector['vol_ratio']:.2f}x, 额比{sector['amount_ratio']:.2f}x")
print("=" * 80)
async def main():
await diagnose_sector_detection()
if __name__ == "__main__":
asyncio.run(main())