Alpaca Integration**: Added `tradingagents/dataflows/alpaca.py` to support `get_stock_data` via Alpaca Data API v2.

This commit is contained in:
swj.premkumar 2026-01-10 04:32:46 -06:00
parent 3644e82f4e
commit 66c9807ed8
5 changed files with 137 additions and 2 deletions

View File

@ -21,6 +21,9 @@ All notable changes to the **TradingAgents** project will be documented in this
- **Import Errors**: Fixed `NameError: name 'tool' is not defined` by restoring `langchain_core` imports in data tools that were accidentally removed during Blindfire integration.
- **Payload Size Error**: Implemented input truncation (max 9000 chars) in `memory.py`.
- **Display Layer De-Anonymization**: Added `deanonymize_text` to `TickerAnonymizer` and patched `cli/main.py` to reverse-map "ASSET_XXX" to real company names in the final report, effectively resolving "[Company Name]" placeholders for the user while keeping the internal system blind.
- **Alpaca Integration**: Added `tradingagents/dataflows/alpaca.py` to support `get_stock_data` via Alpaca Data API v2. Registered as a vendor option in `interface.py` and `default_config.py`. Requires `ALPACA_API_KEY` and `ALPACA_API_SECRET` in `.env`.
### Changed
- **LLM Configuration**: Updated `tradingagents/default_config.py` and `cli/utils.py` to use valid Gemini model names (e.g., `gemini-1.5-flash`, `gemini-1.5-pro`) and `gemini-pro`.

View File

@ -0,0 +1,93 @@
import os
import requests
import pandas as pd
from typing import Optional
from datetime import datetime, timedelta
def get_stock_data(symbol: str, start_date: str = None, end_date: str = None) -> str:
"""
Fetch historical stock data (OHLCV) from Alpaca Data API v2.
Args:
symbol: Ticker symbol (e.g., "AAPL")
start_date: Start date (YYYY-MM-DD), defaults to 1 year ago
end_date: End date (YYYY-MM-DD), defaults to today
Returns:
String representation of the dataframe
"""
api_key = os.getenv("ALPACA_API_KEY")
secret_key = os.getenv("ALPACA_API_SECRET")
if not api_key or not secret_key:
raise ValueError("Error: ALPACA_API_KEY and ALPACA_API_SECRET environment variables must be set.")
# Default dates
if not end_date:
end_date = datetime.now().strftime("%Y-%m-%d")
if not start_date:
start_date = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d")
# Alpaca API URL (Data API v2)
url = f"https://data.alpaca.markets/v2/stocks/{symbol}/bars"
headers = {
"APCA-API-KEY-ID": api_key,
"APCA-API-SECRET-KEY": secret_key
}
params = {
"start": start_date,
"end": end_date,
"timeframe": "1Day",
"limit": 10000,
"adjustment": "all", # Split and dividend adjusted
"feed": "sip" # Use SIP feed if available, or 'iex' for free tier
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
# Check for free tier specific error regarding feed (422 or 403)
# 422: Invalid value (explicit feed req)
# 403: Forbidden (subscription level)
if (response.status_code in [403, 422]) and ("feed" in response.text or "subscription" in response.text):
# Retry with IEX feed (Free tier)
print(f"INFO: Retrying {symbol} with IEX feed (Free Tier)...")
params["feed"] = "iex"
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
raise ValueError(f"Alpaca API Error: {response.status_code} - {response.text}")
data = response.json()
if "bars" not in data or not data["bars"]:
return f"No data found for {symbol} on Alpaca between {start_date} and {end_date}."
# Parse data
# Alpaca returns: t (time), o, h, l, c, v, nw, n
bars = data["bars"]
df_data = []
for bar in bars:
df_data.append({
"Date": bar["t"].split("T")[0],
"Open": bar["o"],
"High": bar["h"],
"Low": bar["l"],
"Close": bar["c"],
"Volume": bar["v"]
})
df = pd.DataFrame(df_data)
# Format output string similar to yfinance output for consistency
result_str = f"Stock Data for {symbol} from {start_date} to {end_date}\n"
result_str += df.to_string(index=False)
return result_str
except Exception as e:
return f"Error fetching data from Alpaca for {symbol}: {str(e)}"

View File

@ -16,6 +16,7 @@ from .alpha_vantage import (
get_news as get_alpha_vantage_news
)
from .alpha_vantage_common import AlphaVantageRateLimitError
from .alpaca import get_stock_data as get_stock_alpaca
# Configuration and routing logic
from .config import get_config
@ -58,7 +59,8 @@ VENDOR_LIST = [
"local",
"yfinance",
"openai",
"google"
"google",
"alpaca"
]
# Mapping of methods to their vendor-specific implementations
@ -68,6 +70,7 @@ VENDOR_METHODS = {
"alpha_vantage": get_alpha_vantage_stock,
"yfinance": get_YFin_data_online,
"local": get_YFin_data,
"alpaca": get_stock_alpaca,
},
# technical_indicators
"get_indicators": {

View File

@ -20,7 +20,7 @@ DEFAULT_CONFIG = {
# Data vendor configuration
# Category-level configuration (default for all tools in category)
"data_vendors": {
"core_stock_apis": "yfinance", # Options: yfinance, alpha_vantage, local
"core_stock_apis": "yfinance", # Options: yfinance, alpha_vantage, local, alpaca
"technical_indicators": "yfinance", # Options: yfinance, alpha_vantage, local
"fundamental_data": "alpha_vantage", # Options: openai, alpha_vantage, local
"news_data": "alpha_vantage", # Options: openai, alpha_vantage, google, local

36
verify_alpaca.py Normal file
View File

@ -0,0 +1,36 @@
import os
from dotenv import load_dotenv
from tradingagents.dataflows.alpaca import get_stock_data
# Load environment variables
load_dotenv()
def verify_alpaca():
print("Locked & Loaded: Verifying Alpaca Data Connection...")
api_key = os.getenv("ALPACA_API_KEY")
secret_key = os.getenv("ALPACA_API_SECRET")
if not api_key or not secret_key:
print("❌ SKIPPING: ALPACA_API_KEY or ALPACA_API_SECRET not found in environment.")
print("Please add them to your .env file to enable Alpaca.")
return
try:
# Test with a known ticker
symbol = "AAPL"
print(f"Fetching data for {symbol}...")
data = get_stock_data(symbol)
if "Error" in data and not "No data found" in data:
print(f"❌ FAIL: {data}")
else:
print("✅ SUCCESS: Data retrieved successfully!")
rows = data.splitlines()[:5]
print(f"Preview:\n" + "\n".join(rows) + "...")
except Exception as e:
print(f"❌ FAIL: Exception occurred: {e}")
if __name__ == "__main__":
verify_alpaca()