Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -4,8 +4,7 @@ import requests
|
|
4 |
import pytz
|
5 |
import yaml
|
6 |
from tools.final_answer import FinalAnswerTool
|
7 |
-
import yfinance as yf
|
8 |
-
from typing import Any, Optional
|
9 |
|
10 |
from Gradio_UI import GradioUI
|
11 |
|
@@ -40,46 +39,94 @@ final_answer = FinalAnswerTool()
|
|
40 |
|
41 |
|
42 |
@tool
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
"""
|
45 |
-
Get the latest stock price for the given ticker symbol
|
46 |
-
the price change over the last 5 days and
|
47 |
-
|
48 |
Args:
|
49 |
ticker_symbol: The stock ticker symbol to fetch the price for.
|
|
|
50 |
Returns:
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
54 |
"""
|
55 |
try:
|
56 |
-
#
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
"price": round(current_price, 2),
|
73 |
"price_change": round(price_change, 2),
|
74 |
-
"price_change_percent": round(price_change_percent, 2)
|
75 |
}
|
76 |
-
return price
|
77 |
|
78 |
-
except
|
79 |
-
logger.error(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
except Exception as e:
|
81 |
-
logger.error(f"Unexpected error fetching price for {ticker_symbol}: {
|
82 |
-
|
83 |
|
84 |
final_answer = FinalAnswerTool()
|
85 |
|
|
|
4 |
import pytz
|
5 |
import yaml
|
6 |
from tools.final_answer import FinalAnswerTool
|
7 |
+
#import yfinance as yf
|
|
|
8 |
|
9 |
from Gradio_UI import GradioUI
|
10 |
|
|
|
39 |
|
40 |
|
41 |
@tool
|
42 |
+
import requests
|
43 |
+
import logging
|
44 |
+
from typing import Optional, Dict, Any
|
45 |
+
|
46 |
+
logger = logging.getLogger(__name__)
|
47 |
+
logger.setLevel(logging.DEBUG)
|
48 |
+
|
49 |
+
|
50 |
+
def get_current_stock_price(ticker_symbol: str) -> Optional[Dict[str, Any]]:
|
51 |
"""
|
52 |
+
Get the latest stock price for the given ticker symbol by querying Yahoo Finance directly,
|
53 |
+
then calculate the price change over the last 5 days (percentage and absolute).
|
54 |
+
|
55 |
Args:
|
56 |
ticker_symbol: The stock ticker symbol to fetch the price for.
|
57 |
+
|
58 |
Returns:
|
59 |
+
A dictionary containing:
|
60 |
+
- "price" : current closing price (float)
|
61 |
+
- "price_change" : absolute change over 5 days (float)
|
62 |
+
- "price_change_percent" : percent change over 5 days (float)
|
63 |
+
|
64 |
+
If there's an error or no data is available, returns a dict with an "error" key, e.g.
|
65 |
+
{"error": "No historical data available for TSLA"}
|
66 |
+
Or returns None for unexpected issues.
|
67 |
"""
|
68 |
try:
|
69 |
+
# Build the Yahoo Finance “chart” API URL for the last 5 calendar days.
|
70 |
+
url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker_symbol}"
|
71 |
+
params = {
|
72 |
+
"range": "5d",
|
73 |
+
"interval": "1d",
|
74 |
+
# We only need daily closes, so the default interval=1d is fine.
|
75 |
+
}
|
76 |
+
|
77 |
+
resp = requests.get(url, params=params, timeout=10)
|
78 |
+
resp.raise_for_status()
|
79 |
+
data = resp.json()
|
80 |
+
|
81 |
+
# Drill into the JSON structure:
|
82 |
+
# data["chart"]["result"][0]["indicators"]["quote"][0]["close"]
|
83 |
+
chart = data.get("chart", {})
|
84 |
+
if not chart or chart.get("error"):
|
85 |
+
return {"error": f"Yahoo Finance returned an error for {ticker_symbol}."}
|
86 |
+
|
87 |
+
result_list = chart.get("result", [])
|
88 |
+
if not result_list:
|
89 |
+
return {"error": f"No chart result found for {ticker_symbol}."}
|
90 |
+
|
91 |
+
quote_section = result_list[0].get("indicators", {}).get("quote", [])
|
92 |
+
if not quote_section:
|
93 |
+
return {"error": f"No quote information in chart for {ticker_symbol}."}
|
94 |
+
|
95 |
+
closes = quote_section[0].get("close", [])
|
96 |
+
# The “close” array may contain nulls if the market was closed on a given day.
|
97 |
+
# Filter out any None values:
|
98 |
+
closes = [c for c in closes if (c is not None)]
|
99 |
+
|
100 |
+
if len(closes) < 2:
|
101 |
+
return {"error": f"Not enough close‐price data (need at least 2 days) for {ticker_symbol}."}
|
102 |
+
|
103 |
+
# The “closes” list is chronological; last element is the most recent closing price:
|
104 |
+
first_price = closes[0]
|
105 |
+
current_price = closes[-1]
|
106 |
+
|
107 |
+
# Calculate changes:
|
108 |
+
price_change = current_price - first_price
|
109 |
+
price_change_percent = (price_change / first_price) * 100 if first_price != 0 else 0.0
|
110 |
+
|
111 |
+
# Round everything to two decimals:
|
112 |
+
return {
|
113 |
"price": round(current_price, 2),
|
114 |
"price_change": round(price_change, 2),
|
115 |
+
"price_change_percent": round(price_change_percent, 2),
|
116 |
}
|
|
|
117 |
|
118 |
+
except requests.HTTPError as http_err:
|
119 |
+
logger.error(f"HTTP error while fetching {ticker_symbol} data: {http_err}")
|
120 |
+
return {"error": f"HTTPError fetching data for {ticker_symbol}: {http_err}"}
|
121 |
+
except requests.RequestException as req_err:
|
122 |
+
logger.error(f"Request exception for {ticker_symbol}: {req_err}")
|
123 |
+
return {"error": f"RequestException fetching data for {ticker_symbol}: {req_err}"}
|
124 |
+
except (KeyError, IndexError, ValueError) as parse_err:
|
125 |
+
logger.error(f"Parsing error for {ticker_symbol}: {parse_err}")
|
126 |
+
return {"error": f"Parsing error for {ticker_symbol}: {parse_err}"}
|
127 |
except Exception as e:
|
128 |
+
logger.error(f"Unexpected error fetching price for {ticker_symbol}: {e}")
|
129 |
+
return None
|
130 |
|
131 |
final_answer = FinalAnswerTool()
|
132 |
|