PierreBrunelle commited on
Commit
3097a6c
·
verified ·
1 Parent(s): f257889

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -22
app.py CHANGED
@@ -55,40 +55,108 @@ def calculate_basic_indicators(data: pd.DataFrame) -> pd.DataFrame:
55
  return df.ffill().bfill()
56
 
57
  @pxt.udf
58
- def generate_analysis_prompt(data: str, analysis_type: str) -> list[dict]:
 
 
59
  """Generate a structured prompt for AI analysis"""
60
- system_prompt = '''You are a financial analyst providing market analysis. Structure your response using EXACTLY the following format and sections:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  SUMMARY
63
- Provide a clear 2-3 sentence executive summary of your analysis.
64
 
65
  TECHNICAL ANALYSIS
66
- • Moving Averages: Analyze trends using MA20, MA50, and MA200
 
67
  • RSI Analysis: Current RSI level and implications
68
- • MACD Analysis: MACD trends and signals
69
  • Volume Analysis: Notable volume patterns and implications
 
70
 
71
  MARKET CONTEXT
72
- List 2-3 key market factors affecting the stock
73
- Include relevant sector/industry context
74
- Note any significant recent developments
75
 
76
  RISKS
77
- Risk 1: [Specific risk and brief explanation]
78
- Risk 2: [Specific risk and brief explanation]
79
- Risk 3: [Specific risk and brief explanation]
80
 
81
  OPPORTUNITIES
82
- Opportunity 1: [Specific opportunity and brief explanation]
83
- Opportunity 2: [Specific opportunity and brief explanation]
84
- Opportunity 3: [Specific opportunity and brief explanation]
 
 
 
 
 
 
85
 
86
  RECOMMENDATION
87
- Provide a clear, actionable investment recommendation based on the analysis above.'''
 
 
 
 
 
 
 
 
88
 
89
  return [
90
  {'role': 'system', 'content': system_prompt},
91
- {'role': 'user', 'content': f'Analyze this market data for {analysis_type} analysis:\n{data}'}
92
  ]
93
 
94
  def parse_analysis_response(response: str) -> Dict[str, str]:
@@ -99,6 +167,7 @@ def parse_analysis_response(response: str) -> Dict[str, str]:
99
  'MARKET CONTEXT': None,
100
  'RISKS': None,
101
  'OPPORTUNITIES': None,
 
102
  'RECOMMENDATION': None
103
  }
104
 
@@ -140,6 +209,7 @@ def parse_analysis_response(response: str) -> Dict[str, str]:
140
  'MARKET CONTEXT': 'Market context information not available',
141
  'RISKS': 'Risk assessment not available',
142
  'OPPORTUNITIES': 'Opportunity analysis not available',
 
143
  'RECOMMENDATION': 'Investment recommendation not available'
144
  }
145
 
@@ -252,6 +322,26 @@ def process_outputs(ticker_symbol, analysis_type, time_horizon, risk_tolerance,
252
  market_data = stock.history(period='1y')
253
  if market_data.empty:
254
  raise ValueError("No data found for the specified ticker symbol.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  technical_data = calculate_basic_indicators(market_data)
257
  market_data_json = technical_data.to_json(date_format='iso')
@@ -263,7 +353,14 @@ def process_outputs(ticker_symbol, analysis_type, time_horizon, risk_tolerance,
263
  'timestamp': datetime.now()
264
  }])
265
 
266
- data_table['prompt'] = generate_analysis_prompt(data_table.data, analysis_type)
 
 
 
 
 
 
 
