# services/chart_analysis.py import streamlit as st from datetime import datetime from utils.file_handlers import save_chat_history from utils.prompts import create_analysis_prompt class ChartAnalysisService: def __init__(self, claude_service): self.claude_service = claude_service def analyze_multiple_charts(self, image_data_list, patterns, indicators, comparison_type="Individual Analysis", expertise_level="Novice"): """Analyze multiple charts and provide comprehensive analysis""" try: results = [] individual_analyses = [] # First get individual analyses for idx, image_data in enumerate(image_data_list): chart_type = self.claude_service.detect_chart_type(image_data) st.info(f"Chart {idx + 1} detected as: {chart_type}") analysis = self.analyze_single_chart( image_data, patterns, indicators, chart_type, expertise_level ) if analysis: individual_analyses.append(analysis) # If we have multiple charts, perform comparison analysis if len(individual_analyses) > 1 and comparison_type != "Individual Analysis": comparison_prompt = self.create_comparison_prompt( individual_analyses, comparison_type, expertise_level ) # Combine all images for the comparison analysis comparative_analysis = self.claude_service.analyze_multiple_images( image_data_list, comparison_prompt ) if comparative_analysis: results.append({ 'timestamp': datetime.now().isoformat(), 'analysis_type': comparison_type, 'analysis': comparative_analysis, 'num_charts': len(image_data_list) }) # Add individual analyses results.extend(individual_analyses) return results except Exception as e: st.error(f"Error in multiple chart analysis: {str(e)}") return None def analyze_single_chart(self, image_data, patterns, indicators, chart_type=None, expertise_level="Novice"): """Analyze a single chart""" try: prompt = create_analysis_prompt(patterns, indicators, expertise_level) analysis = self.claude_service.analyze_image(image_data, prompt) if analysis: return { 'timestamp': datetime.now().isoformat(), 'chart_type': chart_type, 'analysis': analysis, 'analysis_type': 'Individual' } return None except Exception as e: st.error(f"Error in chart analysis: {str(e)}") return None def handle_follow_up_question(self, question, previous_analysis, image_data=None): """Handle follow-up questions about the analysis""" try: # Get previous conversation context from session state if 'conversation_context' not in st.session_state: st.session_state.conversation_context = [] # Add previous analysis to context if not already present if previous_analysis and not st.session_state.conversation_context: st.session_state.conversation_context.append({ 'role': 'assistant', 'content': previous_analysis, 'timestamp': datetime.now().isoformat() }) # Add current question to context st.session_state.conversation_context.append({ 'role': 'user', 'content': question, 'timestamp': datetime.now().isoformat() }) # Create a conversation-aware prompt context = "\n".join([f"{'Q' if msg['role'] == 'user' else 'A'}: {msg['content']}" for msg in st.session_state.conversation_context]) response = self.claude_service.continue_analysis( question=question, previous_analysis=context, # Use full conversation context image_data=image_data ) if response: # Add response to context st.session_state.conversation_context.append({ 'role': 'assistant', 'content': response, 'timestamp': datetime.now().isoformat() }) # Add to followups for UI display if 'followups' not in st.session_state: st.session_state.followups = [] st.session_state.followups.append({ 'question': question, 'response': response, 'timestamp': datetime.now().isoformat() }) return { 'timestamp': datetime.now().isoformat(), 'question': question, 'analysis': response, 'analysis_type': 'Follow-up', 'context_length': len(st.session_state.conversation_context) } return None except Exception as e: st.error(f"Error handling follow-up question: {str(e)}") return None def get_conversation_context(self): """Get the current conversation context""" return st.session_state.get('conversation_context', []) def create_comparison_prompt(self, individual_analyses, comparison_type, expertise_level="Novice"): """Create a prompt for comparing multiple charts""" expertise_adjustments = { "Novice": { "depth": "Focus on basic relationships and clear patterns.", "language": "Use simple terms and explain technical concepts." }, "Intermediate": { "depth": "Include both basic and advanced correlations.", "language": "Balance technical terms with clear explanations." }, "Expert": { "depth": "Provide sophisticated multi-chart analysis.", "language": "Use full technical terminology and advanced concepts." } } adj = expertise_adjustments[expertise_level] if comparison_type == "Correlated Analysis": prompt = f"""Analyze these charts together and provide insights on their relationships. {adj['depth']} {adj['language']} 1. Correlation Analysis - Identify any price correlations - Note common patterns or divergences - Highlight synchronized movements 2. Relative Strength Comparison - Compare relative performance - Identify leader/laggard relationships - Note any rotation patterns 3. Market Implications - What these relationships suggest - Potential trading opportunities - Risk considerations 4. Summary Provide a clear summary of the key relationships and trading implications.""" else: # Market Trend Analysis prompt = f"""Analyze these charts to identify broader market patterns. {adj['depth']} {adj['language']} 1. Market Trend Analysis - Identify common trend directions - Note sector/market momentum - Highlight any broader pattern formations 2. Market Condition Assessment - Overall market health - Risk levels - Potential market turning points 3. Trading Implications - Sector rotation opportunities - Risk management considerations - Timeframe recommendations 4. Summary - Provide a clear summary of the market condition - List key trading implications - Note major risk factors""" # Add disclaimer prompt += "\n\nIMPORTANT: Clearly mark this as AI-generated analysis for informational purposes only." return prompt