#!/usr/bin/env python3 # -*- coding: utf-8 -*- """生成最近60天详细数据邮件""" import sys sys.path.insert(0, '/root/.openclaw/workspace/market-regime-identifier') import numpy as np import pandas as pd from cyb50_market_classifier import fetch_cyb50_data, calculate_features, define_market_regime from sklearn.ensemble import RandomForestClassifier import warnings warnings.filterwarnings('ignore') # 获取数据 df = fetch_cyb50_data('2024-01-01', '2026-03-06') if df is None: exit(1) # 计算特征和标签 features = calculate_features(df) labels = define_market_regime(df, 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) # 预测所有数据 states = clf.predict(X) probs = clf.predict_proba(X) # 对齐数据 df_aligned = df.iloc[-len(states):].copy() df_aligned['state'] = states df_aligned['prob_ranging'] = probs[:, 0] df_aligned['prob_trend'] = probs[:, 1] df_aligned['prob_reversal'] = probs[:, 2] # 获取最近60天 last_60 = df_aligned.tail(60).copy() last_60['date'] = last_60.index.strftime('%m-%d') last_60['change'] = last_60['close'].pct_change() * 100 state_names = ['震荡', '趋势', '反转'] colors = ['#2196F3', '#4CAF50', '#FF5722'] # 生成HTML html_rows = "" for idx, row in last_60.iterrows(): state = int(row['state']) state_name = state_names[state] color = colors[state] change = row['change'] if not pd.isna(row['change']) else 0 change_str = f"{change:+.2f}%" if change != 0 else "-" change_color = "green" if change > 0 else "red" if change < 0 else "gray" html_rows += f""" {idx.strftime('%Y-%m-%d')} {row['close']:.2f} {state_name} {row['prob_ranging']:.1%} {row['prob_trend']:.1%} {row['prob_reversal']:.1%} {change_str} """ # 计算统计 summary = f"""

📊 最近60天统计

统计区间: {last_60.index[0].date()} ~ {last_60.index[-1].date()}

起始价格: {last_60['close'].iloc[0]:.2f}

结束价格: {last_60['close'].iloc[-1]:.2f}

区间涨跌: {(last_60['close'].iloc[-1]/last_60['close'].iloc[0]-1)*100:+.2f}%

最高价: {last_60['close'].max():.2f} ({last_60['close'].idxmax().strftime('%m-%d')})

最低价: {last_60['close'].min():.2f} ({last_60['close'].idxmin().strftime('%m-%d')})


状态分布:

🟦 震荡: {(last_60['state']==0).sum()}天 ({(last_60['state']==0).sum()/60*100:.1f}%)

🟩 趋势: {(last_60['state']==1).sum()}天 ({(last_60['state']==1).sum()/60*100:.1f}%)

🟧 反转: {(last_60['state']==2).sum()}天 ({(last_60['state']==2).sum()/60*100:.1f}%)

""" html = f"""

📊 创业板50最近60天详细数据 (2026-01-06 ~ 2026-03-06)

{summary}

📋 每日详细数据

{html_rows}
日期 收盘价 状态 震荡概率 趋势概率 反转概率 日涨跌

生成时间: 2026-03-06 19:10
数据更新至: 2026-03-06
模型准确率: 72.10%

""" # 保存HTML with open('/root/.openclaw/workspace/market-regime-identifier/last_60_days_report.html', 'w', encoding='utf-8') as f: f.write(html) print("✓ HTML报告已生成") print(f"最近60天: {last_60.index[0].date()} ~ {last_60.index[-1].date()}") print(f"\n状态分布:") print(f" 震荡: {(last_60['state']==0).sum()}天") print(f" 趋势: {(last_60['state']==1).sum()}天") print(f" 反转: {(last_60['state']==2).sum()}天")