Whitepaper
Docs
Sign In
Tool
Tool
v0.4.0
yahoo finance
Tool ID
yahoo_finance
Creator
@johnthellm
Downloads
2.5K+
A comprehensive stock and cryptocurrency analysis tool using Yahoo Finance data, including historical price analysis.
Get
README
No README available
Tool Code
Show
""" title: Yahoo Finance Stock and Crypto Analyzer with Historical Data description: A comprehensive stock and cryptocurrency analysis tool using Yahoo Finance data, including historical price analysis and AI news sentiment. author: AI Assistant author_url: https://github.com/johnongit funding_url: https://github.com/open-webui version: 0.4.0 license: MIT requirements: yfinance, pandas, numpy, aiohttp, asyncio, transformers """ import yfinance as yf import pandas as pd import numpy as np import aiohttp import asyncio from transformers import pipeline from pydantic import BaseModel from typing import Dict, Any, List, Union, Callable, Awaitable from functools import lru_cache # Helper functions @lru_cache(maxsize=128) def _get_sentiment_model(): return pipeline("sentiment-analysis", model="ProsusAI/finbert") async def _async_sentiment_analysis( content: str, model ) -> Dict[str, Union[str, float]]: result = model(content)[0] return {"sentiment": result["label"], "confidence": result["score"]} # Main functions def _get_asset_info(ticker: str) -> Dict[str, Any]: asset = yf.Ticker(ticker) info = asset.info if info.get("quoteType") == "CRYPTOCURRENCY": return { "name": info.get("name", "N/A"), "symbol": info.get("symbol", "N/A"), "market_cap": info.get("marketCap", 0), "circulating_supply": info.get("circulatingSupply", 0), "max_supply": info.get("maxSupply", 0), "24h_volume": info.get("volume24Hr", 0), "7d_change": info.get("sevenDayAvgChangePercent", 0), "is_crypto": True, } else: return { "name": info.get("longName", "N/A"), "symbol": info.get("symbol", "N/A"), "sector": info.get("sector", "N/A"), "industry": info.get("industry", "N/A"), "market_cap": info.get("marketCap", 0), "pe_ratio": info.get("trailingPE", 0), "dividend_yield": info.get("dividendYield", 0), "beta": info.get("beta", 0), "52_week_high": info.get("fiftyTwoWeekHigh", 0), "52_week_low": info.get("fiftyTwoWeekLow", 0), "is_crypto": False, } def _get_current_price(ticker: str) -> Dict[str, float]: asset = yf.Ticker(ticker) data = asset.history(period="1d") return { "current_price": data["Close"].iloc[-1], "open": data["Open"].iloc[-1], "high": data["High"].iloc[-1], "low": data["Low"].iloc[-1], "volume": data["Volume"].iloc[-1], } def _get_asset_news(ticker: str) -> List[Dict[str, Any]]: asset = yf.Ticker(ticker) news = asset.news formatted_news = [] for item in news: formatted_item = { "title": item["title"], "publisher": item["publisher"], "link": item["link"], "published_time": item["providerPublishTime"], "summary": item.get("summary", "No summary available."), } formatted_news.append(formatted_item) return formatted_news def _get_historical_data(ticker: str, period: str = "1y") -> pd.DataFrame: asset = yf.Ticker(ticker) history = asset.history(period=period) return history def _analyze_historical_data(df: pd.DataFrame) -> Dict[str, Any]: analysis = {} # Calculate simple moving averages df["SMA50"] = df["Close"].rolling(window=50).mean() df["SMA200"] = df["Close"].rolling(window=200).mean() # Calculate price change and volatility df["Daily_Return"] = df["Close"].pct_change() analysis["price_change"] = (df["Close"].iloc[-1] / df["Close"].iloc[0] - 1) * 100 analysis["volatility"] = ( df["Daily_Return"].std() * np.sqrt(252) * 100 ) # Annualized volatility # Trend analysis current_price = df["Close"].iloc[-1] analysis["trend_sma50"] = ( "Bullish" if current_price > df["SMA50"].iloc[-1] else "Bearish" ) analysis["trend_sma200"] = ( "Bullish" if current_price > df["SMA200"].iloc[-1] else "Bearish" ) # Highest and lowest prices analysis["highest_price"] = df["High"].max() analysis["lowest_price"] = df["Low"].min() # Average volume analysis["avg_volume"] = df["Volume"].mean() return analysis async def _async_gather_asset_data(ticker: str) -> Dict[str, Any]: asset_info = _get_asset_info(ticker) current_price = _get_current_price(ticker) news_items = _get_asset_news(ticker) historical_data = _get_historical_data(ticker) historical_analysis = _analyze_historical_data(historical_data) model = _get_sentiment_model() sentiment_tasks = [ _async_sentiment_analysis(item["title"], model) for item in news_items ] sentiments = await asyncio.gather(*sentiment_tasks) sentiment_results = [ { "title": news_items[i]["title"], "publisher": news_items[i]["publisher"], "link": news_items[i]["link"], "published_time": news_items[i]["published_time"], "sentiment": sentiment["sentiment"], "confidence": sentiment["confidence"], } for i, sentiment in enumerate(sentiments) ] return { "asset_info": asset_info, "current_price": current_price, "sentiments": sentiment_results, "historical_analysis": historical_analysis, } def _get_rsi_macd(symbol="BTC-USD", period="1mo", interval="1d"): ticker = yf.Ticker(symbol) data = ticker.history(period=period, interval=interval) close_prices = data["Close"] # Calculate RSI delta = close_prices.diff() gain = delta.where(delta > 0, 0) loss = -delta.where(delta < 0, 0) avg_gain = gain.rolling(window=14).mean() avg_loss = loss.rolling(window=14).mean() rs = avg_gain / avg_loss rsi = 100 - (100 / (1 + rs)) # Calculate MACD ema_12 = close_prices.ewm(span=12, adjust=False).mean() ema_26 = close_prices.ewm(span=26, adjust=False).mean() macd_line = ema_12 - ema_26 signal_line = macd_line.ewm(span=9, adjust=False).mean() macd_hist = macd_line - signal_line # Format output output = f"Results for {symbol} over period {period} with interval {interval}:\n\n" output += f"Latest RSI: {rsi.iloc[-1]:.2f}\n" output += f"Latest MACD: {macd_line.iloc[-1]:.2f}\n" output += f"Latest MACD Signal: {signal_line.iloc[-1]:.2f}\n" output += f"Latest MACD Histogram: {macd_hist.iloc[-1]:.2f}\n\n" output += "RSI Evolution:\n" output += f"{rsi.tail(10).to_string(header=False)}\n\n" output += "MACD Evolution:\n" output_df = pd.DataFrame( {"MACD": macd_line, "Signal": signal_line, "Histogram": macd_hist}, index=macd_line.index, ) output += f"{output_df.tail(10).to_string(index=True)}" return output def _compile_report( data: Dict[str, Any], price_history: pd.DataFrame, tech_data: str ) -> str: info = data["asset_info"] price = data["current_price"] historical = data["historical_analysis"] if info["is_crypto"]: report = """ Cryptocurrency Analysis Report for {name} ({symbol}) Basic Information: Market Cap: ${market_cap:,.0f} Circulating Supply: {circulating_supply:,.0f} Current Trading Information: Current Price: ${current_price:.2f} 24h Range: ${low:.2f} - ${high:.2f} 24h Volume: {volume:,.0f} Historical Analysis: Price Change (1 year): {price_change:.2f}% Annualized Volatility: {volatility:.2f}% 50-day SMA Trend: {trend_sma50} 200-day SMA Trend: {trend_sma200} Highest Price (1 year): ${highest_price:.2f} Lowest Price (1 year): ${lowest_price:.2f} Average Daily Volume: {avg_volume:,.0f} Price history: {price_history} Technical data: {tech_data} """.format( name=info["name"], symbol=info["symbol"], market_cap=info["market_cap"], circulating_supply=info["circulating_supply"], current_price=price["current_price"], low=price["low"], high=price["high"], volume=price["volume"], price_change=historical["price_change"], volatility=historical["volatility"], trend_sma50=historical["trend_sma50"], trend_sma200=historical["trend_sma200"], highest_price=historical["highest_price"], lowest_price=historical["lowest_price"], avg_volume=historical["avg_volume"], price_history=price_history.to_string(), tech_data=tech_data, ) else: report = """ Stock Analysis Report for {name} ({symbol}) Basic Information: Sector: {sector} Industry: {industry} Market Cap: ${market_cap:,.0f} Current Trading Information: Current Price: ${current_price:.2f} Day's Range: ${low:.2f} - ${high:.2f} Volume: {volume:,.0f} Key Financial Metrics: P/E Ratio: {pe_ratio} Dividend Yield: {dividend_yield:.2%} Beta: {beta} 52 Week Range: ${week_low:.2f} - ${week_high:.2f} Historical Analysis: Price Change (1 year): {price_change:.2f}% Annualized Volatility: {volatility:.2f}% 50-day SMA Trend: {trend_sma50} 200-day SMA Trend: {trend_sma200} Highest Price (1 year): ${highest_price:.2f} Lowest Price (1 year): ${lowest_price:.2f} Average Daily Volume: {avg_volume:,.0f} """.format( name=info["name"], symbol=info["symbol"], sector=info["sector"], industry=info["industry"], market_cap=info["market_cap"], current_price=price["current_price"], low=price["low"], high=price["high"], volume=price["volume"], pe_ratio=info["pe_ratio"], dividend_yield=info["dividend_yield"], beta=info["beta"], week_low=info["52_week_low"], week_high=info["52_week_high"], price_change=historical["price_change"], volatility=historical["volatility"], trend_sma50=historical["trend_sma50"], trend_sma200=historical["trend_sma200"], highest_price=historical["highest_price"], lowest_price=historical["lowest_price"], avg_volume=historical["avg_volume"], ) report += "Recent News and Sentiment Analysis:\n" for item in data["sentiments"]: report += """ Title: {title} Publisher: {publisher} Link: {url} Published Time: {published_time} Sentiment: {sentiment} (Confidence: {confidence:.2f}) """.format( title=item["title"], publisher=item["publisher"], url=item["link"], published_time=item["published_time"], sentiment=item["sentiment"], confidence=item["confidence"], ) print("report") print(report) return report class Tools: class UserValves(BaseModel): pass def __init__(self): pass async def analyze_asset( self, ticker: str, __user__: dict = {}, __event_emitter__: Callable[[Any], Awaitable[None]] = None, ) -> str: """ Perform a comprehensive analysis and compile a detailed report for a given stock or cryptocurrency ticker using Yahoo Finance data. :param ticker: The asset ticker symbol (e.g., "AAPL" for Apple Inc. or "BTC-USD" for Bitcoin). :return: A comprehensive analysis report of the asset as a formatted string. """ await __event_emitter__( { "type": "status", "data": {"description": "Initializing analysis", "done": False}, } ) await __event_emitter__( { "type": "status", "data": {"description": "Retrieving asset data", "done": False}, } ) price_history = _get_historical_data(ticker) tech_data = _get_rsi_macd(ticker) data = await _async_gather_asset_data(ticker) await __event_emitter__( { "type": "status", "data": {"description": "Compiling asset report", "done": False}, } ) report = _compile_report(data, price_history, tech_data) last_price = data["current_price"]["current_price"] asset_type = "cryptocurrency" if data["asset_info"]["is_crypto"] else "stock" await __event_emitter__( { "type": "status", "data": { "description": "Finished creating report for {0} - latest price: ${1:.4f}".format( asset_type, last_price, ), "done": True, }, } ) return report