Toymakerftw
commited on
Commit
·
f4079e2
1
Parent(s):
3994932
test
Browse files
app.py
CHANGED
@@ -125,47 +125,46 @@ def resolve_ticker_symbol(query: str) -> str:
|
|
125 |
Convert company names/partial symbols to valid Yahoo Finance tickers.
|
126 |
Example: "Kalyan Jewellers" → "KALYANKJIL.NS"
|
127 |
"""
|
128 |
-
exchanges = ["NSE", "BSE"]
|
129 |
-
exchange_suffixes = {
|
130 |
-
"NSE": ".NS",
|
131 |
-
"BSE": ".BO",
|
132 |
-
}
|
133 |
-
|
134 |
url = "https://query2.finance.yahoo.com/v1/finance/search"
|
135 |
headers = {"User-Agent": "Mozilla/5.0"} # Avoid blocking
|
136 |
-
params = {"q": query, "quotesCount": 5, "country": "India"}
|
137 |
|
138 |
response = requests.get(url, headers=headers, params=params)
|
139 |
data = response.json()
|
140 |
|
141 |
-
if data.get("quotes"):
|
142 |
-
# Extract symbols and names
|
143 |
-
tickers = [quote["symbol"] for quote in data["quotes"]]
|
144 |
-
names = [quote["longname"] or quote["shortname"] for quote in data["quotes"]]
|
145 |
-
|
146 |
-
# Fuzzy match the query with company names
|
147 |
-
best_match = process.extractOne(query, names)
|
148 |
-
if best_match:
|
149 |
-
index = names.index(best_match[0])
|
150 |
-
resolved_ticker = tickers[index]
|
151 |
-
|
152 |
-
# Ensure the exchange suffix is only added if not already present
|
153 |
-
for exchange in exchanges:
|
154 |
-
if not resolved_ticker.endswith(exchange_suffixes[exchange]):
|
155 |
-
resolved_ticker += exchange_suffixes[exchange]
|
156 |
-
break
|
157 |
-
return resolved_ticker
|
158 |
-
else:
|
159 |
-
# Default to first result
|
160 |
-
resolved_ticker = tickers[0]
|
161 |
-
for exchange in exchanges:
|
162 |
-
if not resolved_ticker.endswith(exchange_suffixes[exchange]):
|
163 |
-
resolved_ticker += exchange_suffixes[exchange]
|
164 |
-
break
|
165 |
-
return resolved_ticker
|
166 |
-
else:
|
167 |
raise ValueError(f"No ticker found for: {query}")
|
168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
def fetch_articles(query):
|
170 |
try:
|
171 |
logging.info(f"Fetching articles for query: '{query}'")
|
@@ -190,53 +189,41 @@ def analyze_article_sentiment(article):
|
|
190 |
return article
|
191 |
|
192 |
def fetch_yfinance_data(ticker):
|
193 |
-
"""Enhanced Yahoo Finance data fetching with technical analysis
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
"
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
current_price
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
return {
|
225 |
-
'current_price': current_price,
|
226 |
-
'price_change': price_change,
|
227 |
-
'percent_change': percent_change,
|
228 |
-
'chart': chart,
|
229 |
-
'technical_indicators': ta_data,
|
230 |
-
'fundamentals': stock.info
|
231 |
-
}
|
232 |
-
|
233 |
-
except Exception as e:
|
234 |
-
logging.error(f"Error fetching Yahoo Finance data for {ticker}{exchange_suffixes[exchange]}: {str(e)}")
|
235 |
-
continue
|
236 |
-
|
237 |
-
logging.error(f"Failed to fetch data for {ticker} from all exchanges")
|
238 |
-
return {"error": f"Failed to fetch data for {ticker} from all exchanges"}
|
239 |
|
|
|
|
|
|
|
|
|
240 |
def time_weighted_sentiment(articles):
|
241 |
"""Apply time-based weighting to sentiment scores"""
|
242 |
now = datetime.now()
|
|
|
125 |
Convert company names/partial symbols to valid Yahoo Finance tickers.
|
126 |
Example: "Kalyan Jewellers" → "KALYANKJIL.NS"
|
127 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
url = "https://query2.finance.yahoo.com/v1/finance/search"
|
129 |
headers = {"User-Agent": "Mozilla/5.0"} # Avoid blocking
|
130 |
+
params = {"q": query, "quotesCount": 5, "country": "India"}
|
131 |
|
132 |
response = requests.get(url, headers=headers, params=params)
|
133 |
data = response.json()
|
134 |
|
135 |
+
if not data.get("quotes"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
raise ValueError(f"No ticker found for: {query}")
|
137 |
|
138 |
+
# Extract quotes data
|
139 |
+
quotes = data["quotes"]
|
140 |
+
tickers = [quote["symbol"] for quote in quotes]
|
141 |
+
names = [quote.get("longname") or quote.get("shortname", "") for quote in quotes]
|
142 |
+
|
143 |
+
# Fuzzy match the query with company names
|
144 |
+
best_match, score = process.extractOne(query, names)
|
145 |
+
if not best_match:
|
146 |
+
raise ValueError(f"No matching ticker found for: {query}")
|
147 |
+
|
148 |
+
index = names.index(best_match)
|
149 |
+
best_quote = quotes[index]
|
150 |
+
resolved_ticker = best_quote["symbol"]
|
151 |
+
exchange_code = best_quote.get("exchange", "").upper()
|
152 |
+
|
153 |
+
# Map exchange codes to suffixes
|
154 |
+
exchange_suffix_map = {
|
155 |
+
"NSI": ".NS", # NSE
|
156 |
+
"BOM": ".BO", # BSE
|
157 |
+
"BSE": ".BO",
|
158 |
+
"NSE": ".NS",
|
159 |
+
}
|
160 |
+
suffix = exchange_suffix_map.get(exchange_code, ".NS") # Default to NSE
|
161 |
+
|
162 |
+
# Append suffix only if not already present
|
163 |
+
if not resolved_ticker.endswith(suffix):
|
164 |
+
resolved_ticker += suffix
|
165 |
+
|
166 |
+
return resolved_ticker
|
167 |
+
|
168 |
def fetch_articles(query):
|
169 |
try:
|
170 |
logging.info(f"Fetching articles for query: '{query}'")
|
|
|
189 |
return article
|
190 |
|
191 |
def fetch_yfinance_data(ticker):
|
192 |
+
"""Enhanced Yahoo Finance data fetching with technical analysis"""
|
193 |
+
try:
|
194 |
+
logging.info(f"Fetching Yahoo Finance data for: {ticker}")
|
195 |
+
stock = yf.Ticker(ticker)
|
196 |
+
history = stock.history(period="1y", interval="1d")
|
197 |
+
|
198 |
+
if history.empty:
|
199 |
+
logging.error(f"No data found for {ticker}")
|
200 |
+
return {"error": f"No data found for {ticker}"}
|
201 |
+
|
202 |
+
# Calculate technical indicators
|
203 |
+
ta_data = calculate_technical_indicators(history)
|
204 |
+
|
205 |
+
# Current price data
|
206 |
+
current_price = history['Close'].iloc[-1]
|
207 |
+
prev_close = history['Close'].iloc[-2] if len(history) > 1 else 0
|
208 |
+
price_change = current_price - prev_close
|
209 |
+
percent_change = (price_change / prev_close) * 100 if prev_close != 0 else 0
|
210 |
+
|
211 |
+
# Generate price chart
|
212 |
+
chart = generate_price_chart(history[-120:]) # Last 120 days
|
213 |
+
|
214 |
+
return {
|
215 |
+
'current_price': current_price,
|
216 |
+
'price_change': price_change,
|
217 |
+
'percent_change': percent_change,
|
218 |
+
'chart': chart,
|
219 |
+
'technical_indicators': ta_data,
|
220 |
+
'fundamentals': stock.info
|
221 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
|
223 |
+
except Exception as e:
|
224 |
+
logging.error(f"Error fetching Yahoo Finance data for {ticker}: {str(e)}")
|
225 |
+
return {"error": f"Failed to fetch data for {ticker}: {str(e)}"}
|
226 |
+
|
227 |
def time_weighted_sentiment(articles):
|
228 |
"""Apply time-based weighting to sentiment scores"""
|
229 |
now = datetime.now()
|