From 0ab323c2c6575d474575a0a623654dec126c55ce Mon Sep 17 00:00:00 2001 From: luohy15 Date: Fri, 26 Sep 2025 22:57:50 +0800 Subject: [PATCH] Add Alpha Vantage API integration as primary data provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace FinnHub with Alpha Vantage API in README documentation - Implement comprehensive Alpha Vantage modules: - Stock data (daily OHLCV with date filtering) - Technical indicators (SMA, EMA, MACD, RSI, Bollinger Bands, ATR) - Fundamental data (overview, balance sheet, cashflow, income statement) - News and sentiment data with insider transactions - Update news analyst tools to use ticker-based news search - Integrate Alpha Vantage vendor methods into interface routing - Maintain backward compatibility with existing vendor system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 4 +- tradingagents/agents/analysts/news_analyst.py | 2 +- .../agents/analysts/social_media_analyst.py | 2 +- tradingagents/agents/utils/news_data_tools.py | 8 +- tradingagents/dataflows/alpha_vantage.py | 5 + .../dataflows/alpha_vantage_common.py | 103 +++++++++ .../dataflows/alpha_vantage_fundamentals.py | 77 +++++++ .../dataflows/alpha_vantage_indicator.py | 218 ++++++++++++++++++ tradingagents/dataflows/alpha_vantage_news.py | 43 ++++ .../dataflows/alpha_vantage_stock.py | 38 +++ tradingagents/dataflows/interface.py | 23 +- tradingagents/dataflows/stockstats_utils.py | 5 +- tradingagents/dataflows/yahoo_finance.py | 2 - tradingagents/default_config.py | 8 +- 14 files changed, 519 insertions(+), 19 deletions(-) create mode 100644 tradingagents/dataflows/alpha_vantage.py create mode 100644 tradingagents/dataflows/alpha_vantage_common.py create mode 100644 tradingagents/dataflows/alpha_vantage_fundamentals.py create mode 100644 tradingagents/dataflows/alpha_vantage_indicator.py create mode 100644 tradingagents/dataflows/alpha_vantage_news.py create mode 100644 tradingagents/dataflows/alpha_vantage_stock.py diff --git a/README.md b/README.md index 31286500..cef678f6 100644 --- a/README.md +++ b/README.md @@ -114,9 +114,9 @@ pip install -r requirements.txt ### Required APIs -You will also need the FinnHub API for financial data. All of our code is implemented with the free tier. +You will also need the Alpha Vantage API for financial data. The free tier supports 25 API calls per day. ```bash -export FINNHUB_API_KEY=$YOUR_FINNHUB_API_KEY +export ALPHA_VANTAGE_API_KEY=$YOUR_ALPHA_VANTAGE_API_KEY ``` You will need the OpenAI API for all the agents. diff --git a/tradingagents/agents/analysts/news_analyst.py b/tradingagents/agents/analysts/news_analyst.py index 2e227c93..03b4fae4 100644 --- a/tradingagents/agents/analysts/news_analyst.py +++ b/tradingagents/agents/analysts/news_analyst.py @@ -16,7 +16,7 @@ def create_news_analyst(llm): ] system_message = ( - "You are a news researcher tasked with analyzing recent news and trends over the past week. Please write a comprehensive report of the current state of the world that is relevant for trading and macroeconomics. Use the get_news_data tool with different news_type parameters: 'global_news' for macroeconomic news, 'company_news' for company-specific news, 'reddit_global' for social sentiment, 'google' for general news searches. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." + "You are a news researcher tasked with analyzing recent news and trends over the past week. Please write a comprehensive report of the current state of the world that is relevant for trading and macroeconomics. Use the available tools: get_news(query, start_date, end_date) for company-specific or targeted news searches, and get_global_news(curr_date, look_back_days, limit) for broader macroeconomic news. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." + """ Make sure to append a Markdown table at the end of the report to organize key points in the report, organized and easy to read.""" ) diff --git a/tradingagents/agents/analysts/social_media_analyst.py b/tradingagents/agents/analysts/social_media_analyst.py index b1556fb6..b25712d7 100644 --- a/tradingagents/agents/analysts/social_media_analyst.py +++ b/tradingagents/agents/analysts/social_media_analyst.py @@ -16,7 +16,7 @@ def create_social_media_analyst(llm): ] system_message = ( - "You are a social media and company specific news researcher/analyst tasked with analyzing social media posts, recent company news, and public sentiment for a specific company over the past week. You will be given a company's name your objective is to write a comprehensive long report detailing your analysis, insights, and implications for traders and investors on this company's current state after looking at social media and what people are saying about that company, analyzing sentiment data of what people feel each day about the company, and looking at recent company news. Use get_news_data with news_type parameters: 'company_news' for company-specific news, 'reddit_stock' for Reddit discussions about the stock. Try to look at all sources possible from social media to sentiment to news. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." + "You are a social media and company specific news researcher/analyst tasked with analyzing social media posts, recent company news, and public sentiment for a specific company over the past week. You will be given a company's name your objective is to write a comprehensive long report detailing your analysis, insights, and implications for traders and investors on this company's current state after looking at social media and what people are saying about that company, analyzing sentiment data of what people feel each day about the company, and looking at recent company news. Use the get_news(query, start_date, end_date) tool to search for company-specific news and social media discussions. Try to look at all sources possible from social media to sentiment to news. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." + """ Make sure to append a Markdown table at the end of the report to organize key points in the report, organized and easy to read.""", ) diff --git a/tradingagents/agents/utils/news_data_tools.py b/tradingagents/agents/utils/news_data_tools.py index 2949e904..e42b4dfe 100644 --- a/tradingagents/agents/utils/news_data_tools.py +++ b/tradingagents/agents/utils/news_data_tools.py @@ -4,21 +4,21 @@ from tradingagents.dataflows.interface import route_to_vender @tool def get_news( - query: Annotated[str, "Search query or ticker symbol"], + ticker: Annotated[str, "Ticker symbol"], start_date: Annotated[str, "Start date in yyyy-mm-dd format"], end_date: Annotated[str, "End date in yyyy-mm-dd format"], ) -> str: """ - Retrieve news data for a given query or ticker symbol. + Retrieve news data for a given ticker symbol. Uses the configured news_data vendor. Args: - query (str): Search query or ticker symbol + ticker (str): Ticker symbol start_date (str): Start date in yyyy-mm-dd format end_date (str): End date in yyyy-mm-dd format Returns: str: A formatted string containing news data """ - return route_to_vender("get_news", query, start_date, end_date) + return route_to_vender("get_news", ticker, start_date, end_date) @tool def get_global_news( diff --git a/tradingagents/dataflows/alpha_vantage.py b/tradingagents/dataflows/alpha_vantage.py new file mode 100644 index 00000000..c5177c29 --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage.py @@ -0,0 +1,5 @@ +# Import functions from specialized modules +from .alpha_vantage_stock import get_stock +from .alpha_vantage_indicator import get_indicator +from .alpha_vantage_fundamentals import get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement +from .alpha_vantage_news import get_news, get_insider_transactions \ No newline at end of file diff --git a/tradingagents/dataflows/alpha_vantage_common.py b/tradingagents/dataflows/alpha_vantage_common.py new file mode 100644 index 00000000..aeeb30ef --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage_common.py @@ -0,0 +1,103 @@ +import os +import requests +import pandas as pd +from datetime import datetime +from io import StringIO + +API_BASE_URL = "https://www.alphavantage.co/query" + +def get_api_key() -> str: + """Retrieve the API key for Alpha Vantage from environment variables.""" + api_key = os.getenv("ALPHA_VANTAGE_API_KEY") + if not api_key: + raise ValueError("ALPHA_VANTAGE_API_KEY environment variable is not set.") + return api_key + +def format_datetime_for_api(date_input) -> str: + """Convert various date formats to YYYYMMDDTHHMM format required by Alpha Vantage API.""" + if isinstance(date_input, str): + # If already in correct format, return as-is + if len(date_input) == 13 and 'T' in date_input: + return date_input + # Try to parse common date formats + try: + dt = datetime.strptime(date_input, "%Y-%m-%d") + return dt.strftime("%Y%m%dT0000") + except ValueError: + try: + dt = datetime.strptime(date_input, "%Y-%m-%d %H:%M") + return dt.strftime("%Y%m%dT%H%M") + except ValueError: + raise ValueError(f"Unsupported date format: {date_input}") + elif isinstance(date_input, datetime): + return date_input.strftime("%Y%m%dT%H%M") + else: + raise ValueError(f"Date must be string or datetime object, got {type(date_input)}") + +def _make_api_request(function_name: str, params: dict) -> dict | str: + """Helper function to make API requests and handle responses. + + """ + # Create a copy of params to avoid modifying the original + api_params = params.copy() + api_params.update({ + "function": function_name, + "apikey": get_api_key(), + "source": "alphavangtagemcp" + }) + + # Handle entitlement parameter if present in params or global variable + current_entitlement = globals().get('_current_entitlement') + entitlement = api_params.get("entitlement") or current_entitlement + + if entitlement: + api_params["entitlement"] = entitlement + elif "entitlement" in api_params: + # Remove entitlement if it's None or empty + api_params.pop("entitlement", None) + + response = requests.get(API_BASE_URL, params=api_params) + response.raise_for_status() + + response_text = response.text + + return response_text + + + +def _filter_csv_by_date_range(csv_data: str, start_date: str, end_date: str) -> str: + """ + Filter CSV data to include only rows within the specified date range. + + Args: + csv_data: CSV string from Alpha Vantage API + start_date: Start date in yyyy-mm-dd format + end_date: End date in yyyy-mm-dd format + + Returns: + Filtered CSV string + """ + if not csv_data or csv_data.strip() == "": + return csv_data + + try: + # Parse CSV data + df = pd.read_csv(StringIO(csv_data)) + + # Assume the first column is the date column (timestamp) + date_col = df.columns[0] + df[date_col] = pd.to_datetime(df[date_col]) + + # Filter by date range + start_dt = pd.to_datetime(start_date) + end_dt = pd.to_datetime(end_date) + + filtered_df = df[(df[date_col] >= start_dt) & (df[date_col] <= end_dt)] + + # Convert back to CSV string + return filtered_df.to_csv(index=False) + + except Exception as e: + # If filtering fails, return original data with a warning + print(f"Warning: Failed to filter CSV data by date range: {e}") + return csv_data diff --git a/tradingagents/dataflows/alpha_vantage_fundamentals.py b/tradingagents/dataflows/alpha_vantage_fundamentals.py new file mode 100644 index 00000000..8b92faa6 --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage_fundamentals.py @@ -0,0 +1,77 @@ +from .alpha_vantage_common import _make_api_request + + +def get_fundamentals(ticker: str, curr_date: str = None) -> str: + """ + Retrieve comprehensive fundamental data for a given ticker symbol using Alpha Vantage. + + Args: + ticker (str): Ticker symbol of the company + curr_date (str): Current date you are trading at, yyyy-mm-dd (not used for Alpha Vantage) + + Returns: + str: Company overview data including financial ratios and key metrics + """ + params = { + "symbol": ticker, + } + + return _make_api_request("OVERVIEW", params) + + +def get_balance_sheet(ticker: str, freq: str = "quarterly", curr_date: str = None) -> str: + """ + Retrieve balance sheet data for a given ticker symbol using Alpha Vantage. + + Args: + ticker (str): Ticker symbol of the company + freq (str): Reporting frequency: annual/quarterly (default quarterly) - not used for Alpha Vantage + curr_date (str): Current date you are trading at, yyyy-mm-dd (not used for Alpha Vantage) + + Returns: + str: Balance sheet data with normalized fields + """ + params = { + "symbol": ticker, + } + + return _make_api_request("BALANCE_SHEET", params) + + +def get_cashflow(ticker: str, freq: str = "quarterly", curr_date: str = None) -> str: + """ + Retrieve cash flow statement data for a given ticker symbol using Alpha Vantage. + + Args: + ticker (str): Ticker symbol of the company + freq (str): Reporting frequency: annual/quarterly (default quarterly) - not used for Alpha Vantage + curr_date (str): Current date you are trading at, yyyy-mm-dd (not used for Alpha Vantage) + + Returns: + str: Cash flow statement data with normalized fields + """ + params = { + "symbol": ticker, + } + + return _make_api_request("CASH_FLOW", params) + + +def get_income_statement(ticker: str, freq: str = "quarterly", curr_date: str = None) -> str: + """ + Retrieve income statement data for a given ticker symbol using Alpha Vantage. + + Args: + ticker (str): Ticker symbol of the company + freq (str): Reporting frequency: annual/quarterly (default quarterly) - not used for Alpha Vantage + curr_date (str): Current date you are trading at, yyyy-mm-dd (not used for Alpha Vantage) + + Returns: + str: Income statement data with normalized fields + """ + params = { + "symbol": ticker, + } + + return _make_api_request("INCOME_STATEMENT", params) + diff --git a/tradingagents/dataflows/alpha_vantage_indicator.py b/tradingagents/dataflows/alpha_vantage_indicator.py new file mode 100644 index 00000000..c696091c --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage_indicator.py @@ -0,0 +1,218 @@ +from .alpha_vantage_common import _make_api_request + +def get_indicator( + symbol: str, + indicator: str, + curr_date: str, + look_back_days: int, + interval: str = "daily", + time_period: int = 14, + series_type: str = "close" +) -> str: + """ + Returns Alpha Vantage technical indicator values over a time window. + + Args: + symbol: ticker symbol of the company + indicator: technical indicator to get the analysis and report of + curr_date: The current trading date you are trading on, YYYY-mm-dd + look_back_days: how many days to look back + interval: Time interval (daily, weekly, monthly) + time_period: Number of data points for calculation + series_type: The desired price type (close, open, high, low) + + Returns: + String containing indicator values and description + """ + from datetime import datetime + from dateutil.relativedelta import relativedelta + + supported_indicators = { + "close_50_sma": ("50 SMA", "close"), + "close_200_sma": ("200 SMA", "close"), + "close_10_ema": ("10 EMA", "close"), + "macd": ("MACD", "close"), + "macds": ("MACD Signal", "close"), + "macdh": ("MACD Histogram", "close"), + "rsi": ("RSI", "close"), + "boll": ("Bollinger Middle", "close"), + "boll_ub": ("Bollinger Upper Band", "close"), + "boll_lb": ("Bollinger Lower Band", "close"), + "atr": ("ATR", None), + "vwma": ("VWMA", "close") + } + + indicator_descriptions = { + "close_50_sma": "50 SMA: A medium-term trend indicator. Usage: Identify trend direction and serve as dynamic support/resistance. Tips: It lags price; combine with faster indicators for timely signals.", + "close_200_sma": "200 SMA: A long-term trend benchmark. Usage: Confirm overall market trend and identify golden/death cross setups. Tips: It reacts slowly; best for strategic trend confirmation rather than frequent trading entries.", + "close_10_ema": "10 EMA: A responsive short-term average. Usage: Capture quick shifts in momentum and potential entry points. Tips: Prone to noise in choppy markets; use alongside longer averages for filtering false signals.", + "macd": "MACD: Computes momentum via differences of EMAs. Usage: Look for crossovers and divergence as signals of trend changes. Tips: Confirm with other indicators in low-volatility or sideways markets.", + "macds": "MACD Signal: An EMA smoothing of the MACD line. Usage: Use crossovers with the MACD line to trigger trades. Tips: Should be part of a broader strategy to avoid false positives.", + "macdh": "MACD Histogram: Shows the gap between the MACD line and its signal. Usage: Visualize momentum strength and spot divergence early. Tips: Can be volatile; complement with additional filters in fast-moving markets.", + "rsi": "RSI: Measures momentum to flag overbought/oversold conditions. Usage: Apply 70/30 thresholds and watch for divergence to signal reversals. Tips: In strong trends, RSI may remain extreme; always cross-check with trend analysis.", + "boll": "Bollinger Middle: A 20 SMA serving as the basis for Bollinger Bands. Usage: Acts as a dynamic benchmark for price movement. Tips: Combine with the upper and lower bands to effectively spot breakouts or reversals.", + "boll_ub": "Bollinger Upper Band: Typically 2 standard deviations above the middle line. Usage: Signals potential overbought conditions and breakout zones. Tips: Confirm signals with other tools; prices may ride the band in strong trends.", + "boll_lb": "Bollinger Lower Band: Typically 2 standard deviations below the middle line. Usage: Indicates potential oversold conditions. Tips: Use additional analysis to avoid false reversal signals.", + "atr": "ATR: Averages true range to measure volatility. Usage: Set stop-loss levels and adjust position sizes based on current market volatility. Tips: It's a reactive measure, so use it as part of a broader risk management strategy.", + "vwma": "VWMA: A moving average weighted by volume. Usage: Confirm trends by integrating price action with volume data. Tips: Watch for skewed results from volume spikes; use in combination with other volume analyses." + } + + if indicator not in supported_indicators: + raise ValueError( + f"Indicator {indicator} is not supported. Please choose from: {list(supported_indicators.keys())}" + ) + + curr_date_dt = datetime.strptime(curr_date, "%Y-%m-%d") + before = curr_date_dt - relativedelta(days=look_back_days) + + # Get the full data for the period instead of making individual calls + _, required_series_type = supported_indicators[indicator] + + # Use the provided series_type or fall back to the required one + if required_series_type: + series_type = required_series_type + + try: + # Get indicator data for the period + if indicator == "close_50_sma": + data = _make_api_request("SMA", { + "symbol": symbol, + "interval": interval, + "time_period": "50", + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "close_200_sma": + data = _make_api_request("SMA", { + "symbol": symbol, + "interval": interval, + "time_period": "200", + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "close_10_ema": + data = _make_api_request("EMA", { + "symbol": symbol, + "interval": interval, + "time_period": "10", + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "macd": + data = _make_api_request("MACD", { + "symbol": symbol, + "interval": interval, + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "macds": + data = _make_api_request("MACD", { + "symbol": symbol, + "interval": interval, + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "macdh": + data = _make_api_request("MACD", { + "symbol": symbol, + "interval": interval, + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "rsi": + data = _make_api_request("RSI", { + "symbol": symbol, + "interval": interval, + "time_period": str(time_period), + "series_type": series_type, + "datatype": "csv" + }) + elif indicator in ["boll", "boll_ub", "boll_lb"]: + data = _make_api_request("BBANDS", { + "symbol": symbol, + "interval": interval, + "time_period": "20", + "series_type": series_type, + "datatype": "csv" + }) + elif indicator == "atr": + data = _make_api_request("ATR", { + "symbol": symbol, + "interval": interval, + "time_period": str(time_period), + "datatype": "csv" + }) + elif indicator == "vwma": + # Alpha Vantage doesn't have direct VWMA, so we'll return an informative message + # In a real implementation, this would need to be calculated from OHLCV data + return f"## VWMA (Volume Weighted Moving Average) for {symbol}:\n\nVWMA calculation requires OHLCV data and is not directly available from Alpha Vantage API.\nThis indicator would need to be calculated from the raw stock data using volume-weighted price averaging.\n\n{indicator_descriptions.get('vwma', 'No description available.')}" + else: + return f"Error: Indicator {indicator} not implemented yet." + + # Parse CSV data and extract values for the date range + lines = data.strip().split('\n') + if len(lines) < 2: + return f"Error: No data returned for {indicator}" + + # Parse header and data + header = lines[0].split(',') + date_col_idx = 0 # Assuming first column is date + value_col_idx = 1 # Default to second column + + # Handle specific indicator column mappings + if indicator == "macds": + # MACD Signal is typically in the third column + value_col_idx = 2 if len(header) > 2 else 1 + elif indicator == "macdh": + # MACD Histogram is typically in the fourth column + value_col_idx = 3 if len(header) > 3 else 1 + elif indicator == "boll_ub": + # Bollinger Upper Band is typically in the second column + value_col_idx = 1 + elif indicator == "boll": + # Bollinger Middle is typically in the third column + value_col_idx = 2 if len(header) > 2 else 1 + elif indicator == "boll_lb": + # Bollinger Lower Band is typically in the fourth column + value_col_idx = 3 if len(header) > 3 else 1 + + result_data = [] + for line in lines[1:]: + if not line.strip(): + continue + values = line.split(',') + if len(values) > value_col_idx: + try: + date_str = values[date_col_idx].strip() + # Parse the date + date_dt = datetime.strptime(date_str, "%Y-%m-%d") + + # Check if date is in our range + if before <= date_dt <= curr_date_dt: + value = values[value_col_idx].strip() + result_data.append((date_dt, value)) + except (ValueError, IndexError): + continue + + # Sort by date and format output + result_data.sort(key=lambda x: x[0]) + + ind_string = "" + for date_dt, value in result_data: + ind_string += f"{date_dt.strftime('%Y-%m-%d')}: {value}\n" + + if not ind_string: + ind_string = "No data available for the specified date range.\n" + + result_str = ( + f"## {indicator.upper()} values from {before.strftime('%Y-%m-%d')} to {curr_date}:\n\n" + + ind_string + + "\n\n" + + indicator_descriptions.get(indicator, "No description available.") + ) + + return result_str + + except Exception as e: + print(f"Error getting Alpha Vantage indicator data for {indicator}: {e}") + return f"Error retrieving {indicator} data: {str(e)}" diff --git a/tradingagents/dataflows/alpha_vantage_news.py b/tradingagents/dataflows/alpha_vantage_news.py new file mode 100644 index 00000000..8124fb45 --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage_news.py @@ -0,0 +1,43 @@ +from .alpha_vantage_common import _make_api_request, format_datetime_for_api + +def get_news(ticker, start_date, end_date) -> dict[str, str] | str: + """Returns live and historical market news & sentiment data from premier news outlets worldwide. + + Covers stocks, cryptocurrencies, forex, and topics like fiscal policy, mergers & acquisitions, IPOs. + + Args: + ticker: Stock symbol for news articles. + start_date: Start date for news search. + end_date: End date for news search. + + Returns: + Dictionary containing news sentiment data or JSON string. + """ + + params = { + "tickers": ticker, + "time_from": format_datetime_for_api(start_date), + "time_to": format_datetime_for_api(end_date), + "sort": "LATEST", + "limit": "50", + } + + return _make_api_request("NEWS_SENTIMENT", params) + +def get_insider_transactions(symbol: str) -> dict[str, str] | str: + """Returns latest and historical insider transactions by key stakeholders. + + Covers transactions by founders, executives, board members, etc. + + Args: + symbol: Ticker symbol. Example: "IBM". + + Returns: + Dictionary containing insider transaction data or JSON string. + """ + + params = { + "symbol": symbol, + } + + return _make_api_request("INSIDER_TRANSACTIONS", params) \ No newline at end of file diff --git a/tradingagents/dataflows/alpha_vantage_stock.py b/tradingagents/dataflows/alpha_vantage_stock.py new file mode 100644 index 00000000..ffd3570b --- /dev/null +++ b/tradingagents/dataflows/alpha_vantage_stock.py @@ -0,0 +1,38 @@ +from datetime import datetime +from .alpha_vantage_common import _make_api_request, _filter_csv_by_date_range + +def get_stock( + symbol: str, + start_date: str, + end_date: str +) -> str: + """ + Returns raw daily OHLCV values, adjusted close values, and historical split/dividend events + filtered to the specified date range. + + Args: + symbol: The name of the equity. For example: symbol=IBM + start_date: Start date in yyyy-mm-dd format + end_date: End date in yyyy-mm-dd format + + Returns: + CSV string containing the daily adjusted time series data filtered to the date range. + """ + # Parse dates to determine the range + start_dt = datetime.strptime(start_date, "%Y-%m-%d") + today = datetime.now() + + # Choose outputsize based on whether the requested range is within the latest 100 days + # Compact returns latest 100 data points, so check if start_date is recent enough + days_from_today_to_start = (today - start_dt).days + outputsize = "compact" if days_from_today_to_start < 100 else "full" + + params = { + "symbol": symbol, + "outputsize": outputsize, + "datatype": "csv", + } + + response = _make_api_request("TIME_SERIES_DAILY_ADJUSTED", params) + + return _filter_csv_by_date_range(response, start_date, end_date) \ No newline at end of file diff --git a/tradingagents/dataflows/interface.py b/tradingagents/dataflows/interface.py index 2b6b92de..3a23f4ce 100644 --- a/tradingagents/dataflows/interface.py +++ b/tradingagents/dataflows/interface.py @@ -5,6 +5,16 @@ from .local import get_YFin_data, get_finnhub_news, get_finnhub_company_insider_ from .yahoo_finance import get_YFin_data_online, get_stock_stats_indicators_window from .google import get_google_news from .openai import get_stock_news_openai, get_global_news_openai, get_fundamentals_openai +from .alpha_vantage import ( + get_stock as get_alpha_vantage_stock, + get_indicator as get_alpha_vantage_indicator, + get_fundamentals as get_alpha_vantage_fundamentals, + get_balance_sheet as get_alpha_vantage_balance_sheet, + get_cashflow as get_alpha_vantage_cashflow, + get_income_statement as get_alpha_vantage_income_statement, + get_insider_transactions as get_alpha_vantage_insider_transactions, + get_news as get_alpha_vantage_news +) # Configuration and routing logic from .config import get_config @@ -54,29 +64,36 @@ VENDOR_LIST = [ VENDOR_METHODS = { # core_stock_apis "get_stock_data": { + "alpha_vantage": get_alpha_vantage_stock, "yahoo_finance": get_YFin_data_online, "local": get_YFin_data, }, # technical_indicators "get_indicators": { + "alpha_vantage": get_alpha_vantage_indicator, "yahoo_finance": get_stock_stats_indicators_window, "local": get_stock_stats_indicators_window }, # fundamental_data "get_fundamentals": { - "openai": get_fundamentals_openai + "alpha_vantage": get_alpha_vantage_fundamentals, + "openai": get_fundamentals_openai, }, "get_balance_sheet": { + "alpha_vantage": get_alpha_vantage_balance_sheet, "local": get_simfin_balance_sheet, }, "get_cashflow": { + "alpha_vantage": get_alpha_vantage_cashflow, "local": get_simfin_cashflow, }, "get_income_statement": { + "alpha_vantage": get_alpha_vantage_income_statement, "local": get_simfin_income_statements, }, # news_data "get_news": { + "alpha_vantage": get_alpha_vantage_news, "openai": get_stock_news_openai, "google": get_google_news, "local": [get_finnhub_news, get_reddit_company_news, get_google_news], @@ -89,6 +106,7 @@ VENDOR_METHODS = { "local": get_finnhub_company_insider_sentiment }, "get_insider_transactions": { + "alpha_vantage": get_alpha_vantage_insider_transactions, "local": get_finnhub_company_insider_transactions, }, } @@ -131,7 +149,8 @@ def route_to_vender(method: str, *args, **kwargs): for vendor in vendors: if vendor not in VENDOR_METHODS[method]: - raise ValueError(f"Vendor '{vendor}' not supported for method '{method}'") + print(f"Info: Vendor '{vendor}' not supported for method '{method}', ignoring") + continue vendor_impl = VENDOR_METHODS[method][vendor] diff --git a/tradingagents/dataflows/stockstats_utils.py b/tradingagents/dataflows/stockstats_utils.py index ba547dc5..e81684e0 100644 --- a/tradingagents/dataflows/stockstats_utils.py +++ b/tradingagents/dataflows/stockstats_utils.py @@ -3,7 +3,7 @@ import yfinance as yf from stockstats import wrap from typing import Annotated import os -from .config import get_config +from .config import get_config, DATA_DIR class StockstatsUtils: @@ -19,7 +19,6 @@ class StockstatsUtils: ): # Get config and set up data directory path config = get_config() - data_dir = os.path.join(config["DATA_DIR"], "market_data", "price_data") online = config["data_vendors"]["technical_indicators"] != "local" df = None @@ -29,7 +28,7 @@ class StockstatsUtils: try: data = pd.read_csv( os.path.join( - data_dir, + DATA_DIR, f"{symbol}-YFin-data-2015-01-01-2025-03-25.csv", ) ) diff --git a/tradingagents/dataflows/yahoo_finance.py b/tradingagents/dataflows/yahoo_finance.py index 8189cc4d..049403cb 100644 --- a/tradingagents/dataflows/yahoo_finance.py +++ b/tradingagents/dataflows/yahoo_finance.py @@ -1,10 +1,8 @@ from typing import Annotated from datetime import datetime from dateutil.relativedelta import relativedelta -import pandas as pd import yfinance as yf import os -from .config import DATA_DIR from .stockstats_utils import StockstatsUtils def get_YFin_data_online( diff --git a/tradingagents/default_config.py b/tradingagents/default_config.py index 6134d2c1..d02411e0 100644 --- a/tradingagents/default_config.py +++ b/tradingagents/default_config.py @@ -20,10 +20,10 @@ DEFAULT_CONFIG = { # Data vendor configuration # Category-level configuration (default for all tools in category) "data_vendors": { - "core_stock_apis": "yahoo_finance", # OHLCV data: yahoo_finance, local - "technical_indicators": "yahoo_finance", # Technical indicators: yahoo_finance, local - "fundamental_data": "openai", # Fundamentals: openai, local - "news_data": "openai,google", # News: openai, google, local + "core_stock_apis": "alpha_vantage", # OHLCV data: alpha_vantage, yahoo_finance, local + "technical_indicators": "alpha_vantage", # Technical indicators: alpha_vantage, yahoo_finance, local + "fundamental_data": "alpha_vantage", # Fundamentals: alpha_vantage, openai, local + "news_data": "alpha_vantage", # News: alpha_vantage, openai, google, local }, # Tool-level configuration (takes precedence over category-level) "tool_vendors": {