Create get_stock_news.py
Browse files- get_stock_news.py +80 -0
get_stock_news.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any, Optional
|
| 2 |
+
from smolagents.tools import Tool
|
| 3 |
+
|
| 4 |
+
from datetime import datetime, timedelta
|
| 5 |
+
import pytz
|
| 6 |
+
import yfinance as yf
|
| 7 |
+
|
| 8 |
+
class StockNewsTool(Tool):
|
| 9 |
+
name = "stock_news_items"
|
| 10 |
+
description="Searches Yahoo Finance for stock news items and quotes related to the stock named in the query, then returns a string of metadata about news items"
|
| 11 |
+
inputs= {'query': {'type': 'string', 'description': 'The stock name or symbol to look up data for.'}}
|
| 12 |
+
output_type = "string"
|
| 13 |
+
|
| 14 |
+
def date_from_utime(self, utime:str)->str:
|
| 15 |
+
ts = int(utime)
|
| 16 |
+
dt = datetime.utcfromtimestamp(ts)
|
| 17 |
+
eastern = pytz.timezone('US/Eastern')
|
| 18 |
+
return dt.astimezone(eastern).strftime('%Y-%m-%d')
|
| 19 |
+
|
| 20 |
+
def etz_now(self):
|
| 21 |
+
eastern = pytz.timezone('US/Eastern')
|
| 22 |
+
ltime = datetime.now(eastern)
|
| 23 |
+
return ltime
|
| 24 |
+
|
| 25 |
+
def get_last_closing(self, symbol, offset=0, timeout=10):
|
| 26 |
+
try:
|
| 27 |
+
etime = self.etz_now()
|
| 28 |
+
if etime.hour >= 16:
|
| 29 |
+
etime = etime + timedelta(days=1)
|
| 30 |
+
if offset > 0:
|
| 31 |
+
etime = etime - timedelta(weeks=offset)
|
| 32 |
+
five_days_ago = etime - timedelta(days=6)
|
| 33 |
+
end = etime.strftime('%Y-%m-%d')
|
| 34 |
+
start = five_days_ago.strftime('%Y-%m-%d')
|
| 35 |
+
df = yf.download(symbol,
|
| 36 |
+
start = start,
|
| 37 |
+
end = end,
|
| 38 |
+
progress = False,
|
| 39 |
+
timeout=timeout,
|
| 40 |
+
)
|
| 41 |
+
# print(df)
|
| 42 |
+
closing_date = 'unknown'
|
| 43 |
+
data_top = df.tail(1)
|
| 44 |
+
for row in data_top.index:
|
| 45 |
+
closing_date = row.strftime('%Y-%m-%d')
|
| 46 |
+
# print(closing_date)
|
| 47 |
+
return (df.iat[-1,0], closing_date)
|
| 48 |
+
except:
|
| 49 |
+
return ("unknown", "0000-00-00")
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# class StockNewsTool(Tool):
|
| 53 |
+
|
| 54 |
+
def forward(self, query:str)->str:
|
| 55 |
+
fuzzy = True
|
| 56 |
+
last_closing = 'unknown'
|
| 57 |
+
closing_date = 'n/a'
|
| 58 |
+
try:
|
| 59 |
+
yf_search = yf.Search(query, news_count= 5, max_results = 3, enable_fuzzy_query=fuzzy)
|
| 60 |
+
news = yf_search.news
|
| 61 |
+
quotes = yf_search.quotes
|
| 62 |
+
except:
|
| 63 |
+
return f'No results for search term {query}\n'
|
| 64 |
+
rv = 'News:\n'
|
| 65 |
+
for item in news:
|
| 66 |
+
rv += f'Title: {item["title"]}\n'
|
| 67 |
+
rv += f'Publisher: {item["publisher"]}\n'
|
| 68 |
+
rv += f'Date published: {self.date_from_utime(item["providerPublishTime"])}\n'
|
| 69 |
+
rv += f'Link: [URL]({item["link"]})\n\n'
|
| 70 |
+
for quote in quotes:
|
| 71 |
+
exchange = quote['exchange']
|
| 72 |
+
symbol = quote['symbol']
|
| 73 |
+
if exchange == 'NYQ' or exchange == 'NYS':
|
| 74 |
+
(last_closing, closing_date) = self.get_last_closing(symbol)
|
| 75 |
+
break
|
| 76 |
+
rv += f'\n\nPrice quote at last closing on {closing_date} is {last_closing}\n'
|
| 77 |
+
return rv
|
| 78 |
+
|
| 79 |
+
def __init__(self, *args, **kwargs):
|
| 80 |
+
self.is_initialized = False
|