267
  data_table['analysis'] = openai.chat_completions(
268
  messages=data_table.prompt,
269
  model='gpt-4o-mini-2024-07-18',
@@ -324,15 +421,17 @@ def process_outputs(ticker_symbol, analysis_type, time_horizon, risk_tolerance,
324
  return (
325
  json.dumps(company_info_data),
326
  json.dumps(market_stats_data),
 
327
  plot,
328
  parsed_analysis['SUMMARY'],
329
  parsed_analysis['TECHNICAL ANALYSIS'],
330
  parsed_analysis['MARKET CONTEXT'],
331
  parsed_analysis['RISKS'],
332
  parsed_analysis['OPPORTUNITIES'],
 
333
  parsed_analysis['RECOMMENDATION'],
334
  technical_data_with_time,
335
- raw_llm_output # Add raw output to return values
336
  )
337
 
338
  except Exception as e:
@@ -342,6 +441,7 @@ def process_outputs(ticker_symbol, analysis_type, time_horizon, risk_tolerance,
342
  empty_df = pd.DataFrame()
343
 
344
  return (
 
345
  empty_json,
346
  empty_json,
347
  None,
@@ -351,8 +451,9 @@ def process_outputs(ticker_symbol, analysis_type, time_horizon, risk_tolerance,
351
  no_data_msg,
352
  no_data_msg,
353
  no_data_msg,
 
354
  empty_df,
355
- f"Error occurred: {str(e)}" # Add error message to raw output
356
  )
357
 
358
  def create_interface() -> gr.Blocks:
@@ -472,6 +573,11 @@ def create_interface() -> gr.Blocks:
472
  label="Market Statistics",
473
  height=150
474
  )
 
 
 
 
 
475
 
476
  with gr.TabItem("📑 Historical Data"):
477
  technical_data = gr.DataFrame(
@@ -544,6 +650,14 @@ def create_interface() -> gr.Blocks:
544
  max_lines=7,
545
  show_label=True
546
  )
 
 
 
 
 
 
 
 
547
 
548
  with gr.Row():
549
  recommendation = gr.Textbox(
@@ -606,10 +720,10 @@ def create_interface() -> gr.Blocks:
606
  investment_style, technical_depth
607
  ],
608
  outputs=[
609
- company_info, market_stats, plot_output,
610
  summary, tech_analysis, market_context,
611
- risks, opportunities, recommendation,
612
- technical_data, raw_output # Add raw_output to outputs
613
  ]
614
  )
615
 
 
55
  return df.ffill().bfill()
56
 
57
  @pxt.udf
58
+ def generate_analysis_prompt(data: str, analysis_type: str, time_horizon: str,
59
+ risk_tolerance: str, investment_style: str,
60
+ technical_depth: str) -> list[dict]:
61
  """Generate a structured prompt for AI analysis"""
62
+
63
+ # Create specific guidance based on parameters
64
+ time_horizon_guidance = {
65
+ 'short': 'Focus on short-term trading opportunities within 1-3 months. Emphasize technical signals and immediate catalysts.',
66
+ 'medium': 'Balance short-term opportunities with medium-term trends over 3-12 months. Consider both technical and fundamental factors.',
67
+ 'long': 'Prioritize long-term growth potential over 1+ years. Emphasize fundamental analysis and strategic positioning.'
68
+ }
69
+
70
+ risk_tolerance_guidance = {
71
+ 'conservative': 'Prioritize capital preservation. Focus on stable, large-cap stocks with strong fundamentals. Suggest conservative options strategies like covered calls.',
72
+ 'moderate': 'Balance growth opportunities with risk management. Consider mid-cap stocks and moderate options strategies.',
73
+ 'aggressive': 'Seek high-growth opportunities. Include small-cap stocks and more aggressive options strategies in the analysis.'
74
+ }
75
+
76
+ investment_style_guidance = {
77
+ 'value': 'Focus on valuation metrics, margin of safety, and undervalued opportunities.',
78
+ 'growth': 'Emphasize revenue growth, market expansion, and future potential.',
79
+ 'momentum': 'Focus on price trends, relative strength, and technical indicators.',
80
+ 'balanced': 'Consider both value and growth factors, maintaining a balanced perspective.',
81
+ 'income': 'Prioritize dividend yield, payout ratio, and income-generating options strategies.'
82
+ }
83
+
84
+ analysis_depth = {
85
+ 'comprehensive': 'Provide detailed analysis across all categories.',
86
+ 'quantitative': 'Focus on numerical metrics and statistical analysis.',
87
+ 'technical': 'Emphasize technical analysis and chart patterns.'
88
+ }
89
+
90
+ technical_guidance = {
91
+ 'basic': 'Focus on essential technical indicators (MA, RSI, MACD).',
92
+ 'advanced': 'Include advanced technical analysis including Fibonacci levels, Elliott Wave patterns, and advanced options analysis.'
93
+ }
94
+
95
+ system_prompt = f'''You are a senior investment advisor and market analyst with decades of experience, holding CFA and CMT certifications. Provide analysis tailored to the following parameters:
96
+
97
+ TIME HORIZON: {time_horizon.upper()}
98
+ {time_horizon_guidance[time_horizon]}
99
+
100
+ RISK PROFILE: {risk_tolerance.upper()}
101
+ {risk_tolerance_guidance[risk_tolerance]}
102
+
103
+ INVESTMENT STYLE: {investment_style.upper()}
104
+ {investment_style_guidance[investment_style]}
105
+
106
+ ANALYSIS FOCUS: {analysis_type.upper()}
107
+ {analysis_depth[analysis_type]}
108
+
109
+ TECHNICAL DEPTH: {technical_depth.upper()}
110
+ {technical_guidance[technical_depth]}
111
+
112
+ Structure your response using EXACTLY the following format and sections:
113
 
114
  SUMMARY
115
+ Provide a clear 2-3 sentence executive summary aligned with the specified time horizon ({time_horizon}) and risk tolerance ({risk_tolerance}).
116
 
117
  TECHNICAL ANALYSIS
118
+ {technical_guidance[technical_depth]}
119
+ • Moving Averages: Analyze trends with emphasis on {time_horizon} timeframe
120
  • RSI Analysis: Current RSI level and implications
121
+ • MACD Analysis: Signal trends relevant to {time_horizon} horizon
122
  • Volume Analysis: Notable volume patterns and implications
123
+ {"• Advanced Patterns: Fibonacci levels, Elliott Wave analysis" if technical_depth == "advanced" else ""}
124
 
125
  MARKET CONTEXT
126
+ Sector Analysis: {"Long-term industry trends and positioning" if time_horizon == "long" else "Short-term sector momentum" if time_horizon == "short" else "Medium-term sector outlook"}
127
+ {"Fundamental Drivers: Key growth catalysts" if investment_style == "growth" else "Value Metrics: Key valuation catalysts" if investment_style == "value" else "Market Dynamics: Key price catalysts"}
128
+ Economic Impact: Factors relevant to {time_horizon} horizon
129
 
130
  RISKS
131
+ Identify and quantify risks specific to {risk_tolerance} risk tolerance
132
+ Focus on {time_horizon} horizon risks
133
+ {"Include volatility analysis" if technical_depth == "advanced" else ""}
134
 
135
  OPPORTUNITIES
136
+ Align opportunities with {investment_style} style
137
+ Focus on {time_horizon} timeline
138
+ Match risk/reward to {risk_tolerance} profile
139
+
140
+ OPTIONS STRATEGY
141
+ {"• Advanced Options Analysis: Complex strategies and volatility analysis" if technical_depth == "advanced" else "• Basic Options Strategies: Simple hedging and income generation"}
142
+ • Tailor strategies to {risk_tolerance} risk tolerance
143
+ • Focus on {time_horizon} expiration cycles
144
+ • Match strategies to {investment_style} style objectives
145
 
146
  RECOMMENDATION
147
+ Provide specific recommendations aligned with:
148
+ - {time_horizon.capitalize()} time horizon
149
+ - {risk_tolerance.capitalize()} risk tolerance
150
+ - {investment_style.capitalize()} investment style
151
+ • Include position sizing appropriate for risk level
152
+ • Specify entry, exit, and stop-loss levels
153
+ • {"Include advanced technical levels" if technical_depth == "advanced" else "Focus on key support/resistance levels"}
154
+
155
+ IMPORTANT: This analysis is for informational purposes only. All investments carry risk. Please consult with a licensed financial advisor before making investment decisions.'''
156
 
157
  return [
158
  {'role': 'system', 'content': system_prompt},
159
+ {'role': 'user', 'content': f'Analyze this market data considering the specified parameters:\n{data}'}
160
  ]
161
 
162
  def parse_analysis_response(response: str) -> Dict[str, str]:
 
167
  'MARKET CONTEXT': None,
168
  'RISKS': None,
169
  'OPPORTUNITIES': None,
170
+ 'OPTIONS STRATEGY': None,
171
  'RECOMMENDATION': None
172
  }
173
 
 
209
  'MARKET CONTEXT': 'Market context information not available',
210
  'RISKS': 'Risk assessment not available',
211
  'OPPORTUNITIES': 'Opportunity analysis not available',
212
+ 'OPTIONS STRATEGY': 'Options trading analysis not available',
213
  'RECOMMENDATION': 'Investment recommendation not available'
214
  }
