#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 增强版Kronos预测器 集成量价分析和波浪理论 """ import numpy as np import pandas as pd import torch import torch.nn as nn from typing import Dict, List, Tuple, Optional import warnings warnings.filterwarnings('ignore') # 导入原始Kronos模块 from model.kronos import KronosPredictor, KronosTokenizer, Kronos from model.technical_indicators import TechnicalIndicators, VolumePriceAnalyzer, WaveTheoryAnalyzer, enhance_kronos_features class EnhancedKronosPredictor(KronosPredictor): """增强版Kronos预测器,集成技术指标和波浪理论""" def __init__(self, model, tokenizer, device="cuda:0", max_context=512, clip=5, use_technical_indicators=True, use_wave_theory=True): """ 初始化增强版预测器 Args: model: Kronos模型 tokenizer: Kronos分词器 device: 计算设备 max_context: 最大上下文长度 clip: 数据裁剪值 use_technical_indicators: 是否使用技术指标 use_wave_theory: 是否使用波浪理论 """ super().__init__(model, tokenizer, device, max_context, clip) self.use_technical_indicators = use_technical_indicators self.use_wave_theory = use_wave_theory # 初始化分析器 if self.use_technical_indicators: self.technical_indicators = TechnicalIndicators() self.volume_price_analyzer = VolumePriceAnalyzer() if self.use_wave_theory: self.wave_analyzer = WaveTheoryAnalyzer() # 定义增强特征列表 self.enhanced_features = self._define_enhanced_features() # 更新价格列,包含更多特征 self.price_cols = ['open', 'high', 'low', 'close'] self.vol_col = 'volume' self.amt_vol = 'amount' self.time_cols = ['minute', 'hour', 'weekday', 'day', 'month'] def _define_enhanced_features(self) -> List[str]: """定义增强特征列表""" enhanced_features = [] if self.use_technical_indicators: # 技术指标特征 enhanced_features.extend([ 'sma_5', 'sma_10', 'sma_20', 'sma_50', 'ema_5', 'ema_10', 'ema_20', 'bb_upper', 'bb_middle', 'bb_lower', 'bb_width', 'bb_position', 'k', 'd', 'j', 'rsi_6', 'rsi_14', 'macd', 'macd_signal', 'macd_hist', 'williams_r', 'cci', 'volume_sma_5', 'volume_sma_10', 'volume_sma_20', 'volume_ratio_5', 'volume_ratio_10', 'volume_ratio_20', 'obv', 'ad', 'mfi', 'vwap', 'roc_5', 'roc_10', 'roc_20', 'mom_5', 'mom_10', 'cmo', 'adx', 'plus_di', 'minus_di', 'aroon_up', 'aroon_down', 'aroon_osc', 'sar', 'trix', 'ultosc', 'atr', 'natr', 'trange', 'volatility_5', 'volatility_10', 'volatility_20', 'price_change', 'volume_change', 'price_volume_trend', 'vwap_change', 'volume_price_sync', 'volume_anomaly', 'price_breakout_volume' ]) if self.use_wave_theory: # 波浪理论特征 enhanced_features.extend([ 'wave_count', 'wave_strength', 'fib_5_0.236', 'fib_5_0.382', 'fib_5_0.5', 'fib_5_0.618', 'fib_5_0.786', 'fib_10_0.236', 'fib_10_0.382', 'fib_10_0.5', 'fib_10_0.618', 'fib_10_0.786', 'fib_20_0.236', 'fib_20_0.382', 'fib_20_0.5', 'fib_20_0.618', 'fib_20_0.786', 'fib_50_0.236', 'fib_50_0.382', 'fib_50_0.5', 'fib_50_0.618', 'fib_50_0.786', 'fib_retracement_382', 'fib_retracement_618', 'support_level', 'resistance_level', 'support_distance', 'resistance_distance', 'support_strength', 'resistance_strength', 'wave_momentum_5', 'wave_momentum_10', 'wave_acceleration', 'wave_consistency' ]) return enhanced_features def prepare_enhanced_data(self, df: pd.DataFrame) -> pd.DataFrame: """ 准备增强数据 Args: df: 原始OHLCV数据 Returns: 增强后的数据 """ # 确保数据按时间排序 if 'timestamps' in df.columns: df = df.sort_values('timestamps').reset_index(drop=True) # 计算技术指标和波浪理论特征 enhanced_df = enhance_kronos_features(df) # 处理缺失值 enhanced_df = self._handle_missing_values(enhanced_df) return enhanced_df def _handle_missing_values(self, df: pd.DataFrame) -> pd.DataFrame: """处理缺失值""" # 对于数值列,使用前向填充和后向填充 numeric_columns = df.select_dtypes(include=[np.number]).columns for col in numeric_columns: if df[col].isna().any(): # 前向填充 df[col] = df[col].fillna(method='ffill') # 后向填充 df[col] = df[col].fillna(method='bfill') # 如果还有缺失值,用0填充 df[col] = df[col].fillna(0) return df def predict_enhanced(self, df: pd.DataFrame, x_timestamp: pd.Series, y_timestamp: pd.Series, pred_len: int, T: float = 1.0, top_k: int = 0, top_p: float = 0.9, sample_count: int = 1, verbose: bool = True) -> pd.DataFrame: """ 使用增强特征进行预测 Args: df: 历史数据DataFrame x_timestamp: 历史时间戳 y_timestamp: 预测时间戳 pred_len: 预测长度 T: 采样温度 top_k: top-k采样 top_p: top-p采样 sample_count: 采样次数 verbose: 是否显示详细信息 Returns: 预测结果DataFrame """ if not isinstance(df, pd.DataFrame): raise ValueError("Input must be a pandas DataFrame.") # 检查基础列是否存在 if not all(col in df.columns for col in self.price_cols): raise ValueError(f"Price columns {self.price_cols} not found in DataFrame.") # 准备增强数据 enhanced_df = self.prepare_enhanced_data(df) # 选择用于预测的特征 prediction_features = self._select_prediction_features(enhanced_df) # 处理缺失的volume和amount列 if self.vol_col not in prediction_features.columns: prediction_features[self.vol_col] = 0.0 prediction_features[self.amt_vol] = 0.0 if self.amt_vol not in prediction_features.columns and self.vol_col in prediction_features.columns: prediction_features[self.amt_vol] = prediction_features[self.vol_col] * prediction_features[self.price_cols].mean(axis=1) # 检查是否有NaN值 if prediction_features.isnull().values.any(): print("⚠️ Warning: DataFrame contains NaN values. Filling with zeros.") prediction_features = prediction_features.fillna(0) # 计算时间特征 from model.kronos import calc_time_stamps x_time_df = calc_time_stamps(x_timestamp) y_time_df = calc_time_stamps(y_timestamp) # 准备输入数据 x = prediction_features.values.astype(np.float32) x_stamp = x_time_df.values.astype(np.float32) y_stamp = y_time_df.values.astype(np.float32) # 数据标准化 x_mean, x_std = np.mean(x, axis=0), np.std(x, axis=0) x = (x - x_mean) / (x_std + 1e-5) x = np.clip(x, -self.clip, self.clip) # 添加批次维度 x = x[np.newaxis, :] x_stamp = x_stamp[np.newaxis, :] y_stamp = y_stamp[np.newaxis, :] # 生成预测 preds = self.generate(x, x_stamp, y_stamp, pred_len, T, top_k, top_p, sample_count, verbose) # 反标准化 preds = preds.squeeze(0) preds = preds * (x_std + 1e-5) + x_mean # 创建预测结果DataFrame # 只返回OHLCV列 output_columns = self.price_cols + [self.vol_col, self.amt_vol] pred_df = pd.DataFrame(preds[:, :len(output_columns)], columns=output_columns, index=y_timestamp) return pred_df def _select_prediction_features(self, enhanced_df: pd.DataFrame) -> pd.DataFrame: """选择用于预测的特征""" # 基础特征 base_features = self.price_cols + [self.vol_col, self.amt_vol] # 选择存在的增强特征 available_enhanced_features = [f for f in self.enhanced_features if f in enhanced_df.columns] # 组合所有特征 all_features = base_features + available_enhanced_features # 选择存在的特征 existing_features = [f for f in all_features if f in enhanced_df.columns] return enhanced_df[existing_features] def analyze_prediction_quality(self, historical_df: pd.DataFrame, pred_df: pd.DataFrame) -> Dict[str, float]: """ 分析预测质量 Args: historical_df: 历史数据 pred_df: 预测数据 Returns: 预测质量分析结果 """ analysis = {} # 计算历史数据的统计特征 hist_stats = self._calculate_statistics(historical_df) pred_stats = self._calculate_statistics(pred_df) # 计算预测一致性 analysis['price_consistency'] = self._calculate_price_consistency(hist_stats, pred_stats) analysis['volume_consistency'] = self._calculate_volume_consistency(hist_stats, pred_stats) analysis['volatility_consistency'] = self._calculate_volatility_consistency(hist_stats, pred_stats) # 计算趋势一致性 analysis['trend_consistency'] = self._calculate_trend_consistency(historical_df, pred_df) return analysis def _calculate_statistics(self, df: pd.DataFrame) -> Dict[str, float]: """计算数据统计特征""" stats = {} if 'close' in df.columns: stats['close_mean'] = df['close'].mean() stats['close_std'] = df['close'].std() stats['close_volatility'] = df['close'].pct_change().std() if 'volume' in df.columns: stats['volume_mean'] = df['volume'].mean() stats['volume_std'] = df['volume'].std() return stats def _calculate_price_consistency(self, hist_stats: Dict, pred_stats: Dict) -> float: """计算价格一致性""" if 'close_mean' not in hist_stats or 'close_mean' not in pred_stats: return 0.0 # 计算价格变化的合理性 price_change_ratio = abs(pred_stats['close_mean'] - hist_stats['close_mean']) / hist_stats['close_mean'] # 如果价格变化在合理范围内(比如20%以内),认为一致性较高 consistency = max(0, 1 - price_change_ratio / 0.2) return min(1.0, consistency) def _calculate_volume_consistency(self, hist_stats: Dict, pred_stats: Dict) -> float: """计算成交量一致性""" if 'volume_mean' not in hist_stats or 'volume_mean' not in pred_stats: return 0.0 # 计算成交量变化的合理性 volume_change_ratio = abs(pred_stats['volume_mean'] - hist_stats['volume_mean']) / hist_stats['volume_mean'] # 成交量变化在50%以内认为合理 consistency = max(0, 1 - volume_change_ratio / 0.5) return min(1.0, consistency) def _calculate_volatility_consistency(self, hist_stats: Dict, pred_stats: Dict) -> float: """计算波动率一致性""" if 'close_volatility' not in hist_stats or 'close_volatility' not in pred_stats: return 0.0 # 计算波动率变化的合理性 vol_change_ratio = abs(pred_stats['close_volatility'] - hist_stats['close_volatility']) / hist_stats['close_volatility'] # 波动率变化在30%以内认为合理 consistency = max(0, 1 - vol_change_ratio / 0.3) return min(1.0, consistency) def _calculate_trend_consistency(self, historical_df: pd.DataFrame, pred_df: pd.DataFrame) -> float: """计算趋势一致性""" if 'close' not in historical_df.columns or 'close' not in pred_df.columns: return 0.0 # 计算历史趋势 hist_trend = np.polyfit(range(len(historical_df)), historical_df['close'], 1)[0] # 计算预测趋势 pred_trend = np.polyfit(range(len(pred_df)), pred_df['close'], 1)[0] # 计算趋势方向一致性 if hist_trend * pred_trend > 0: # 趋势方向一致 trend_consistency = 1 - abs(hist_trend - pred_trend) / max(abs(hist_trend), abs(pred_trend), 1e-8) else: # 趋势方向相反 trend_consistency = 0 return max(0, trend_consistency) class WaveTheoryEnhancedPredictor(EnhancedKronosPredictor): """专门针对波浪理论优化的预测器""" def __init__(self, model, tokenizer, device="cuda:0", max_context=512, clip=5): super().__init__(model, tokenizer, device, max_context, clip, use_technical_indicators=True, use_wave_theory=True) # 波浪理论特定参数 self.wave_sensitivity = 0.8 # 波浪敏感度 self.fibonacci_weight = 0.3 # 斐波那契权重 self.support_resistance_weight = 0.2 # 支撑阻力权重 def predict_with_wave_analysis(self, df: pd.DataFrame, x_timestamp: pd.Series, y_timestamp: pd.Series, pred_len: int, **kwargs) -> Tuple[pd.DataFrame, Dict]: """ 结合波浪分析进行预测 Args: df: 历史数据 x_timestamp: 历史时间戳 y_timestamp: 预测时间戳 pred_len: 预测长度 **kwargs: 其他预测参数 Returns: (预测结果, 波浪分析结果) """ # 进行波浪分析 wave_analysis = self.wave_analyzer.analyze_wave_patterns(df) # 调整预测参数 based on 波浪分析 adjusted_params = self._adjust_prediction_params(wave_analysis, **kwargs) # 进行预测 pred_df = self.predict_enhanced(df, x_timestamp, y_timestamp, pred_len, **adjusted_params) return pred_df, wave_analysis def _adjust_prediction_params(self, wave_analysis: Dict, **kwargs) -> Dict: """根据波浪分析调整预测参数""" adjusted_params = kwargs.copy() # 根据波浪强度调整采样参数 wave_strength = wave_analysis.get('wave_strength', 0.5) if wave_strength > 0.7: # 强波浪,降低随机性 adjusted_params['T'] = kwargs.get('T', 1.0) * 0.8 adjusted_params['top_p'] = kwargs.get('top_p', 0.9) * 0.95 elif wave_strength < 0.3: # 弱波浪,增加随机性 adjusted_params['T'] = kwargs.get('T', 1.0) * 1.2 adjusted_params['top_p'] = kwargs.get('top_p', 0.9) * 1.05 return adjusted_params def create_enhanced_predictor(model_path: str = "NeoQuasar/Kronos-small", tokenizer_path: str = "NeoQuasar/Kronos-Tokenizer-base", device: str = "cuda:0") -> EnhancedKronosPredictor: """ 创建增强版预测器 Args: model_path: 模型路径 tokenizer_path: 分词器路径 device: 计算设备 Returns: 增强版预测器实例 """ try: # 加载模型和分词器 tokenizer = KronosTokenizer.from_pretrained(tokenizer_path) model = Kronos.from_pretrained(model_path) # 创建增强版预测器 predictor = EnhancedKronosPredictor( model=model, tokenizer=tokenizer, device=device, max_context=512, clip=5, use_technical_indicators=True, use_wave_theory=True ) print("✅ 增强版Kronos预测器创建成功!") print(f" - 技术指标: {'启用' if predictor.use_technical_indicators else '禁用'}") print(f" - 波浪理论: {'启用' if predictor.use_wave_theory else '禁用'}") print(f" - 增强特征数量: {len(predictor.enhanced_features)}") return predictor except Exception as e: print(f"❌ 创建增强版预测器失败: {str(e)}") raise if __name__ == "__main__": # 测试代码 print("测试增强版Kronos预测器...") # 创建示例数据 dates = pd.date_range('2024-01-01', periods=100, freq='D') np.random.seed(42) base_price = 100 prices = [base_price] for i in range(99): change = np.random.normal(0, 0.02) prices.append(max(0.01, prices[-1] * (1 + change))) df = pd.DataFrame({ 'timestamps': dates, 'open': prices, 'high': [p * (1 + abs(np.random.normal(0, 0.01))) for p in prices], 'low': [p * (1 - abs(np.random.normal(0, 0.01))) for p in prices], 'close': prices, 'volume': np.random.normal(1000000, 200000, 100) }) # 测试特征增强 enhanced_df = enhance_kronos_features(df) print(f"原始特征: {len(df.columns)}") print(f"增强特征: {len(enhanced_df.columns)}") print(f"新增特征: {len(enhanced_df.columns) - len(df.columns)}") # 显示部分新特征 new_features = [col for col in enhanced_df.columns if col not in df.columns] print(f"\n新增特征示例:") for feature in new_features[:10]: print(f" {feature}")