diff --git a/board_monitor.py b/board_monitor.py index 4208c55..72c9f64 100644 --- a/board_monitor.py +++ b/board_monitor.py @@ -92,6 +92,127 @@ def get_board_data(board_type: str, sort_by: str = "f3", limit: int = 100) -> Op return None +def analyze_market(all_industry: List, all_concept: List) -> Dict: + """ + 专业市场分析 + + 返回各种分析指标 + """ + analysis = {} + + # 1. 市场整体统计 + if all_industry: + up_count = len([b for b in all_industry if b['pct_change'] > 0]) + down_count = len([b for b in all_industry if b['pct_change'] < 0]) + flat_count = len([b for b in all_industry if b['pct_change'] == 0]) + + avg_pct = sum(b['pct_change'] for b in all_industry) / len(all_industry) + max_pct = max(b['pct_change'] for b in all_industry) + min_pct = min(b['pct_change'] for b in all_industry) + + total_flow = sum(b['main_flow'] for b in all_industry) + + analysis['market_stats'] = { + 'up_count': up_count, + 'down_count': down_count, + 'flat_count': flat_count, + 'up_ratio': up_count / len(all_industry) * 100, + 'avg_pct': avg_pct, + 'max_pct': max_pct, + 'min_pct': min_pct, + 'total_flow': total_flow, + } + + # 2. 资金集中度分析 + if all_industry: + sorted_by_flow = sorted(all_industry, key=lambda x: x['main_flow'], reverse=True) + top5_flow = sum(b['main_flow'] for b in sorted_by_flow[:5]) + analysis['fund_concentration'] = { + 'top5_flow': top5_flow, + 'top5_ratio': abs(top5_flow) / abs(analysis['market_stats']['total_flow']) * 100 if analysis['market_stats']['total_flow'] != 0 else 0, + } + + # 3. 板块强弱分析 + if all_industry: + strong_boards = [b for b in all_industry if b['pct_change'] > 1 and b['main_flow'] > 5] + weak_boards = [b for b in all_industry if b['pct_change'] < -1 and b['main_flow'] < -5] + analysis['strength'] = { + 'strong_count': len(strong_boards), + 'weak_count': len(weak_boards), + 'strong_boards': strong_boards[:5], + 'weak_boards': weak_boards[:5], + } + + # 4. 概念板块热度分析 + if all_concept: + hot_concepts = sorted([b for b in all_concept if b['main_flow'] > 0], + key=lambda x: x['main_flow'], reverse=True)[:5] + cold_concepts = sorted([b for b in all_concept if b['main_flow'] < 0], + key=lambda x: x['main_flow'])[:5] + analysis['concept_heat'] = { + 'hot': hot_concepts, + 'cold': cold_concepts, + } + + # 5. 市场情绪判断 + if analysis.get('market_stats'): + stats = analysis['market_stats'] + + # 综合判断 + sentiment_score = 0 + + # 涨跌比例贡献 + if stats['up_ratio'] > 70: + sentiment_score += 2 + elif stats['up_ratio'] > 50: + sentiment_score += 1 + elif stats['up_ratio'] < 30: + sentiment_score -= 2 + elif stats['up_ratio'] < 50: + sentiment_score -= 1 + + # 平均涨跌幅贡献 + if stats['avg_pct'] > 0.5: + sentiment_score += 1 + elif stats['avg_pct'] < -0.5: + sentiment_score -= 1 + + # 资金流向贡献 + if stats['total_flow'] > 50: + sentiment_score += 2 + elif stats['total_flow'] > 0: + sentiment_score += 1 + elif stats['total_flow'] < -50: + sentiment_score -= 2 + elif stats['total_flow'] < 0: + sentiment_score -= 1 + + # 情绪等级 + if sentiment_score >= 4: + sentiment = '强势上涨' + sentiment_desc = '市场情绪高涨,多数板块上涨,资金大幅流入,建议关注强势板块机会。' + elif sentiment_score >= 2: + sentiment = '偏强' + sentiment_desc = '市场整体偏强,资金流向积极,可适度参与热门板块。' + elif sentiment_score >= 0: + sentiment = '平稳' + sentiment_desc = '市场情绪平稳,涨跌均衡,建议观望或轻仓布局。' + elif sentiment_score >= -2: + sentiment = '偏弱' + sentiment_desc = '市场整体偏弱,资金流出明显,建议谨慎操作,关注防御性板块。' + else: + sentiment = '弱势下跌' + sentiment_desc = '市场情绪低迷,多数板块下跌,资金大幅流出,建议规避风险,等待企稳信号。' + + analysis['sentiment'] = { + 'score': sentiment_score, + 'level': sentiment, + 'description': sentiment_desc, + } + + return analysis + + def generate_daily_report(boards_data: Dict, to_email: str = "wlq@tphai.com") -> bool: """ 生成盘后分析报告并发送邮件 @@ -113,90 +234,176 @@ def generate_daily_report(boards_data: Dict, to_email: str = "wlq@tphai.com") -> # 分析总结 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # 计算市场趋势 - avg_pct = 0 - if all_industry: - avg_pct = sum(b['pct_change'] for b in all_industry) / len(all_industry) - - market_trend = '平稳' - if avg_pct > 0.5: - market_trend = '上涨' - elif avg_pct < -0.5: - market_trend = '下跌' - # 排序数据 industry_by_pct = sorted(all_industry, key=lambda x: x['pct_change'], reverse=True) industry_by_flow = sorted(all_industry, key=lambda x: x['main_flow'], reverse=True) concept_by_pct = sorted(all_concept, key=lambda x: x['pct_change'], reverse=True) concept_by_flow = sorted(all_concept, key=lambda x: x['main_flow'], reverse=True) - # 生成HTML正文(分析总结) + # 执行专业分析 + analysis = analyze_market(all_industry, all_concept) + + # ========== 生成HTML正文 ========== html_lines = [ "

