""" AI分析数据访问对象 """ from typing import Dict, List, Optional, Any import json from datetime import datetime, date from .base_dao import BaseDAO class AIAnalysisDAO(BaseDAO): """AI分析数据访问对象""" def save_analysis(self, stock_code: str, analysis_type: str, analysis_data: Dict, analysis_date: str = None) -> bool: """保存AI分析结果""" if analysis_date is None: analysis_date = self.get_today_date() try: # 检查是否已存在当日的分析 existing = self.get_analysis(stock_code, analysis_type, analysis_date) investment_summary = analysis_data.get('investment_suggestion', {}) investment_key_points = json.dumps(investment_summary.get('key_points', []), ensure_ascii=False) investment_summary_text = investment_summary.get('summary', '') investment_action = investment_summary.get('action', '') price_analysis = analysis_data.get('price_analysis', {}) if existing: # 更新现有分析 query = """ UPDATE ai_analysis SET investment_summary = %s, investment_action = %s, investment_key_points = %s, valuation_analysis = %s, financial_analysis = %s, growth_analysis = %s, risk_analysis = %s, reasonable_price_min = %s, reasonable_price_max = %s, target_market_value_min = %s, target_market_value_max = %s, from_cache = %s, updated_at = CURRENT_TIMESTAMP WHERE stock_code = %s AND analysis_type = %s AND analysis_date = %s """ self._execute_update(query, ( investment_summary_text, investment_action, investment_key_points, analysis_data.get('analysis', {}).get('估值分析', ''), analysis_data.get('analysis', {}).get('财务健康状况', ''), analysis_data.get('analysis', {}).get('成长潜力', ''), analysis_data.get('analysis', {}).get('风险评估', ''), self.parse_float(price_analysis.get('合理价格区间', [None, None])[0]), self.parse_float(price_analysis.get('合理价格区间', [None, None])[1]), self.parse_float(price_analysis.get('目标市值区间', [None, None])[0]), self.parse_float(price_analysis.get('目标市值区间', [None, None])[1]), bool(analysis_data.get('from_cache', False)), stock_code, analysis_type, analysis_date )) else: # 插入新分析 query = """ INSERT INTO ai_analysis ( stock_code, analysis_type, analysis_date, investment_summary, investment_action, investment_key_points, valuation_analysis, financial_analysis, growth_analysis, risk_analysis, reasonable_price_min, reasonable_price_max, target_market_value_min, target_market_value_max, from_cache ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ self._execute_insert(query, ( stock_code, analysis_type, analysis_date, investment_summary_text, investment_action, investment_key_points, analysis_data.get('analysis', {}).get('估值分析', ''), analysis_data.get('analysis', {}).get('财务健康状况', ''), analysis_data.get('analysis', {}).get('成长潜力', ''), analysis_data.get('analysis', {}).get('风险评估', ''), self.parse_float(price_analysis.get('合理价格区间', [None, None])[0]), self.parse_float(price_analysis.get('合理价格区间', [None, None])[1]), self.parse_float(price_analysis.get('目标市值区间', [None, None])[0]), self.parse_float(price_analysis.get('目标市值区间', [None, None])[1]), bool(analysis_data.get('from_cache', False)) )) self.log_data_update(f'ai_analysis_{analysis_type}', stock_code, 'success', 'Analysis saved') return True except Exception as e: self.logger.error(f"保存AI分析失败: {stock_code}, {analysis_type}, 错误: {e}") self.log_data_update(f'ai_analysis_{analysis_type}', stock_code, 'failed', str(e)) return False def get_analysis(self, stock_code: str, analysis_type: str, analysis_date: str = None) -> Optional[Dict]: """获取AI分析结果""" if analysis_date is None: analysis_date = self.get_today_date() query = """ SELECT * FROM ai_analysis WHERE stock_code = %s AND analysis_type = %s AND analysis_date = %s """ return self._execute_single_query(query, (stock_code, analysis_type, analysis_date)) def get_latest_analysis(self, stock_code: str, analysis_type: str) -> Optional[Dict]: """获取最新的AI分析结果""" query = """ SELECT * FROM ai_analysis WHERE stock_code = %s AND analysis_type = %s ORDER BY analysis_date DESC LIMIT 1 """ return self._execute_single_query(query, (stock_code, analysis_type)) def get_all_analysis_types(self, stock_code: str, analysis_date: str = None) -> List[Dict]: """获取股票的所有类型分析""" if analysis_date is None: analysis_date = self.get_today_date() query = """ SELECT * FROM ai_analysis WHERE stock_code = %s AND analysis_date = %s ORDER BY analysis_type """ return self._execute_query(query, (stock_code, analysis_date)) def format_analysis_data(self, analysis_record: Dict) -> Dict: """将数据库记录格式化为原始分析数据格式""" if not analysis_record: return {} # 解析JSON字段 key_points = [] if analysis_record.get('investment_key_points'): try: key_points = json.loads(analysis_record['investment_key_points']) except json.JSONDecodeError: key_points = [] # 构建投资建议 investment_suggestion = { 'summary': analysis_record.get('investment_summary', ''), 'action': analysis_record.get('investment_action', ''), 'key_points': key_points } # 构建分析详情 analysis = {} if analysis_record.get('valuation_analysis'): analysis['估值分析'] = analysis_record['valuation_analysis'] if analysis_record.get('financial_analysis'): analysis['财务健康状况'] = analysis_record['financial_analysis'] if analysis_record.get('growth_analysis'): analysis['成长潜力'] = analysis_record['growth_analysis'] if analysis_record.get('risk_analysis'): analysis['风险评估'] = analysis_record['risk_analysis'] # 构建价格分析 price_analysis = {} if analysis_record.get('reasonable_price_min') or analysis_record.get('reasonable_price_max'): price_analysis['合理价格区间'] = [ analysis_record.get('reasonable_price_min'), analysis_record.get('reasonable_price_max') ] if analysis_record.get('target_market_value_min') or analysis_record.get('target_market_value_max'): price_analysis['目标市值区间'] = [ analysis_record.get('target_market_value_min'), analysis_record.get('target_market_value_max') ] return { 'investment_suggestion': investment_suggestion, 'analysis': analysis, 'price_analysis': price_analysis, 'from_cache': analysis_record.get('from_cache', False) } def get_analysis_history(self, stock_code: str, analysis_type: str, days: int = 30) -> List[Dict]: """获取分析历史""" query = """ SELECT * FROM ai_analysis WHERE stock_code = %s AND analysis_type = %s AND analysis_date >= DATE_SUB(CURDATE(), INTERVAL %s DAY) ORDER BY analysis_date DESC """ return self._execute_query(query, (stock_code, analysis_type, days)) def delete_analysis(self, stock_code: str, analysis_type: str, before_date: str = None) -> int: """删除分析数据""" if before_date: query = """ DELETE FROM ai_analysis WHERE stock_code = %s AND analysis_type = %s AND analysis_date < %s """ return self._execute_update(query, (stock_code, analysis_type, before_date)) else: query = """ DELETE FROM ai_analysis WHERE stock_code = %s AND analysis_type = %s """ return self._execute_update(query, (stock_code, analysis_type)) def get_analysis_count(self, analysis_type: str = None) -> int: """获取分析数量""" if analysis_type: query = "SELECT COUNT(*) as count FROM ai_analysis WHERE analysis_type = %s" result = self._execute_single_query(query, (analysis_type,)) else: query = "SELECT COUNT(*) as count FROM ai_analysis" result = self._execute_single_query(query) return result['count'] if result else 0