Spaces:
Sleeping
Sleeping
| import os | |
| from langchain_community.tools import DuckDuckGoSearchResults, RedditSearchRun | |
| from langchain_community.utilities.reddit_search import RedditSearchAPIWrapper | |
| from langchain_community.tools.reddit_search.tool import RedditSearchSchema | |
| from langchain_community.utilities import DuckDuckGoSearchAPIWrapper | |
| from langchain.tools import Tool , tool | |
| from pydantic import BaseModel | |
| from time import sleep | |
| import re | |
| groq_api= os.getenv('GROQ_API_KEY') | |
| Onews_api = os.getenv('NEWS_API') | |
| from newsdataapi import NewsDataApiClient | |
| import yfinance as yf | |
| import pandas as pd | |
| class RedditInput(BaseModel): | |
| query: str | |
| sort: str = "new" | |
| time_filter: str = "week" | |
| subreddit: str = "stocks" | |
| limit: str = "5" | |
| class WebSearchInput(BaseModel): | |
| query: str | |
| class StanderdNewsSearchProtocol(BaseModel): | |
| topic: str | |
| class StockFundamentals(BaseModel): | |
| company_name: str | |
| def reddit_search_tool(query: str, sort: str, time_filter: str, subreddit: str, limit: str) -> str: | |
| """ | |
| Search Reddit for a given query. Provide query and optionally sort, time_filter, subreddit, and limit. | |
| """ | |
| sleep(1) | |
| try: | |
| search = RedditSearchRun(api_wrapper=RedditSearchAPIWrapper()) | |
| search_params = RedditSearchSchema( | |
| query=query, | |
| sort=sort, | |
| time_filter=time_filter, | |
| subreddit=subreddit, | |
| limit=limit | |
| ) | |
| result = search.run(tool_input=search_params.model_dump()) | |
| except Exception as e: | |
| result = "There was an error in ruuning the tool. try again or skip the tool" | |
| sleep(1) | |
| return result | |
| def resolve_ticker(company_name: str) -> str: | |
| """ | |
| Resolves the correct stock ticker for a given company name using web search. | |
| Example: 'Apple' -> 'AAPL', 'Tesla' -> 'TSLA' | |
| """ | |
| try: | |
| wrapper = DuckDuckGoSearchAPIWrapper(max_results=1) | |
| search = DuckDuckGoSearchResults(api_wrapper=wrapper) | |
| query = f"{company_name} stock ticker site:finance.yahoo.com" | |
| results = search.invoke(query) | |
| match = re.search(r"finance\.yahoo\.com/quote/([^/?]+)", results) | |
| if match: | |
| return match.group(1).strip() | |
| else : return f"Not able to find the correct stocks name for {company_name}. Trying again..." | |
| except : | |
| return "Not able to run the tool successfuly." | |
| def fetch_stock_summary(company_name: str) -> str: | |
| """ | |
| Fetches a comprehensive stock summary including technical indicators, daily stats for the last 4 days, | |
| 1-month summary, and quarterly trends. | |
| Args: company_name: Full name of the company. | |
| """ | |
| sleep(1) | |
| try: | |
| ticker = resolve_ticker(company_name=company_name) | |
| stock = yf.Ticker(ticker) | |
| info = stock.info | |
| current_price = info.get("currentPrice", "N/A") | |
| market_cap = info.get("marketCap", "N/A") | |
| pe_ratio = info.get("trailingPE", "N/A") | |
| sector = info.get("sector", "N/A") | |
| industry = info.get("industry", "N/A") | |
| summary = info.get("longBusinessSummary", "N/A") | |
| last_4_days = stock.history(period="5d") | |
| last_4 = last_4_days.tail(4).copy() | |
| daily_info = "\nLast 4 Days:\n" | |
| for date, row in last_4.iterrows(): | |
| change = ((row['Close'] - row['Open']) / row['Open']) * 100 | |
| daily_info += f"- {date.date()}: Close ${row['Close']:.2f}, Vol: {int(row['Volume'])}, Change: {change:+.2f}%\n" | |
| month_df = stock.history(period="1mo") | |
| avg_close = month_df['Close'].mean() | |
| high_close = month_df['Close'].max() | |
| low_close = month_df['Close'].min() | |
| total_volume = month_df['Volume'].sum() | |
| month_summary = ( | |
| f"\n1-Month Summary:\n" | |
| f"- Avg Close: ${avg_close:.2f}\n" | |
| f"- High: ${high_close:.2f} | Low: ${low_close:.2f}\n" | |
| f"- Total Volume: {int(total_volume)}" | |
| ) | |
| quarter_df = stock.history(period="3mo") | |
| start_price = quarter_df['Close'].iloc[0] | |
| end_price = quarter_df['Close'].iloc[-1] | |
| pct_change = ((end_price - start_price) / start_price) * 100 | |
| high_q = quarter_df['Close'].max() | |
| low_q = quarter_df['Close'].min() | |
| avg_vol_q = quarter_df['Volume'].mean() | |
| quarter_summary = ( | |
| f"\nQuarterly Summary (3mo):\n" | |
| f"- Start Price: ${start_price:.2f} | End Price: ${end_price:.2f}\n" | |
| f"- % Change: {pct_change:.2f}%\n" | |
| f"- High: ${high_q:.2f} | Low: ${low_q:.2f}\n" | |
| f"- Avg Volume: {int(avg_vol_q)}" | |
| ) | |
| df = month_df.copy() | |
| df['SMA_10'] = df['Close'].rolling(10).mean() | |
| df['EMA_10'] = df['Close'].ewm(span=10).mean() | |
| delta = df['Close'].diff() | |
| gain = delta.where(delta > 0, 0.0) | |
| loss = -delta.where(delta < 0, 0.0) | |
| avg_gain = gain.rolling(window=14).mean() | |
| avg_loss = loss.rolling(window=14).mean() | |
| rs = avg_gain / avg_loss | |
| df['RSI_14'] = 100 - (100 / (1 + rs)) | |
| ema_12 = df['Close'].ewm(span=12, adjust=False).mean() | |
| ema_26 = df['Close'].ewm(span=26, adjust=False).mean() | |
| df['MACD'] = ema_12 - ema_26 | |
| df['MACD_Signal'] = df['MACD'].ewm(span=9, adjust=False).mean() | |
| df['BB_Middle'] = df['Close'].rolling(20).mean() | |
| df['BB_Upper'] = df['BB_Middle'] + 2 * df['Close'].rolling(20).std() | |
| df['BB_Lower'] = df['BB_Middle'] - 2 * df['Close'].rolling(20).std() | |
| df['ATR_14'] = df[['High', 'Low', 'Close']].apply(lambda x: max(x['High'] - x['Low'], abs(x['High'] - x['Close']), abs(x['Low'] - x['Close'])), axis=1).rolling(14).mean() | |
| df['Volatility'] = df['Close'].pct_change().rolling(14).std() | |
| latest = df.iloc[-1] | |
| indicators = ( | |
| f"\nTechnical Indicators:\n" | |
| f"- SMA(10): {latest['SMA_10']:.2f} | EMA(10): {latest['EMA_10']:.2f}\n" | |
| f"- RSI(14): {latest['RSI_14']:.2f}\n" | |
| f"- MACD: {latest['MACD']:.2f} | Signal: {latest['MACD_Signal']:.2f}\n" | |
| f"- Bollinger Bands: Upper={latest['BB_Upper']:.2f}, Lower={latest['BB_Lower']:.2f}\n" | |
| f"- ATR(14): {latest['ATR_14']:.2f}\n" | |
| f"- Volatility (14-day): {latest['Volatility']:.4f}" | |
| ) | |
| output = ( | |
| f"{ticker.upper()} Summary:\n" | |
| f"- Current Price: ${current_price}\n" | |
| f"- Market Cap: {market_cap}\n" | |
| f"- Sector: {sector} | Industry: {industry}\n" | |
| f"- PE Ratio: {pe_ratio}\n" | |
| f"{daily_info}" | |
| f"{month_summary}" | |
| f"{quarter_summary}" | |
| f"{indicators}" | |
| f"\n\nCompany Overview:\n{summary}" | |
| ) | |
| return output | |
| except Exception as e: | |
| return f"Error fetching stock data for {company_name}: {str(e)}" | |
| def web_search(query: str) -> str: | |
| """ | |
| This function allows to search anything on internet. A big query with more details will only give a high quality result. | |
| Args: query: Search query. | |
| """ | |
| sleep(1) | |
| try: | |
| wrapper = DuckDuckGoSearchAPIWrapper(max_results=2) | |
| search = DuckDuckGoSearchResults(api_wrapper=wrapper) | |
| return search.invoke(query) | |
| except: | |
| return "Error in running the tool." | |
| def tech_news(topic:str) -> str: | |
| """ | |
| Fetches recent UK-based technology news headlines and descriptions from NewsData.io | |
| with a focus on the given topic (matched in the article title). | |
| Args: | |
| topic (str): The keyword to search for in technology news article titles. | |
| Returns: | |
| str: A concatenated string of news summaries with topic-specific tech news. | |
| """ | |
| sleep(1) | |
| try: | |
| client = NewsDataApiClient(apikey=Onews_api, | |
| debug=True, | |
| folder_path="./news_output") | |
| content = client.latest_api(category="technology", language="en", country="gb", size=3,qInTitle=topic) | |
| content = content['results'] | |
| tech_news= "" | |
| for i, j in enumerate(content): | |
| full_news = f"tech_news {i+1}: "+ j["description"] | |
| tech_news += full_news | |
| return tech_news | |
| except: | |
| return "There was an error. Can't run the tool" | |
| def politics_news(topic:str) -> str: | |
| """ | |
| Fetches recent UK-based politics news headlines and descriptions from NewsData.io | |
| with a focus on the given topic (matched in the article title). | |
| Args: | |
| topic (str): The keyword to search for in politics news article titles. | |
| Returns: | |
| str: A concatenated string of news summaries with topic-specific political news. | |
| """ | |
| sleep(1) | |
| try: | |
| client = NewsDataApiClient(apikey=Onews_api, | |
| debug=True, | |
| folder_path="./news_output") | |
| content = client.latest_api(category="politics", language="en", country="gb", size=3,qInTitle=topic) | |
| content = content['results'] | |
| p_news= "" | |
| for i, j in enumerate(content): | |
| full_news = f"politics_news {i+1}: "+ j["description"] | |
| p_news += full_news | |
| return p_news | |
| except: | |
| return "There was an error. Can't run the tool" | |
| def business_news(topic:str) -> str: | |
| """ | |
| Fetches recent UK-based business news headlines and descriptions from NewsData.io | |
| with a focus on the given topic (matched in the article title). | |
| Args: | |
| topic (str): The keyword to search for in business news article titles. | |
| Returns: | |
| str: A concatenated string of news summaries with topic-specific business news. | |
| """ | |
| sleep(1) | |
| try: | |
| client = NewsDataApiClient(apikey=Onews_api, | |
| debug=True, | |
| folder_path="./news_output") | |
| content = client.latest_api(category="business", language="en", country="gb", size=3,qInTitle=topic) | |
| content = content['results'] | |
| b_news= "" | |
| for i, j in enumerate(content): | |
| full_news = f"business_news {i+1}: "+ j["description"] | |
| b_news += full_news | |
| return b_news | |
| except: | |
| return "There was an error. Can't run the tool" | |
| def world_news(topic:str) -> str: | |
| """ | |
| Fetches recent world news headlines related to UK and descriptions from NewsData.io | |
| with a focus on the given topic (matched in the article title). | |
| Args: | |
| topic (str): The keyword to search for in World news article titles. | |
| Returns: | |
| str: A concatenated string of news summaries with topic-specific world news. | |
| """ | |
| sleep(1) | |
| try: | |
| client = NewsDataApiClient(apikey=Onews_api, | |
| debug=True, | |
| folder_path="./news_output") | |
| content = client.latest_api(category="world", language="en", country="gb", size=3,qInTitle=topic) | |
| content = content['results'] | |
| w_news= "" | |
| for i, j in enumerate(content): | |
| full_news = f"world_news {i+1}: "+ j["description"] | |
| w_news += full_news | |
| return w_news | |
| except: | |
| return "There was an error. Can't run the tool" | |
| stock_data_tool = Tool( | |
| name="Stock Market Data", | |
| func=fetch_stock_summary, | |
| description=( | |
| "Use this tool to get current stock market data like price, market cap, and historical trend for a specific Company. (e.g., apple or APPLE, NVIDIA or nvidia, TESLA or tesla)." | |
| "Args: company_name (str): the name of the company (e.g., 'Tesla')" | |
| ) | |
| ) | |
| web_search = Tool( | |
| name="Web Search", | |
| func=web_search, | |
| description=( | |
| "Use this tool to Search and get any general information from the Internet about the stock. This tool takes a query and returns the result." | |
| "For high Quality results provide a good length query with as much details as posible." | |
| ) | |
| ) | |
| reddit_search_tool = Tool( | |
| name="Reddit Search", | |
| func=reddit_search_tool, | |
| description=( | |
| "Use this tool to search Reddit for recent discussions and sentiments about a stock, event, or topic." | |
| "Input should be a search query (e.g., 'Do you like tesla?', 'what do you think about Tesla products?' , 'Tesla is a scam')." | |
| "Args: query (str): The search query (e.g., 'Tesla stock'). sort (str): Sort order ('new', 'hot', etc.). Defaults to 'new'. time_filter (str): Time range ('hour', 'day', 'week', 'month', 'year', 'all'). Defaults to 'week'. subreddit (str): type of subreddit ('stocks', 'products', 'car', 'bikes'). limit (str): Maximum number of results to return. Defaults to '10'." | |
| ) | |
| ) | |
| tech_news_tool = Tool( | |
| name="Technology News Search", | |
| func=tech_news, | |
| description=("Use this tool to get the latest technology news articles from the UK that match a topic (e.g., AI, robotics, fintech, Apple, Meta, Tesla).") | |
| ) | |
| politics_news_tool = Tool( | |
| name="Politics News Search", | |
| func=politics_news, | |
| description=("Use this tool to get the latest politicial news articles from the UK that match a topic (e.g., AI, robotics, fintech, Apple, Meta, Tesla).") | |
| ) | |
| business_news_tool = Tool( | |
| name="Business News Search", | |
| func=business_news, | |
| description=("Use this tool to get the latest Business news articles from the UK that match a topic (e.g., AI, robotics, fintech, Apple, Meta, Tesla).") | |
| ) | |
| world_news_tool = Tool( | |
| name="World News Search", | |
| func=world_news, | |
| description=("Use this tool to get the latest World news (geopolitical) articles from the UK that match a topic (e.g., AI, robotics, fintech, Apple, Meta, Tesla).") | |
| ) | |
| def get_tools(): | |
| return [ | |
| stock_data_tool, | |
| reddit_search_tool, | |
| web_search, | |
| tech_news_tool, | |
| business_news_tool, | |
| politics_news_tool, | |
| world_news_tool | |
| ] |