215
 
 
322
  market_data = stock.history(period='1y')
323
  if market_data.empty:
324
  raise ValueError("No data found for the specified ticker symbol.")
325
+ options_data = stock.options # Get available expiration dates
326
+
327
+ if len(options_data) > 0:
328
+ nearest_expiry = options_data[0]
329
+ opt_chain = stock.option_chain(nearest_expiry)
330
+ options_info = {
331
+ 'Nearest Expiry': nearest_expiry,
332
+ 'Call Volume': int(opt_chain.calls['volume'].sum()),
333
+ 'Put Volume': int(opt_chain.puts['volume'].sum()),
334
+ 'Put/Call Ratio': float(opt_chain.puts['volume'].sum() / opt_chain.calls['volume'].sum()),
335
+ 'Implied Volatility': float(opt_chain.calls['impliedVolatility'].mean())
336
+ }
337
+ else:
338
+ options_info = {
339
+ 'Nearest Expiry': 'N/A',
340
+ 'Call Volume': 0,
341
+ 'Put Volume': 0,
342
+ 'Put/Call Ratio': 0,
343
+ 'Implied Volatility': 0
344
+ }
345
 
346
  technical_data = calculate_basic_indicators(market_data)
347
  market_data_json = technical_data.to_json(date_format='iso')
 
353
  'timestamp': datetime.now()
354
  }])
355
 
356
+ data_table['prompt'] = generate_analysis_prompt(
357
+ data_table.data,
358
+ analysis_type,
359
+ time_horizon,
360
+ risk_tolerance,
361
+ investment_style,
362
+ technical_depth
363
+ )
364
  data_table['analysis'] = openai.chat_completions(
365
  messages=data_table.prompt,
366
  model='gpt-4o-mini-2024-07-18',
 
421
  return (
422
  json.dumps(company_info_data),
423
  json.dumps(market_stats_data),
424
+ json.dumps(options_info), # Add options info to return values
425
  plot,
426
  parsed_analysis['SUMMARY'],
427
  parsed_analysis['TECHNICAL ANALYSIS'],
428
  parsed_analysis['MARKET CONTEXT'],
429
  parsed_analysis['RISKS'],
430
  parsed_analysis['OPPORTUNITIES'],
431
+ parsed_analysis['OPTIONS STRATEGY'], # Add options strategy
432
  parsed_analysis['RECOMMENDATION'],
433
  technical_data_with_time,
434
+ raw_llm_output
435
  )
436
 
437
  except Exception as e:
 
441
  empty_df = pd.DataFrame()
442
 
443
  return (
444
+ empty_json,
445
  empty_json,
446
  empty_json,
447
  None,
 
451
  no_data_msg,
452
  no_data_msg,
453
  no_data_msg,
454
+ no_data_msg,
455
  empty_df,
456
+ f"Error occurred: {str(e)}"
457
  )
458
 
459
  def create_interface() -> gr.Blocks:
 
573
  label="Market Statistics",
574
  height=150
575
  )
576
+ with gr.Column(scale=1):
577
+ options_info = gr.JSON(
578
+ label="Options Market Data",
579
+ height=150
580
+ )
581
 
582
  with gr.TabItem("📑 Historical Data"):
583
  technical_data = gr.DataFrame(
 
650
  max_lines=7,
651
  show_label=True
652
  )
653
+
654
+ with gr.Row():
655
+ options_strategy = gr.Textbox(
656
+ label="Options Trading Strategy",
657
+ lines=8,
658
+ max_lines=10,
659
+ show_label=True
660
+ )
661
 
662
  with gr.Row():
663
  recommendation = gr.Textbox(
 
720
  investment_style, technical_depth
721
  ],
722
  outputs=[
723
+ company_info, market_stats, options_info, plot_output,
724
  summary, tech_analysis, market_context,
725
+ risks, opportunities, options_strategy, recommendation,
726
+ technical_data, raw_output
727
  ]
728
  )
729