📊 A股板块盘后分析报告

", f"

报告时间: {timestamp}

", - f"

市场整体: {market_trend} (行业平均涨跌 {avg_pct:+.2f}%)

", "", "
", - "", - "

🔥 今日热门概念板块 TOP5

", - "", - "", ] - for board in concept_by_pct[:5]: - pct_str = f"+{board['pct_change']:.2f}%" if board['pct_change'] > 0 else f"{board['pct_change']:.2f}%" - flow_str = f"+{board['main_flow']:.2f}亿" if board['main_flow'] > 0 else f"{board['main_flow']:.2f}亿" - html_lines.append(f"") + # ===== 一、市场情绪分析 ===== + if analysis.get('sentiment'): + sent = analysis['sentiment'] + stats = analysis.get('market_stats', {}) + + html_lines.append("") + html_lines.append("

一、市场情绪分析

") + html_lines.append(f"

市场评级: {sent['level']}

") + html_lines.append(f"

{sent['description']}

") + + if stats: + html_lines.append("
板块涨跌幅主力资金
{board['name']}{pct_str}{flow_str}
") + html_lines.append("".format(stats['up_count'], stats['up_ratio'])) + html_lines.append("".format(stats['down_count'], 100 - stats['up_ratio'])) + html_lines.append("".format(stats['avg_pct'], stats['max_pct'])) + html_lines.append("".format(stats['total_flow'], stats['min_pct'])) + html_lines.append("
上涨板块{}占比 {:.1f}%
下跌板块{}占比 {:.1f}%
平均涨跌{:.2f}%最大涨幅 {:.2f}%
资金净流{:.2f}亿最大跌幅 {:.2f}%
") - html_lines.append("") + # ===== 二、资金流向分析 ===== + if analysis.get('fund_concentration'): + fund = analysis['fund_concentration'] + + html_lines.append("") + html_lines.append("

二、资金流向分析

") + html_lines.append(f"

TOP5板块资金合计: {fund['top5_flow']:.2f}亿

") + html_lines.append(f"

资金集中度: {fund['top5_ratio']:.1f}%(流入资金集中在少数板块)

") + + # ===== 三、板块强弱分析 ===== + if analysis.get('strength'): + strength = analysis['strength'] + + html_lines.append("") + html_lines.append("

三、板块强弱分析

") + html_lines.append(f"

强势板块(涨幅>1%且资金流入>5亿): {strength['strong_count']} 个

") + html_lines.append(f"

弱势板块(跌幅>1%且资金流出>5亿): {strength['weak_count']} 个

") + + if strength['strong_boards']: + html_lines.append("

强势板块示例:

") + html_lines.append("") + + if strength['weak_boards']: + html_lines.append("

弱势板块示例:

") + html_lines.append("") + + # ===== 四、热门概念分析 ===== + if analysis.get('concept_heat'): + heat = analysis['concept_heat'] + + html_lines.append("") + html_lines.append("

四、概念板块热度

") + + if heat['hot']: + html_lines.append("

🔥 热门概念(资金流入TOP):

") + html_lines.append("") + html_lines.append("") + for b in heat['hot'][:5]: + pct_str = f"+{b['pct_change']:.2f}%" if b['pct_change'] > 0 else f"{b['pct_change']:.2f}%" + html_lines.append(f"") + html_lines.append("
概念资金(亿)涨跌
{b['name']}+{b['main_flow']:.2f}{pct_str}
") + + if heat['cold']: + html_lines.append("

