453 lines
16 KiB
Python
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'
|
|
] |