#!/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_this_week_dates(): """获取本周的开始和结束日期""" today = datetime.now() # 获取本周一 monday = today - timedelta(days=today.weekday()) # 获取本周五(或今天如果还没到周五) friday = monday + timedelta(days=4) if friday > today: friday = today return monday.strftime('%Y%m%d'), friday.strftime('%Y%m%d') def analyze_sector_performance(fetcher: TushareFetcher): """分析行业板块表现""" try: logger.info("开始分析本周强势板块...") # 获取本周日期范围 start_date, end_date = get_this_week_dates() logger.info(f"分析时间范围: {start_date} 到 {end_date}") if not fetcher.pro: logger.error("需要Tushare Pro权限才能获取行业数据") return # 直接使用概念和行业数据分析 logger.info("通过个股数据分析板块表现...") # 获取股票基本信息(包含行业分类) try: stock_basic = fetcher.pro.stock_basic( exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,market' ) logger.info(f"获取到 {len(stock_basic)} 只股票基本信息") except Exception as e: logger.error(f"获取股票基本信息失败: {e}") return # 按行业分组分析 industry_performance = {} # 取样分析(避免API请求过多) sample_stocks = stock_basic.sample(min(200, len(stock_basic))) # 随机取200只股票 logger.info(f"随机抽样 {len(sample_stocks)} 只股票进行分析...") for _, stock in sample_stocks.iterrows(): ts_code = stock['ts_code'] industry = stock['industry'] stock_name = stock['name'] if pd.isna(industry) or industry == '': continue try: # 获取个股本周数据 stock_data = fetcher.pro.daily( ts_code=ts_code, start_date=start_date, end_date=end_date ) if not stock_data.empty and len(stock_data) >= 1: # 获取最新价格和前一个交易日价格 if len(stock_data) >= 2: latest_close = stock_data.iloc[0]['close'] prev_close = stock_data.iloc[1]['close'] else: # 如果只有一天数据,获取开盘价作为对比 latest_close = stock_data.iloc[0]['close'] prev_close = stock_data.iloc[0]['open'] if prev_close > 0: change_pct = (latest_close - prev_close) / prev_close * 100 # 按行业归类 if industry not in industry_performance: industry_performance[industry] = { 'stock_changes': [], 'stock_count': 0, 'stock_names': [] } industry_performance[industry]['stock_changes'].append(change_pct) industry_performance[industry]['stock_count'] += 1 industry_performance[industry]['stock_names'].append(f"{stock_name}({change_pct:+.2f}%)") logger.debug(f"{stock_name} ({industry}): {change_pct:+.2f}%") except Exception as e: logger.debug(f"分析个股 {ts_code} 失败: {e}") continue # 计算各行业平均表现 industry_results = [] for industry, data in industry_performance.items(): if data['stock_count'] >= 3: # 至少要有3只股票才参与排名 avg_change = sum(data['stock_changes']) / len(data['stock_changes']) industry_results.append({ 'industry_name': industry, 'avg_change_pct': avg_change, 'stock_count': data['stock_count'], 'best_stocks': sorted(data['stock_names'], key=lambda x: float(x.split('(')[1].split('%')[0]), reverse=True)[:3] }) # 3. 分析结果 if industry_results: df_performance = pd.DataFrame(industry_results) # 按平均涨跌幅排序 df_performance = df_performance.sort_values('avg_change_pct', ascending=False) logger.info("\n" + "="*80) logger.info("📈 本周强势板块排行榜(基于抽样股票分析)") logger.info("="*80) print(f"{'排名':<4} {'行业名称':<20} {'平均涨跌幅':<12} {'样本数量':<8} {'代表个股':<30}") print("-" * 80) for i, (_, row) in enumerate(df_performance.head(15).iterrows()): rank = i + 1 industry_name = row['industry_name'][:18] + '..' if len(row['industry_name']) > 18 else row['industry_name'] change_pct = f"{row['avg_change_pct']:+.2f}%" stock_count = f"{row['stock_count']}只" best_stock = row['best_stocks'][0] if row['best_stocks'] else "无数据" print(f"{rank:<4} {industry_name:<20} {change_pct:<12} {stock_count:<8} {best_stock:<30}") # 输出强势板块(涨幅前5) top_sectors = df_performance.head(5) logger.info(f"\n🚀 本周TOP5强势板块:") for i, (_, sector) in enumerate(top_sectors.iterrows()): logger.info(f" {i+1}. {sector['industry_name']}: {sector['avg_change_pct']:+.2f}% (样本{sector['stock_count']}只)") for j, stock in enumerate(sector['best_stocks'][:3]): logger.info(f" └─ {stock}") # 输出弱势板块(跌幅前5) weak_sectors = df_performance.tail(5) logger.info(f"\n📉 本周TOP5弱势板块:") for i, (_, sector) in enumerate(weak_sectors.iterrows()): logger.info(f" {i+1}. {sector['industry_name']}: {sector['avg_change_pct']:+.2f}% (样本{sector['stock_count']}只)") else: logger.warning("未获取到有效的行业表现数据") except Exception as e: logger.error(f"分析行业表现失败: {e}") def get_sector_top_stocks(fetcher: TushareFetcher, industry_code: str, industry_name: str, limit: int = 5): """获取指定板块的强势个股""" try: logger.info(f"获取 {industry_name} 板块的强势个股...") if not fetcher.pro: return # 获取该行业的成分股 try: constituents = fetcher.pro.index_member(index_code=industry_code) if constituents.empty: logger.warning(f"{industry_name} 行业无成分股数据") return stock_codes = constituents['con_code'].tolist()[:20] # 取前20只股票测试 logger.info(f"{industry_name} 行业共 {len(constituents)} 只成分股,分析前 {len(stock_codes)} 只") except Exception as e: logger.error(f"获取 {industry_name} 成分股失败: {e}") return # 获取本周日期 start_date, end_date = get_this_week_dates() # 分析各股票本周表现 stock_performance = [] for stock_code in stock_codes[:10]: # 限制分析数量 try: # 获取个股本周数据 stock_data = fetcher.pro.daily( ts_code=stock_code, start_date=start_date, end_date=end_date ) if not stock_data.empty and len(stock_data) >= 2: latest_close = stock_data.iloc[0]['close'] week_start_close = stock_data.iloc[-1]['close'] week_change = (latest_close - week_start_close) / week_start_close * 100 # 获取股票名称 stock_name = fetcher.get_stock_name(stock_code.split('.')[0]) stock_performance.append({ 'stock_code': stock_code, 'stock_name': stock_name, 'week_change_pct': week_change, 'latest_close': latest_close }) except Exception as e: logger.debug(f"分析个股 {stock_code} 失败: {e}") continue # 输出该板块强势个股 if stock_performance: df_stocks = pd.DataFrame(stock_performance) df_stocks = df_stocks.sort_values('week_change_pct', ascending=False) logger.info(f"\n📊 {industry_name} 板块强势个股 TOP{limit}:") for _, stock in df_stocks.head(limit).iterrows(): logger.info(f" {stock['stock_name']} ({stock['stock_code']}): {stock['week_change_pct']:+.2f}%") except Exception as e: logger.error(f"获取 {industry_name} 板块个股失败: {e}") def main(): """主函数""" logger.info("开始测试Tushare获取本周强势板块...") # 初始化Tushare数据获取器 token = "0ed6419a00d8923dc19c0b58fc92d94c9a0696949ab91a13aa58a0cc" fetcher = TushareFetcher(token=token) # 分析板块表现 analyze_sector_performance(fetcher) # 分析某个强势板块的个股(示例) # get_sector_top_stocks(fetcher, "801010.SI", "农林牧渔") logger.info("测试完成!") if __name__ == "__main__": main()