TradingAgents/tradingagents/dataflows/indian_interface.py

453 lines
16 KiB
Python

"""
Indian Market Data Interface
Integration layer for Indian market data with the TradingAgents framework
"""
from typing import Annotated, Dict, Optional, List, Any
from datetime import datetime, timedelta
import pandas as pd
import logging
import os
import json
from .indian_market_utils import (
IndianMarketDataManager,
get_indian_market_data,
get_indian_fundamentals,
get_indian_quote
)
from .ticker_utils import (
format_indian_ticker,
validate_indian_ticker,
get_plain_symbol,
TickerManager
)
from .config import get_config
logger = logging.getLogger(__name__)
# Initialize ticker manager
ticker_manager = TickerManager()
def get_indian_market_data_interface(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
start_date: Annotated[str, "Start date in yyyy-mm-dd format"],
end_date: Annotated[str, "End date in yyyy-mm-dd format"],
exchange: Annotated[str, "Exchange: NSE or BSE"] = "NSE"
) -> str:
"""
Get Indian stock market data with multiple source fallbacks
Args:
symbol: Stock symbol (e.g., 'RELIANCE', 'TCS')
start_date: Start date in yyyy-mm-dd format
end_date: End date in yyyy-mm-dd format
exchange: Exchange (NSE or BSE)
Returns:
Formatted string with market data
"""
try:
# Validate dates
datetime.strptime(start_date, "%Y-%m-%d")
datetime.strptime(end_date, "%Y-%m-%d")
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol, exchange)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
# Get configuration
config = get_config()
# Get market data
result = get_indian_market_data(
symbol=symbol,
start_date=start_date,
end_date=end_date,
exchange=exchange,
config=config
)
return result
except ValueError as e:
error_msg = f"Date format error: {e}"
logger.error(error_msg)
return error_msg
except Exception as e:
error_msg = f"Error fetching market data for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_fundamentals_interface(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
exchange: Annotated[str, "Exchange: NSE or BSE"] = "NSE"
) -> str:
"""
Get Indian company fundamental data
Args:
symbol: Stock symbol (e.g., 'RELIANCE', 'TCS')
exchange: Exchange (NSE or BSE)
Returns:
Formatted string with fundamental data
"""
try:
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol, exchange)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
# Get configuration
config = get_config()
# Get fundamental data
result = get_indian_fundamentals(
symbol=symbol,
exchange=exchange,
config=config
)
return result
except Exception as e:
error_msg = f"Error fetching fundamentals for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_quote_interface(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
exchange: Annotated[str, "Exchange: NSE or BSE"] = "NSE"
) -> str:
"""
Get Indian real-time quote data
Args:
symbol: Stock symbol (e.g., 'RELIANCE', 'TCS')
exchange: Exchange (NSE or BSE)
Returns:
Formatted string with quote data
"""
try:
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol, exchange)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
# Get configuration
config = get_config()
# Get quote data
result = get_indian_quote(
symbol=symbol,
exchange=exchange,
config=config
)
return result
except Exception as e:
error_msg = f"Error fetching quote for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_technical_indicators(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
indicator: Annotated[str, "Technical indicator (e.g., rsi, macd, sma)"],
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"],
lookback_days: Annotated[int, "Number of days to look back"] = 30,
exchange: Annotated[str, "Exchange: NSE or BSE"] = "NSE"
) -> str:
"""
Get technical indicators for Indian stocks
Args:
symbol: Stock symbol
indicator: Technical indicator name
curr_date: Current date
lookback_days: Number of days to look back
exchange: Exchange
Returns:
Formatted string with indicator data
"""
try:
# Import stockstats here to avoid circular imports
from .stockstats_utils import StockstatsUtils
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol, exchange)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
# Calculate date range
end_date = datetime.strptime(curr_date, "%Y-%m-%d")
start_date = end_date - timedelta(days=lookback_days + 50) # Extra days for indicator calculation
# Get market data first
market_data = get_indian_market_data_interface(
symbol=symbol,
start_date=start_date.strftime("%Y-%m-%d"),
end_date=curr_date,
exchange=exchange
)
if "Error" in market_data or "No data" in market_data:
return f"Cannot calculate {indicator}: {market_data}"
# For now, return a placeholder - full integration with stockstats would need more work
result = f"# Technical Indicator: {indicator} for {ticker_info['formatted_ticker']}\n"
result += f"# Date: {curr_date}\n"
result += f"# Lookback period: {lookback_days} days\n\n"
result += f"Technical indicator calculation for {indicator} would be performed here.\n"
result += "This requires integration with the stockstats library using Indian market data.\n"
return result
except Exception as e:
error_msg = f"Error calculating {indicator} for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_news_interface(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"],
lookback_days: Annotated[int, "Number of days to look back"] = 7
) -> str:
"""
Get Indian company news from local sources
Args:
symbol: Stock symbol
curr_date: Current date
lookback_days: Number of days to look back
Returns:
Formatted string with news data
"""
try:
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
# Get company name for news search
plain_symbol = ticker_info["plain_symbol"]
# For now, return a placeholder for Indian news sources
result = f"# Indian News for {plain_symbol}\n"
result += f"# Date range: {(datetime.strptime(curr_date, '%Y-%m-%d') - timedelta(days=lookback_days)).strftime('%Y-%m-%d')} to {curr_date}\n\n"
# Placeholder news items (in production, these would come from actual Indian news APIs)
result += "## Recent News Headlines:\n\n"
result += f"### Company-specific news for {plain_symbol} would be fetched from:\n"
result += "- Economic Times\n"
result += "- Moneycontrol\n"
result += "- Business Standard\n"
result += "- NSE/BSE announcements\n"
result += "- Company investor relations\n\n"
result += "### Market and sector news would include:\n"
result += "- RBI policy announcements\n"
result += "- SEBI regulatory updates\n"
result += "- Sectoral developments\n"
result += "- FII/DII flow data\n"
result += "- Currency and commodity updates\n"
return result
except Exception as e:
error_msg = f"Error fetching news for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_sentiment_interface(
symbol: Annotated[str, "Indian stock symbol (e.g., RELIANCE, TCS)"],
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"],
lookback_days: Annotated[int, "Number of days to look back"] = 7
) -> str:
"""
Get Indian social media sentiment data
Args:
symbol: Stock symbol
curr_date: Current date
lookback_days: Number of days to look back
Returns:
Formatted string with sentiment data
"""
try:
# Process ticker
ticker_info = ticker_manager.process_ticker(symbol)
if not ticker_info["is_valid"]:
return f"Invalid ticker: {symbol}. Error: {ticker_info.get('error', 'Unknown error')}"
plain_symbol = ticker_info["plain_symbol"]
# For now, return a placeholder for Indian sentiment sources
result = f"# Indian Social Media Sentiment for {plain_symbol}\n"
result += f"# Date range: {(datetime.strptime(curr_date, '%Y-%m-%d') - timedelta(days=lookback_days)).strftime('%Y-%m-%d')} to {curr_date}\n\n"
result += "## Sentiment Analysis Sources:\n\n"
result += f"### Social Media Sentiment for {plain_symbol}:\n"
result += "- Twitter India discussions\n"
result += "- Indian stock forums (ValuePickr, etc.)\n"
result += "- Reddit India finance communities\n"
result += "- Telegram trading groups\n\n"
result += "### Institutional Sentiment Indicators:\n"
result += "- FII/DII buying/selling patterns\n"
result += "- Mutual fund holdings changes\n"
result += "- Analyst recommendations from Indian brokerages\n"
result += "- Retail investor participation metrics\n"
return result
except Exception as e:
error_msg = f"Error fetching sentiment for {symbol}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_sector_analysis(
sector: Annotated[str, "Sector name (e.g., banking, it, pharma)"],
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"]
) -> str:
"""
Get Indian sector analysis and performance
Args:
sector: Sector name
curr_date: Current date
Returns:
Formatted string with sector analysis
"""
try:
from tradingagents.indian_config import get_sector_stocks, INDIAN_SECTORS
# Get stocks in the sector
sector_stocks = get_sector_stocks(sector.lower())
if not sector_stocks:
available_sectors = list(INDIAN_SECTORS.keys())
return f"Sector '{sector}' not found. Available sectors: {', '.join(available_sectors)}"
result = f"# Indian {sector.title()} Sector Analysis\n"
result += f"# Date: {curr_date}\n\n"
result += f"## Key Stocks in {sector.title()} Sector:\n"
for stock in sector_stocks[:10]: # Limit to top 10
result += f"- {stock}\n"
result += f"\n## Sector Performance Metrics:\n"
result += "- Sectoral index performance vs Nifty 50\n"
result += "- Average P/E ratio for the sector\n"
result += "- FII/DII flows into sector stocks\n"
result += "- Government policy impact on sector\n"
result += "- Regulatory changes affecting the sector\n"
result += f"\n## Recent Sector Developments:\n"
result += f"Sector-specific news and developments for {sector} would be analyzed here.\n"
return result
except Exception as e:
error_msg = f"Error analyzing sector {sector}: {e}"
logger.error(error_msg)
return error_msg
def get_indian_market_overview(
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"]
) -> str:
"""
Get Indian market overview and indices performance
Args:
curr_date: Current date
Returns:
Formatted string with market overview
"""
try:
result = f"# Indian Market Overview\n"
result += f"# Date: {curr_date}\n\n"
result += "## Key Indices Performance:\n"
result += "- Nifty 50 (^NSEI)\n"
result += "- BSE Sensex (^BSESN)\n"
result += "- Nifty Bank (^CNXBANK)\n"
result += "- Nifty IT (^CNXIT)\n"
result += "- Nifty Auto (^CNXAUTO)\n"
result += "- Nifty Pharma (^CNXPHARMA)\n"
result += "\n## Market Breadth:\n"
result += "- Advances vs Declines\n"
result += "- New highs vs New lows\n"
result += "- Volume analysis\n"
result += "- Market volatility (India VIX)\n"
result += "\n## Key Market Drivers:\n"
result += "- RBI monetary policy stance\n"
result += "- Government fiscal policy\n"
result += "- Global market sentiment\n"
result += "- FII/DII flows\n"
result += "- Currency (USD-INR) movement\n"
result += "- Commodity prices impact\n"
result += "\n## Regulatory Updates:\n"
result += "- SEBI policy changes\n"
result += "- Tax policy impacts\n"
result += "- Corporate governance updates\n"
return result
except Exception as e:
error_msg = f"Error generating market overview: {e}"
logger.error(error_msg)
return error_msg
# Integration functions for existing framework compatibility
def get_YFin_data_indian(
symbol: Annotated[str, "Indian stock symbol"],
start_date: Annotated[str, "Start date in yyyy-mm-dd format"],
end_date: Annotated[str, "End date in yyyy-mm-dd format"]
) -> str:
"""
Compatibility wrapper for existing YFin interface
Automatically detects Indian tickers and routes to Indian data sources
"""
# Check if it's an Indian ticker
if validate_indian_ticker(symbol) or any(symbol.upper() in stocks for stocks in [
list(range(20)) # Placeholder - would check against known Indian stocks
]):
return get_indian_market_data_interface(symbol, start_date, end_date)
else:
# Fall back to original YFin implementation
from .interface import get_YFin_data
return get_YFin_data(symbol, start_date, end_date)
def get_fundamentals_indian(
symbol: Annotated[str, "Indian stock symbol"]
) -> str:
"""
Compatibility wrapper for fundamentals data
"""
return get_indian_fundamentals_interface(symbol)
# Export functions for use in agents
__all__ = [
'get_indian_market_data_interface',
'get_indian_fundamentals_interface',
'get_indian_quote_interface',
'get_indian_technical_indicators',
'get_indian_news_interface',
'get_indian_sentiment_interface',
'get_indian_sector_analysis',
'get_indian_market_overview',
'get_YFin_data_indian',
'get_fundamentals_indian'
]