226 lines
7.2 KiB
Python
226 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
A股短期题材选股 - 调试版本
|
||
用于诊断为什么没有选出股票
|
||
"""
|
||
import asyncio
|
||
import sys
|
||
import os
|
||
from datetime import datetime, timedelta
|
||
|
||
# 添加项目根目录到Python路径
|
||
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 debug_tushare_connection():
|
||
"""测试Tushare连接"""
|
||
print("\n" + "=" * 60)
|
||
print("📊 测试1: Tushare连接测试")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
settings = get_settings()
|
||
print(f"Token配置: {'已配置' if settings.tushare_token else '未配置'}")
|
||
|
||
if not settings.tushare_token:
|
||
print("❌ Tushare Token未配置,请在.env文件中设置TUSHARE_TOKEN")
|
||
return False
|
||
|
||
ts_client = get_tushare_client(settings.tushare_token)
|
||
print(f"✅ Tushare客户端初始化成功")
|
||
|
||
# 测试基本API调用
|
||
print("\n测试API调用...")
|
||
|
||
# 测试获取概念板块
|
||
sectors_df = ts_client.get_concept_sectors()
|
||
print(f"概念板块数量: {len(sectors_df)}")
|
||
if not sectors_df.empty:
|
||
print(f"示例板块: {sectors_df.head(3)['name'].tolist()}")
|
||
else:
|
||
print("❌ 无法获取概念板块列表")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ Tushare连接失败: {e}")
|
||
import traceback
|
||
print(traceback.format_exc())
|
||
return False
|
||
|
||
|
||
async def debug_hot_sectors():
|
||
"""测试异动板块获取"""
|
||
print("\n" + "=" * 60)
|
||
print("📊 测试2: 异动板块检测")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
settings = get_settings()
|
||
ts_client = get_tushare_client(settings.tushare_token)
|
||
|
||
sectors_df = ts_client.get_concept_sectors()
|
||
print(f"总概念板块数: {len(sectors_df)}")
|
||
|
||
# 检查异动板块
|
||
today = datetime.now().strftime('%Y%m%d')
|
||
print(f"当前日期: {today}")
|
||
|
||
# 检查是否是交易日
|
||
weekday = datetime.now().weekday()
|
||
if weekday >= 5:
|
||
print(f"⚠️ 当前是周末(周{weekday}),可能没有最新数据")
|
||
else:
|
||
print(f"✅ 当前是工作日(周{weekday})")
|
||
|
||
# 手动检查几个热门板块
|
||
print("\n检查前10个板块的行情...")
|
||
check_count = min(10, len(sectors_df))
|
||
|
||
hot_count = 0
|
||
for idx, row in sectors_df.head(check_count).iterrows():
|
||
ts_code = row['ts_code']
|
||
name = row['name']
|
||
|
||
try:
|
||
yesterday = (datetime.now() - timedelta(days=10)).strftime('%Y%m%d')
|
||
daily_df = ts_client.pro.ths_daily(
|
||
ts_code=ts_code,
|
||
start_date=yesterday,
|
||
end_date=today
|
||
)
|
||
|
||
if not daily_df.empty:
|
||
latest = daily_df.sort_values('trade_date').iloc[-1]
|
||
change_pct = float(latest.get('pct_change', 0))
|
||
trade_date = str(latest.get('trade_date', ''))
|
||
|
||
status = "🔥" if change_pct >= 2.0 else "📊"
|
||
print(f" {status} {name}: {change_pct:+.2f}% (日期: {trade_date})")
|
||
|
||
if change_pct >= 2.0:
|
||
hot_count += 1
|
||
else:
|
||
print(f" ⚠️ {name}: 无数据")
|
||
|
||
except Exception as e:
|
||
print(f" ❌ {name}: 查询失败 ({e})")
|
||
|
||
print(f"\n找到 {hot_count} 个涨幅≥2%的板块")
|
||
|
||
if hot_count == 0:
|
||
print("\n⚠️ 没有找到符合条件的异动板块,可能原因:")
|
||
print(" 1. 当前不是交易日(周末或节假日)")
|
||
print(" 2. 盘中时段数据未更新")
|
||
print(" 3. 市场整体表现平淡")
|
||
|
||
return hot_count > 0
|
||
|
||
except Exception as e:
|
||
print(f"❌ 异动板块检测失败: {e}")
|
||
import traceback
|
||
print(traceback.format_exc())
|
||
return False
|
||
|
||
|
||
async def debug_stock_screening():
|
||
"""测试个股筛选"""
|
||
print("\n" + "=" * 60)
|
||
print("📊 测试3: 个股筛选条件分析")
|
||
print("=" * 60)
|
||
|
||
print("\n筛选条件回顾:")
|
||
print(" 1. 市值: 50-500亿")
|
||
print(" 2. 换手率: 3%-15%")
|
||
print(" 3. 涨跌幅: -5% 到 +8%")
|
||
print(" 4. MA多头排列: MA5 > MA10 > MA20")
|
||
print(" 5. 量能配合: 量比 > 1.2")
|
||
print(" 6. 20日动量 > 0")
|
||
print(" 7. 距离高点回撤 < 15%")
|
||
|
||
print("\n⚠️ 如果没有选出股票,可能是因为:")
|
||
print(" 1. 市场整体不符合技术形态(没有MA多头排列的股票)")
|
||
print(" 2. 筛选条件较严格(可以尝试放宽参数)")
|
||
print(" 3. 数据时间窗口问题(需要30天以上历史数据)")
|
||
|
||
# 建议放宽的条件
|
||
print("\n建议放宽的参数(在当前市场环境下):")
|
||
print(" - 换手率: 1%-15% (降低下限)")
|
||
print(" - 涨跌幅: -7% 到 +10% (扩大范围)")
|
||
print(" - 市值: 30-500亿 (降低下限)")
|
||
|
||
|
||
async def debug_selector_run():
|
||
"""尝试运行选股器并显示详细信息"""
|
||
print("\n" + "=" * 60)
|
||
print("📊 测试4: 运行选股器(详细日志)")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
from app.astock_agent.short_term_thematic_selector import get_thematic_selector
|
||
|
||
settings = get_settings()
|
||
ts_client = get_tushare_client(settings.tushare_token)
|
||
selector = get_thematic_selector(ts_client)
|
||
|
||
# 运行选股,启用详细日志
|
||
import logging
|
||
logging.basicConfig(level=logging.DEBUG)
|
||
|
||
result = selector.select_stocks(max_stocks=10)
|
||
|
||
print(f"\n选股结果: {result['total_stocks']} 只")
|
||
|
||
if result['total_stocks'] == 0:
|
||
print("\n❌ 未选出股票")
|
||
print("\n请查看上方详细日志,分析哪个环节过滤掉了股票")
|
||
else:
|
||
print("\n✅ 选股成功!")
|
||
print(selector.format_output_text(result))
|
||
|
||
except Exception as e:
|
||
print(f"❌ 选股器运行失败: {e}")
|
||
import traceback
|
||
print(traceback.format_exc())
|
||
|
||
|
||
async def main():
|
||
"""主函数"""
|
||
print("\n" + "=" * 60)
|
||
print("🔍 A股选股器诊断工具")
|
||
print("=" * 60)
|
||
|
||
# 运行所有测试
|
||
step1_ok = await debug_tushare_connection()
|
||
if not step1_ok:
|
||
print("\n❌ Tushare连接失败,请检查配置")
|
||
return 1
|
||
|
||
step2_ok = await debug_hot_sectors()
|
||
if not step2_ok:
|
||
print("\n⚠️ 没有找到异动板块,这是正常的(取决于市场情况)")
|
||
|
||
await debug_stock_screening()
|
||
|
||
print("\n" + "=" * 60)
|
||
print("📋 诊断完成")
|
||
print("=" * 60)
|
||
print("\n如果所有测试通过但未选出股票,说明当前市场条件不符合策略要求。")
|
||
print("这是正常的,策略不会在市场条件不符合时强行选股。")
|
||
print("\n建议:")
|
||
print(" 1. 在交易日15:00后运行(确保有完整数据)")
|
||
print(" 2. 或者放宽筛选条件以适应当前市场环境")
|
||
print("")
|
||
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
exit_code = asyncio.run(main())
|
||
sys.exit(exit_code)
|