jashdoshi77 commited on
Commit
32a996a
Β·
1 Parent(s): 624c105

fix: company info from chart API meta, multi-market sentiment, factor analysis

Browse files
backend/app/services/data_ingestion/yahoo.py CHANGED
@@ -126,43 +126,62 @@ def _direct_fetch_history(ticker: str, period: str = "1y", interval: str = "1d",
126
 
127
 
128
  def _direct_fetch_info(ticker: str) -> dict:
129
- """Fetch quote info directly from Yahoo's quote API via curl_cffi."""
 
 
 
 
130
  if not _USE_CURL or not _curl_session:
131
  return _yfinance_fetch_info(ticker)
132
 
133
  try:
134
- resp = _curl_session.get(_QUOTE_URL, params={"symbols": ticker}, timeout=10)
 
 
 
 
 
 
 
 
135
  if resp.status_code != 200:
136
- logger.debug("Yahoo quote API returned %d for %s", resp.status_code, ticker)
137
  return {}
138
 
139
  data = resp.json()
140
- results = data.get("quoteResponse", {}).get("result", [])
141
- if not results:
142
  return {}
143
 
144
- q = results[0]
 
 
 
 
 
145
  return {
146
- "longName": q.get("longName"),
147
- "shortName": q.get("shortName"),
148
- "currency": q.get("currency", "USD"),
149
- "exchange": q.get("exchange"),
150
- "sector": q.get("sector"),
151
- "industry": q.get("industry"),
152
- "marketCap": q.get("marketCap"),
153
- "trailingPE": q.get("trailingPE"),
154
- "forwardPE": q.get("forwardPE"),
155
- "priceToBook": q.get("priceToBook"),
156
- "dividendYield": q.get("dividendYield"),
157
- "trailingEps": q.get("epsTrailingTwelveMonths"),
158
- "fiftyTwoWeekHigh": q.get("fiftyTwoWeekHigh"),
159
- "fiftyTwoWeekLow": q.get("fiftyTwoWeekLow"),
160
- "averageVolume": q.get("averageDailyVolume3Month"),
161
- "beta": q.get("beta"),
162
- "country": q.get("region"),
 
 
163
  }
164
  except Exception as e:
165
- logger.debug("Direct quote API failed for %s: %s", ticker, e)
166
  return {}
167
 
168
 
 
126
 
127
 
128
  def _direct_fetch_info(ticker: str) -> dict:
129
+ """Fetch quote info from Yahoo's chart API meta field via curl_cffi.
130
+
131
+ The v7/finance/quote endpoint is blocked on cloud IPs, but the v8/finance/chart
132
+ endpoint works and includes a 'meta' field with useful company data.
133
+ """
134
  if not _USE_CURL or not _curl_session:
135
  return _yfinance_fetch_info(ticker)
136
 
137
  try:
138
+ # Use the chart API which is confirmed working β€” extract from meta
139
+ url = _CHART_URL.format(ticker=ticker)
140
+ params = {
141
+ "period1": str(int(time.time()) - 86400 * 5),
142
+ "period2": str(int(time.time())),
143
+ "interval": "1d",
144
+ "includeAdjustedClose": "true",
145
+ }
146
+ resp = _curl_session.get(url, params=params, timeout=10)
147
  if resp.status_code != 200:
148
+ logger.debug("Yahoo chart meta API returned %d for %s", resp.status_code, ticker)
149
  return {}
150
 
151
  data = resp.json()
152
+ result = data.get("chart", {}).get("result")
153
+ if not result:
154
  return {}
155
 
156
+ meta = result[0].get("meta", {})
157
+
158
+ # Calculate basic metrics from price data if available
159
+ prev_close = meta.get("chartPreviousClose") or meta.get("previousClose")
160
+ reg_price = meta.get("regularMarketPrice")
161
+
162
  return {
163
+ "longName": meta.get("longName"),
164
+ "shortName": meta.get("shortName") or meta.get("symbol"),
165
+ "currency": meta.get("currency", "USD"),
166
+ "exchange": meta.get("exchangeName") or meta.get("exchange"),
167
+ "sector": None, # Not available from chart meta
168
+ "industry": None,
169
+ "marketCap": None,
170
+ "trailingPE": None,
171
+ "forwardPE": None,
172
+ "priceToBook": None,
173
+ "dividendYield": None,
174
+ "trailingEps": None,
175
+ "fiftyTwoWeekHigh": meta.get("fiftyTwoWeekHigh"),
176
+ "fiftyTwoWeekLow": meta.get("fiftyTwoWeekLow"),
177
+ "averageVolume": None,
178
+ "beta": None,
179
+ "country": None,
180
+ "regularMarketPrice": reg_price,
181
+ "previousClose": prev_close,
182
  }
183
  except Exception as e:
184
+ logger.debug("Direct chart meta fetch failed for %s: %s", ticker, e)
185
  return {}
186
 
187
 
backend/app/services/sentiment/engine.py CHANGED
@@ -143,18 +143,24 @@ async def fetch_multi_sentiment(tickers: List[str]) -> List[Dict[str, Any]]:
143
 
144
  # ── Trending / Market Mood ───────────────────────────────────────────────
145
  MARKET_TICKERS = [
 
146
  "SPY", "QQQ", "AAPL", "MSFT", "GOOGL", "AMZN", "NVDA", "TSLA",
147
- "META", "BRK-B", "JPM", "V", "UNH", "MA", "HD",
 
 
 
 
 
148
  ]
149
 
150
  async def get_market_mood() -> Dict[str, Any]:
151
- """Get overall market sentiment from major tickers."""
152
  cache_key = "sentiment:market_mood"
153
  cached = await cache_get(cache_key)
154
  if cached:
155
  return cached
156
 
157
- results = await fetch_multi_sentiment(MARKET_TICKERS[:8])
158
 
159
  if not results:
160
  return {"mood": "neutral", "score": 0, "tickers_analyzed": 0}
 
143
 
144
  # ── Trending / Market Mood ───────────────────────────────────────────────
145
  MARKET_TICKERS = [
146
+ # US
147
  "SPY", "QQQ", "AAPL", "MSFT", "GOOGL", "AMZN", "NVDA", "TSLA",
148
+ # India
149
+ "RELIANCE.NS", "TCS.NS", "HDFCBANK.NS", "INFY.NS",
150
+ # Europe
151
+ "ASML", "SAP", "SHEL", "AZN",
152
+ # Asia
153
+ "9988.HK", "7203.T",
154
  ]
155
 
156
  async def get_market_mood() -> Dict[str, Any]:
157
+ """Get overall market sentiment from major tickers across all markets."""
158
  cache_key = "sentiment:market_mood"
159
  cached = await cache_get(cache_key)
160
  if cached:
161
  return cached
162
 
163
+ results = await fetch_multi_sentiment(MARKET_TICKERS[:10])
164
 
165
  if not results:
166
  return {"mood": "neutral", "score": 0, "tickers_analyzed": 0}