File size: 8,782 Bytes
b0fc267
4b3e425
 
 
 
 
 
2fc00b0
b0fc267
 
 
c04f979
2fc00b0
4b3e425
2fc00b0
 
 
 
 
 
 
 
c04f979
 
 
 
 
 
 
2fc00b0
 
 
 
 
 
 
c04f979
 
2fc00b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4b3e425
c04f979
2fc00b0
 
c04f979
4b3e425
 
 
 
 
 
2fc00b0
 
4b3e425
 
 
 
 
 
6e1efa8
 
 
373fcc7
 
 
 
 
 
 
 
0c4880f
 
373fcc7
 
 
 
 
0c4880f
 
373fcc7
 
 
 
 
 
6e1efa8
 
373fcc7
6e1efa8
 
 
 
373fcc7
 
 
0c4880f
 
 
 
 
 
 
 
 
 
 
 
373fcc7
 
6e1efa8
 
 
 
0c4880f
 
6e1efa8
 
 
 
 
 
0c4880f
 
 
 
c04f979
2fc00b0
c04f979
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2fc00b0
c04f979
 
6e1efa8
2fc00b0
 
 
 
4b3e425
2fc00b0
 
 
 
 
 
 
 
 
 
 
6e1efa8
c04f979
2fc00b0
c04f979
 
6e1efa8
2fc00b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e1efa8
 
 
 
 
 
c04f979
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# 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