238 lines
8.2 KiB
Python
238 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
使用Tushare直接获取板块数据的测试
|
||
"""
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
import pandas as pd
|
||
from datetime import datetime, timedelta
|
||
|
||
# 添加项目根目录到路径
|
||
current_dir = Path(__file__).parent
|
||
sys.path.insert(0, str(current_dir))
|
||
|
||
from src.data.tushare_fetcher import TushareFetcher
|
||
from loguru import logger
|
||
|
||
|
||
def get_concept_sectors(fetcher: TushareFetcher):
|
||
"""获取概念板块数据"""
|
||
try:
|
||
if not fetcher.pro:
|
||
logger.error("需要Tushare Pro权限")
|
||
return
|
||
|
||
logger.info("尝试获取概念板块数据...")
|
||
|
||
# 1. 尝试获取概念板块列表
|
||
try:
|
||
concept_list = fetcher.pro.concept()
|
||
logger.info(f"获取到 {len(concept_list)} 个概念板块")
|
||
|
||
if not concept_list.empty:
|
||
print("概念板块列表(前10个):")
|
||
for _, concept in concept_list.head(10).iterrows():
|
||
print(f" {concept['code']}: {concept['name']}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取概念板块列表失败: {e}")
|
||
|
||
# 2. 尝试获取同花顺概念指数
|
||
try:
|
||
ths_concept = fetcher.pro.ths_index(exchange='A', type='N')
|
||
logger.info(f"获取同花顺概念指数: {len(ths_concept)} 个")
|
||
|
||
if not ths_concept.empty:
|
||
print("\n同花顺概念指数(前10个):")
|
||
for _, index in ths_concept.head(10).iterrows():
|
||
print(f" {index['ts_code']}: {index['name']}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取同花顺概念指数失败: {e}")
|
||
|
||
# 3. 尝试获取行业指数
|
||
try:
|
||
industry_index = fetcher.pro.index_basic(market='SW')
|
||
logger.info(f"获取申万行业指数: {len(industry_index)} 个")
|
||
|
||
if not industry_index.empty:
|
||
print("\n申万行业指数(前10个):")
|
||
for _, index in industry_index.head(10).iterrows():
|
||
print(f" {index['ts_code']}: {index['name']}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取申万行业指数失败: {e}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取板块数据失败: {e}")
|
||
|
||
|
||
def analyze_hot_concepts(fetcher: TushareFetcher):
|
||
"""分析热门概念板块"""
|
||
try:
|
||
if not fetcher.pro:
|
||
logger.error("需要Tushare Pro权限")
|
||
return
|
||
|
||
logger.info("分析热门概念板块...")
|
||
|
||
# 获取今日涨跌停统计
|
||
today = datetime.now().strftime('%Y%m%d')
|
||
|
||
try:
|
||
# 获取涨停股票
|
||
limit_up = fetcher.pro.limit_list(trade_date=today, limit_type='U')
|
||
logger.info(f"今日涨停股票: {len(limit_up)} 只")
|
||
|
||
if not limit_up.empty:
|
||
print(f"\n今日涨停股票(前10只):")
|
||
for _, stock in limit_up.head(10).iterrows():
|
||
print(f" {stock['ts_code']}: {stock['name']} (+{stock['pct_chg']:.2f}%)")
|
||
|
||
# 分析涨停股票的行业分布
|
||
if 'industry' in limit_up.columns:
|
||
industry_counts = limit_up['industry'].value_counts()
|
||
print(f"\n涨停股票行业分布:")
|
||
for industry, count in industry_counts.head(5).items():
|
||
print(f" {industry}: {count}只")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取涨停数据失败: {e}")
|
||
|
||
# 获取龙虎榜数据
|
||
try:
|
||
top_list = fetcher.pro.top_list(trade_date=today)
|
||
logger.info(f"今日龙虎榜: {len(top_list)} 只股票")
|
||
|
||
if not top_list.empty:
|
||
print(f"\n今日龙虎榜股票(前5只):")
|
||
for _, stock in top_list.head(5).iterrows():
|
||
print(f" {stock['ts_code']}: {stock['name']} 净买入: {stock['amount']:.0f}万元")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取龙虎榜数据失败: {e}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"分析热门概念失败: {e}")
|
||
|
||
|
||
def get_sector_performance_direct(fetcher: TushareFetcher):
|
||
"""直接通过指数数据获取板块表现"""
|
||
try:
|
||
if not fetcher.pro:
|
||
logger.error("需要Tushare Pro权限")
|
||
return
|
||
|
||
logger.info("通过指数数据分析板块表现...")
|
||
|
||
# 获取申万一级行业指数
|
||
try:
|
||
sw_index = fetcher.pro.index_basic(market='SW', level='L1')
|
||
logger.info(f"获取申万一级行业指数: {len(sw_index)} 个")
|
||
|
||
if sw_index.empty:
|
||
logger.warning("未获取到申万行业指数")
|
||
return
|
||
|
||
# 获取最近两个交易日的指数行情
|
||
end_date = datetime.now().strftime('%Y%m%d')
|
||
start_date = (datetime.now() - timedelta(days=7)).strftime('%Y%m%d')
|
||
|
||
sector_performance = []
|
||
|
||
for _, index in sw_index.head(15).iterrows(): # 分析前15个行业
|
||
ts_code = index['ts_code']
|
||
name = index['name']
|
||
|
||
try:
|
||
# 获取指数行情
|
||
index_data = fetcher.pro.index_daily(
|
||
ts_code=ts_code,
|
||
start_date=start_date,
|
||
end_date=end_date
|
||
)
|
||
|
||
if not index_data.empty and len(index_data) >= 2:
|
||
# 计算涨跌幅
|
||
latest = index_data.iloc[0]
|
||
previous = index_data.iloc[1]
|
||
|
||
change_pct = (latest['close'] - previous['close']) / previous['close'] * 100
|
||
|
||
sector_performance.append({
|
||
'name': name,
|
||
'code': ts_code,
|
||
'change_pct': change_pct,
|
||
'latest_close': latest['close'],
|
||
'volume': latest['vol']
|
||
})
|
||
|
||
logger.debug(f"{name}: {change_pct:+.2f}%")
|
||
|
||
except Exception as e:
|
||
logger.debug(f"获取 {name} 指数数据失败: {e}")
|
||
continue
|
||
|
||
# 输出结果
|
||
if sector_performance:
|
||
df = pd.DataFrame(sector_performance)
|
||
df = df.sort_values('change_pct', ascending=False)
|
||
|
||
print("\n" + "="*60)
|
||
print("📈 申万行业指数表现排行")
|
||
print("="*60)
|
||
print(f"{'排名':<4} {'行业名称':<20} {'涨跌幅':<10} {'最新点位':<10}")
|
||
print("-" * 60)
|
||
|
||
for i, (_, row) in enumerate(df.iterrows()):
|
||
rank = i + 1
|
||
name = row['name'][:18] + '..' if len(row['name']) > 18 else row['name']
|
||
change = f"{row['change_pct']:+.2f}%"
|
||
close = f"{row['latest_close']:.2f}"
|
||
|
||
print(f"{rank:<4} {name:<20} {change:<10} {close:<10}")
|
||
|
||
# 强势行业
|
||
print(f"\n🚀 强势行业TOP5:")
|
||
for _, row in df.head(5).iterrows():
|
||
print(f" {row['name']}: {row['change_pct']:+.2f}%")
|
||
|
||
# 弱势行业
|
||
print(f"\n📉 弱势行业TOP5:")
|
||
for _, row in df.tail(5).iterrows():
|
||
print(f" {row['name']}: {row['change_pct']:+.2f}%")
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取申万指数失败: {e}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"分析板块表现失败: {e}")
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
logger.info("测试Tushare板块数据接口...")
|
||
|
||
# 初始化Tushare数据获取器
|
||
token = "0ed6419a00d8923dc19c0b58fc92d94c9a0696949ab91a13aa58a0cc"
|
||
fetcher = TushareFetcher(token=token)
|
||
|
||
# 1. 获取板块分类数据
|
||
get_concept_sectors(fetcher)
|
||
|
||
print("\n" + "="*80 + "\n")
|
||
|
||
# 2. 分析热门概念
|
||
analyze_hot_concepts(fetcher)
|
||
|
||
print("\n" + "="*80 + "\n")
|
||
|
||
# 3. 通过指数直接获取板块表现
|
||
get_sector_performance_direct(fetcher)
|
||
|
||
logger.info("测试完成!")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |