tbdavid2019 commited on
Commit
76e906f
·
1 Parent(s): cdf1418
Files changed (1) hide show
  1. app.py +25 -14
app.py CHANGED
@@ -16,6 +16,7 @@ from ta.volume import volume_weighted_average_price
16
  import dotenv
17
  dotenv.load_dotenv()
18
 
 
19
  FUNDAMENTAL_ANALYST_PROMPT = """
20
  You are a fundamental analyst specializing in evaluating company (whose symbol is {company}) performance based on stock prices, technical indicators, financial metrics, recent news, industry trends, competitor positioning, and financial ratios. Your task is to provide a comprehensive summary.
21
 
@@ -32,11 +33,11 @@ You have access to the following tools:
32
  2. Analyze the following areas in sequence:
33
  - **Stock price movements and technical indicators**: Examine recent price trends, volatility, and signals from RSI, MACD, VWAP, and other indicators.
34
  - **Financial health and key financial ratios**: Assess profitability, liquidity, solvency, and operational efficiency using metrics such as:
35
- - Profitability Ratios: Gross Profit Margin, Net Profit Margin, Operating Profit Margin
36
- - Liquidity Ratios: Current Ratio, Quick Ratio
37
- - Solvency Ratios: Debt-to-Equity Ratio, Interest Coverage Ratio
38
- - Efficiency Ratios: Inventory Turnover, Accounts Receivable Turnover
39
- - Market Ratios: Price-to-Earnings Ratio (P/E), Price-to-Book Ratio (P/B)
40
  - **Recent news and market sentiment**: Identify significant events or trends impacting the company's market perception.
41
  - **Industry analysis**: Evaluate the industry’s growth trends, technological advancements, and regulatory environment. Identify how the industry is evolving and how it affects the target company.
42
  - **Competitor analysis**: Compare the target company with key competitors in terms of market share, financial health, and growth potential.
@@ -47,7 +48,7 @@ You have access to the following tools:
47
 
48
  ### Output Format : 以下請用繁體中文輸出
49
  {
50
- "stock": "",
51
  "price_analysis": "<股票價格趨勢與技術指標分析>",
52
  "technical_analysis": "<技術指標分析與見解>",
53
  "financial_analysis": {
@@ -64,6 +65,14 @@ You have access to the following tools:
64
  "final_summary": "<整體綜合結論與投資建議>",
65
  "Asked Question Answer": "<根據上述分析的具體回答>"
66
  }
 
 
 
 
 
 
 
 
67
  """
68
 
69
  def period_to_start_end(period_str: str):
@@ -78,12 +87,12 @@ def period_to_start_end(period_str: str):
78
  elif period_str == "1yr":
79
  start = now - dt.timedelta(weeks=52)
80
  else:
 
81
  start = now - dt.timedelta(weeks=13)
82
  return start, now
83
 
84
-
85
  def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
86
- """Fetches historical stock price data and technical indicator for a given ticker."""
87
  try:
88
  start, end = period_to_start_end(period)
89
  data = yf.download(
@@ -96,7 +105,7 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
96
  if data.empty:
97
  return {"error": f"No stock data found for {ticker}"}
98
 
99
- # 如果 columns 有多層,才做重命名
100
  if data.columns.nlevels > 1:
101
  data.columns = [col[0] for col in data.columns]
102
 
@@ -105,9 +114,11 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
105
 
106
  df = data.copy()
107
 
108
- indicators = {}
109
  n = min(12, len(df))
110
 
 
 
111
  # RSI
112
  rsi_series = RSIIndicator(df['Close'], window=14).rsi().iloc[-n:]
113
  indicators["RSI"] = {
@@ -149,7 +160,6 @@ def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
149
  except Exception as e:
150
  return f"Error fetching price data: {str(e)}"
151
 
152
-
153
  def get_financial_news(ticker: str) -> Union[Dict, str]:
154
  """Fetches the latest financial news related to a given ticker."""
155
  try:
@@ -171,7 +181,6 @@ def get_financial_news(ticker: str) -> Union[Dict, str]:
171
  except Exception as e:
172
  return f"Error fetching news: {str(e)}"
173
 
174
-
175
  def get_financial_metrics(ticker: str) -> Union[Dict, str]:
176
  """Fetches key financial ratios for a given ticker."""
177
  try:
@@ -186,7 +195,6 @@ def get_financial_metrics(ticker: str) -> Union[Dict, str]:
186
  except Exception as e:
187
  return f"Error fetching ratios: {str(e)}"
188
 
189
- # --- 綜合基本面分析 ---
190
  def analyze_stock(api_key: str, ticker: str, period: str) -> str:
191
  """
192
  根據輸入的 LLM API key、股票代號與時間區間,抓取各項資料後,
@@ -199,12 +207,13 @@ def analyze_stock(api_key: str, ticker: str, period: str) -> str:
199
  openai_api_key=api_key,
200
  temperature=0
201
  )
 
202
  # 取得資料
203
  price_data = get_stock_prices(ticker, period)
204
  metrics = get_financial_metrics(ticker)
205
  news = get_financial_news(ticker)
206
 
207
- # 準備 prompt
208
  prompt = FUNDAMENTAL_ANALYST_PROMPT.replace("{company}", ticker)
209
  user_question = "Should I buy this stock?"
210
  analysis_prompt = f"""
@@ -221,9 +230,11 @@ def analyze_stock(api_key: str, ticker: str, period: str) -> str:
221
 
222
  {prompt}
223
  """
 
224
  # 呼叫 LLM 生成最終分析報告
225
  response = llm.invoke(analysis_prompt)
226
  return response.content
 
227
  except Exception as e:
228
  return f"分析過程中發生錯誤: {str(e)}\n{traceback.format_exc()}"
229
 
 
16
  import dotenv
17
  dotenv.load_dotenv()
18
 
19
+ # --- 新版 Prompt ---
20
  FUNDAMENTAL_ANALYST_PROMPT = """
21
  You are a fundamental analyst specializing in evaluating company (whose symbol is {company}) performance based on stock prices, technical indicators, financial metrics, recent news, industry trends, competitor positioning, and financial ratios. Your task is to provide a comprehensive summary.
22
 
 
33
  2. Analyze the following areas in sequence:
34
  - **Stock price movements and technical indicators**: Examine recent price trends, volatility, and signals from RSI, MACD, VWAP, and other indicators.
35
  - **Financial health and key financial ratios**: Assess profitability, liquidity, solvency, and operational efficiency using metrics such as:
36
+ - Profitability Ratios: Gross Profit Margin, Net Profit Margin, Operating Profit Margin
37
+ - Liquidity Ratios: Current Ratio, Quick Ratio
38
+ - Solvency Ratios: Debt-to-Equity Ratio, Interest Coverage Ratio
39
+ - Efficiency Ratios: Inventory Turnover, Accounts Receivable Turnover
40
+ - Market Ratios: Price-to-Earnings Ratio (P/E), Price-to-Book Ratio (P/B)
41
  - **Recent news and market sentiment**: Identify significant events or trends impacting the company's market perception.
42
  - **Industry analysis**: Evaluate the industry’s growth trends, technological advancements, and regulatory environment. Identify how the industry is evolving and how it affects the target company.
43
  - **Competitor analysis**: Compare the target company with key competitors in terms of market share, financial health, and growth potential.
 
48
 
49
  ### Output Format : 以下請用繁體中文輸出
50
  {
51
+ "stock": "<Stock Symbol>",
52
  "price_analysis": "<股票價格趨勢與技術指標分析>",
53
  "technical_analysis": "<技術指標分析與見解>",
54
  "financial_analysis": {
 
65
  "final_summary": "<整體綜合結論與投資建議>",
66
  "Asked Question Answer": "<根據上述分析的具體回答>"
67
  }
68
+
69
+ ---
70
+
71
+ ### Guidelines:
72
+ - Use the provided tools for data. If any data is unavailable, clearly state so in the respective section.
73
+ - Ensure the analysis is objective, data-driven, and free of speculative language.
74
+ - Keep responses concise but informative. Highlight actionable insights and risks.
75
+ - Output should be structured, easy to read, and in Traditional Chinese.
76
  """
77
 
78
  def period_to_start_end(period_str: str):
 
87
  elif period_str == "1yr":
88
  start = now - dt.timedelta(weeks=52)
89
  else:
90
+ # 若未指定或指定其他值,一律視為 3 個月
91
  start = now - dt.timedelta(weeks=13)
92
  return start, now
93
 
 
94
  def get_stock_prices(ticker: str, period: str = "3mo") -> Union[Dict, str]:
95
+ """Fetches historical stock price data and technical indicators for a given ticker."""
96
  try:
97
  start, end = period_to_start_end(period)
98
  data = yf.download(
 
105
  if data.empty:
106
  return {"error": f"No stock data found for {ticker}"}
107
 
108
+ # 處理多層欄位
109
  if data.columns.nlevels > 1:
110
  data.columns = [col[0] for col in data.columns]
111
 
 
114
 
115
  df = data.copy()
116
 
117
+ # 指標只取最後 12 筆即可
118
  n = min(12, len(df))
119
 
120
+ indicators = {}
121
+
122
  # RSI
123
  rsi_series = RSIIndicator(df['Close'], window=14).rsi().iloc[-n:]
124
  indicators["RSI"] = {
 
160
  except Exception as e:
161
  return f"Error fetching price data: {str(e)}"
162
 
 
163
  def get_financial_news(ticker: str) -> Union[Dict, str]:
164
  """Fetches the latest financial news related to a given ticker."""
165
  try:
 
181
  except Exception as e:
182
  return f"Error fetching news: {str(e)}"
183
 
 
184
  def get_financial_metrics(ticker: str) -> Union[Dict, str]:
185
  """Fetches key financial ratios for a given ticker."""
186
  try:
 
195
  except Exception as e:
196
  return f"Error fetching ratios: {str(e)}"
197
 
 
198
  def analyze_stock(api_key: str, ticker: str, period: str) -> str:
199
  """
200
  根據輸入的 LLM API key、股票代號與時間區間,抓取各項資料後,
 
207
  openai_api_key=api_key,
208
  temperature=0
209
  )
210
+
211
  # 取得資料
212
  price_data = get_stock_prices(ticker, period)
213
  metrics = get_financial_metrics(ticker)
214
  news = get_financial_news(ticker)
215
 
216
+ # 組合 Prompt
217
  prompt = FUNDAMENTAL_ANALYST_PROMPT.replace("{company}", ticker)
218
  user_question = "Should I buy this stock?"
219
  analysis_prompt = f"""
 
230
 
231
  {prompt}
232
  """
233
+
234
  # 呼叫 LLM 生成最終分析報告
235
  response = llm.invoke(analysis_prompt)
236
  return response.content
237
+
238
  except Exception as e:
239
  return f"分析過程中發生錯誤: {str(e)}\n{traceback.format_exc()}"
240