#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Trend-Max: 三大策略综合分析 汇总 Trend-Mix, TQE, Regime 的结果 工作日15:30定时推送 发件人: trend-max """ import sys sys.path.insert(0, '/root/.openclaw/workspace/trend-mix') sys.path.insert(0, '/root/.openclaw/workspace/trend-quality-evaluator') sys.path.insert(0, '/root/.openclaw/workspace/market-regime-identifier') import numpy as np import pandas as pd from trend_mix_strategy import TrendMixStrategy from trend_quality_evaluator import fetch_stock_data as tqe_fetch, TrendQualityEvaluator from cyb50_market_classifier import fetch_cyb50_data, calculate_features, define_market_regime from sklearn.ensemble import RandomForestClassifier from datetime import datetime import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header import warnings warnings.filterwarnings('ignore') print("="*70) print(f"Trend-Max 三大策略综合分析 - {datetime.now().strftime('%Y-%m-%d %H:%M')}") print("="*70) # ============================================ # 1. Trend-Mix 分析 # ============================================ print("\n[1/3] 运行 Trend-Mix 分析...") strategy_mix = TrendMixStrategy() df_mix = strategy_mix.fetch_data("399673", "2024-01-01", "2026-12-31") if df_mix is not None: # 计算综合状态 composite_df = strategy_mix.calc_composite_state() latest_mix = composite_df.iloc[-1] mix_result = { 'state': latest_mix['Composite_State'], 'adx': latest_mix['ADX'], 'adx_state': latest_mix['ADX_State'], 'vr_state': latest_mix['VR_State'], 'hurst_state': latest_mix['Hurst_State'], 'bb_state': latest_mix['BB_State'], 'deviation': latest_mix['Deviation'] } print(f" ✓ Trend-Mix: {mix_result['state']}") else: mix_result = None print(" ✗ Trend-Mix 失败") # ============================================ # 2. TQE 分析 # ============================================ print("\n[2/3] 运行 TQE 分析...") df_tqe = tqe_fetch("399673", "2024-01-01", "2026-12-31", "d") if df_tqe is not None: evaluator = TrendQualityEvaluator() score = evaluator.evaluate(df_tqe) tqe_result = { 'total_score': score.total_score, 'is_tradeable': score.is_tradeable, 'adx_score': score.adx_score, 'ma_slope_score': score.ma_slope_score, 'volatility_score': score.volatility_score, 'timeframe_score': score.timeframe_score, 'volume_score': score.volume_score, 'adx_value': score.adx_value, 'ma_slope': score.ma_slope, 'volatility_ratio': score.volatility_ratio, 'volume_ratio': score.volume_ratio } print(f" ✓ TQE: {score.total_score:.1f}分 {'✅可交易' if score.is_tradeable else '❌观望'}") else: tqe_result = None print(" ✗ TQE 失败") # ============================================ # 3. Regime 分析 # ============================================ print("\n[3/3] 运行 Regime 分析...") df_regime = fetch_cyb50_data("2024-01-01", "2026-12-31") if df_regime is not None: features = calculate_features(df_regime) labels = define_market_regime(df_regime, lookback=10) # 训练模型 valid_idx = ~np.isnan(labels) X = features[valid_idx] y = labels[valid_idx] clf = RandomForestClassifier( n_estimators=100, max_depth=10, min_samples_split=20, min_samples_leaf=10, random_state=42, class_weight='balanced' ) clf.fit(X, y) # 预测 latest_features = features.iloc[-1:] pred = clf.predict(latest_features)[0] proba = clf.predict_proba(latest_features)[0] state_names = ['震荡', '趋势', '反转'] regime_result = { 'state': state_names[pred], 'confidence': proba[pred], 'prob_ranging': proba[0], 'prob_trend': proba[1], 'prob_reversal': proba[2] } print(f" ✓ Regime: {regime_result['state']} (置信度{regime_result['confidence']:.1%})") else: regime_result = None print(" ✗ Regime 失败") # ============================================ # 4. 综合分析 # ============================================ print("\n" + "="*70) print("综合分析") print("="*70) state_names_cn = ['震荡', '趋势', '反转'] final_recommendation = "观望" final_confidence = 0.0 if mix_result and tqe_result and regime_result: # 统计各策略的状态 states = [mix_result['state'], '趋势' if tqe_result['is_tradeable'] else '震荡', regime_result['state']] # 交易建议映射 trade_advice = { '强趋势': '重仓', '趋势': '持仓/加仓', '潜在爆发': '建仓', '反转': '止盈/减仓', '震荡': '观望' } mix_advice = trade_advice.get(mix_result['state'], '观望') tqe_advice = '交易' if tqe_result['is_tradeable'] else '观望' regime_advice = regime_result['state'] # 综合判断 trend_count = sum([s in ['强趋势', '趋势'] for s in states]) ranging_count = sum([s == '震荡' for s in states]) reversal_count = sum([s == '反转' for s in states]) if trend_count >= 2 and tqe_result['is_tradeable']: final_recommendation = "✅ 交易 (趋势确认)" final_confidence = 0.8 elif ranging_count >= 2 or not tqe_result['is_tradeable']: final_recommendation = "❌ 观望 (震荡整理)" final_confidence = 0.7 elif reversal_count >= 2: final_recommendation = "⚠️ 谨慎 (可能反转)" final_confidence = 0.6 else: final_recommendation = "❓ 分歧 (信号不一)" final_confidence = 0.4 print(f"\nTrend-Mix: {mix_result['state']} → {mix_advice}") print(f"TQE: {tqe_result['total_score']:.0f}分 → {tqe_advice}") print(f"Regime: {regime_result['state']} → {regime_advice}") print(f"\n综合建议: {final_recommendation}") # ============================================ # 5. 生成邮件 # ============================================ print("\n生成邮件...") today = datetime.now().strftime('%Y-%m-%d') html = f"""
日期: {today} | 标的: 创业板50 (399673)
置信度: {final_confidence*100:.0f}% | 三策略一致率: {max(trend_count, ranging_count, reversal_count)}/3
状态: {mix_result['state'] if mix_result else 'N/A'}
| 指标 | 数值 | 状态 |
|---|---|---|
| ADX(14) | {mix_result['adx']:.2f} | {mix_result['adx_state']} |
| 价格偏离MA20 | {mix_result['deviation']:.2f}% | - |
| 方差比检验 | - | {mix_result['vr_state']} |
| Hurst指数 | - | {mix_result['hurst_state']} |
| 布林带 | - | {mix_result['bb_state']} |
建议: {trade_advice.get(mix_result['state'], '观望') if mix_result else 'N/A'}
总分: {tqe_result['total_score']:.1f}分
是否可交易: {'✅ 是 (≥60分)' if tqe_result['is_tradeable'] else '❌ 否 (<60分)'}
| 因子 | 得分 | 原始值 |
|---|---|---|
| ADX趋势强度 (30分) | {tqe_result['adx_score']:.1f} | ADX={tqe_result['adx_value']:.1f} |
| 均线斜率 (25分) | {tqe_result['ma_slope_score']:.1f} | 斜率={tqe_result['ma_slope']:.4f} |
| 波动率收缩 (20分) | {tqe_result['volatility_score']:.1f} | ATR比={tqe_result['volatility_ratio']:.3f} |
| 时间框架共振 (15分) | {tqe_result['timeframe_score']:.1f} | - |
| 成交量确认 (10分) | {tqe_result['volume_score']:.1f} | 量比={tqe_result['volume_ratio']:.2f}x |
建议: {'交易' if tqe_result['is_tradeable'] else '观望'}
预测状态: {regime_result['state']} (置信度 {regime_result['confidence']:.1%})
| 状态 | 概率 | 可视化 |
|---|---|---|
| 震荡 | {regime_result['prob_ranging']:.1%} | {'█' * int(regime_result['prob_ranging'] * 20)} |
| 趋势 | {regime_result['prob_trend']:.1%} | {'█' * int(regime_result['prob_trend'] * 20)} |
| 反转 | {regime_result['prob_reversal']:.1%} | {'█' * int(regime_result['prob_reversal'] * 20)} |
建议: {regime_result['state']}期 {'持仓' if regime_result['state'] == '趋势' else '观望' if regime_result['state'] == '震荡' else '减仓'}
| 策略 | 判断 | 建议 |
|---|---|---|
| Trend-Mix | {mix_result['state']} | {trade_advice.get(mix_result['state'], '观望')} |
| TQE | {tqe_result['total_score']:.0f}分 {'✅' if tqe_result['is_tradeable'] else '❌'} | {'交易' if tqe_result['is_tradeable'] else '观望'} |
| Regime | {regime_result['state']} | {regime_result['state']}期操作 |
生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}
分析模块: Trend-Mix + TQE + Regime
发件人: trend-max | 推送时间: 工作日 15:30