❄️ 冷门概念(资金流出TOP):

") + html_lines.append("") + html_lines.append("") + for b in heat['cold'][:5]: + pct_str = f"+{b['pct_change']:.2f}%" if b['pct_change'] > 0 else f"{b['pct_change']:.2f}%" + html_lines.append(f"") + html_lines.append("
概念资金(亿)涨跌
{b['name']}{b['main_flow']:.2f}{pct_str}
") + + # ===== 五、行业板块排行 ===== html_lines.append("") + html_lines.append("
") + html_lines.append("") + html_lines.append("

五、行业板块涨跌排行

") - html_lines.append("

📈 行业板块涨幅 TOP5

") + html_lines.append("

📈 涨幅 TOP5:

") html_lines.append("") html_lines.append("") - for board in industry_by_pct[:5]: pct_str = f"+{board['pct_change']:.2f}%" if board['pct_change'] > 0 else f"{board['pct_change']:.2f}%" flow_str = f"+{board['main_flow']:.2f}亿" if board['main_flow'] > 0 else f"{board['main_flow']:.2f}亿" html_lines.append(f"") - html_lines.append("
板块涨跌幅主力资金领涨股
{board['name']}{pct_str}{flow_str}{board['leader_name'] or '-'}
") - html_lines.append("") - html_lines.append("

📉 行业板块跌幅 TOP5

") + html_lines.append("

📉 跌幅 TOP5:

") html_lines.append("") html_lines.append("") - for board in industry_by_pct[-5:]: pct_str = f"+{board['pct_change']:.2f}%" if board['pct_change'] > 0 else f"{board['pct_change']:.2f}%" flow_str = f"+{board['main_flow']:.2f}亿" if board['main_flow'] > 0 else f"{board['main_flow']:.2f}亿" html_lines.append(f"") - html_lines.append("
板块涨跌幅主力资金
{board['name']}{pct_str}{flow_str}
") + + # ===== 六、主力资金排行 ===== html_lines.append("") + html_lines.append("

六、主力资金流向排行

") - html_lines.append("

💰 主力资金大幅流入 TOP10

") + html_lines.append("

💰 大幅流入 TOP10 (≥10亿):

") html_lines.append("") - html_lines.append("") - + html_lines.append("") inflow_boards = [b for b in industry_by_flow if b['main_flow'] > 10][:10] for board in inflow_boards: pct_str = f"+{board['pct_change']:.2f}%" if board['pct_change'] > 0 else f"{board['pct_change']:.2f}%" html_lines.append(f"") - html_lines.append("
板块资金流入(亿)涨跌幅
板块资金(亿)涨跌
{board['name']}+{board['main_flow']:.2f}{pct_str}
") - html_lines.append("") - html_lines.append("

💸 主力资金大幅流出 TOP10

") + html_lines.append("

💸 大幅流出 TOP10 (≤-10亿):

") html_lines.append("") - html_lines.append("") - + html_lines.append("") outflow_boards = [b for b in industry_by_flow if b['main_flow'] < -10][:10] for board in outflow_boards: pct_str = f"+{board['pct_change']:.2f}%" if board['pct_change'] > 0 else f"{board['pct_change']:.2f}%" html_lines.append(f"") - html_lines.append("
板块资金流出(亿)涨跌幅
板块资金(亿)涨跌
{board['name']}{board['main_flow']:.2f}{pct_str}
") + + # ===== 七、投资建议 ===== + html_lines.append("") + html_lines.append("
") + html_lines.append("

七、投资建议

") + + if analysis.get('sentiment'): + sent = analysis['sentiment'] + + if sent['score'] >= 2: + html_lines.append("

策略建议: 积极参与

") + html_lines.append("") + elif sent['score'] >= 0: + html_lines.append("

策略建议: 观望为主

") + html_lines.append("") + else: + html_lines.append("

策略建议: 谨慎防守

") + html_lines.append("") + html_lines.append("") html_lines.append("
") html_lines.append("

📊 详细数据请查看附件 CSV 文件

") diff --git a/data/board_detail_20260410.csv b/data/board_detail_20260410.csv index be5e496..b4adeb4 100644 --- a/data/board_detail_20260410.csv +++ b/data/board_detail_20260410.csv @@ -1,5 +1,5 @@ # A股板块详细数据 -# 生成时间: 2026-04-10 17:19:21 +# 生成时间: 2026-04-10 17:42:51 === 行业板块涨跌幅排行 === 板块名称,涨跌幅(%),主力资金(亿),领涨股